=Paper= {{Paper |id=Vol-2832/paper14 |storemode=property |title=Development of an automated system for conducting, checking and evaluating programming competitions |pdfUrl=https://ceur-ws.org/Vol-2832/paper14.pdf |volume=Vol-2832 |authors=Bohdan V. Hrebeniuk,Olena H. Rybalchenko }} ==Development of an automated system for conducting, checking and evaluating programming competitions== https://ceur-ws.org/Vol-2832/paper14.pdf
Development of an automated system for
conducting, checking and evaluating programming
competitions
Bohdan V. Hrebeniuk, Olena H. Rybalchenko
Kryvyi National University, 11 Vitalii Matusevych Str., Kryvyi Rih, 50027, Ukraine


                                      Abstract
                                      The paper analyzes the existing platforms for conducting programming contests. Possible approaches
                                      are analyzed for creating isolated environments and running participants’ solutions, advantages and
                                      disadvantages of both approaches are highlighted. Requirements for the user interface are defined that
                                      must provide quick and convenient work in the system; the system was planned and developed. It was
                                      concluded that designed system has a potential for conducting contests and further development.

                                      Keywords
                                      competiteve programming, isolated environment, virtualization, containerization, REST




1. Introduction
Competitive programming has been maintaining a dynamic development rate for several decades.
Year by year, more and more teams take part in local, regional and international contests, there-
fore making the needs of both contest organizers and participants grow.
   Kryvyi Rih National University supports the development of competitive programming –
local contests are held, and the university annually hosts the qualification phase of the inter-
national student contest under the aegis of ACM/ICPC. To maintain the level of students and
teachers competence, it is necessary to have our own flexible system, since existing analogues
have certain disadvantages.
   The aim of the work is to study and analyze the process of creating isolated environments,
design and develop a flexible system for conducting, checking and evaluating programming
contests.




CS&SE@SW 2020: 3rd Workshop for Young Scientists in Computer Science & Software Engineering, November 27,
2020, Kryvyi Rih, Ukraine
" bogdan020699@gmail.com (B.V. Hrebeniuk); rybalchenko@knu.edu.ua (O.H. Rybalchenko)
 0000-0002-0423-8476 (B.V. Hrebeniuk); 0000-0001-8691-5401 (O.H. Rybalchenko)
                                    © 2020 Copyright for this paper by its authors.
                                    Use permitted under Creative Commons License Attribution 4.0 International (CC BY 4.0).
 CEUR
 Workshop
 Proceedings
               http://ceur-ws.org
               ISSN 1613-0073       CEUR Workshop Proceedings (CEUR-WS.org)
2. Development of a system for conducting, checking and
   evaluating programming competitions
2.1. Analysis of existing systems
One of the first systems with automatic checking of tasks is UVa Online Judge, an online system
of the University of Valladolid with an installed task archive. The archive is constantly being
updated, but it is impossible to create tasks yourself using this system – any system updates
(uploading new tasks, supporting new programming languages, changing the rules for creating
a rating) are possible only with permission and active interaction with developers. Additionally,
downloading the software and installing it for use are prohibited due to the product license,
because the system uses the “SaaS” (Software as a Service) model [1]. Under this model, the
software is not installed on users’ computers, but on the provider’s servers, and the user does
not have any access to the system. This disadvantage makes the system unsuitable for long-
term contests due to the fact that the terms of the service provider can change at any moment
and the user (in our case, the organizer of the contest) will not be able to do anything [2].
   One of the most successful systems in history was PCSM2, which was formed by combining
the APPES and PCMS systems and is characterized by the flexibility of the internal structure.
Software units have low connectivity due to the fact that they rely on high-level abstractions
of each other. This makes the PCSM2 system easy to upgrade on a programming level. But
this flexibility has made it difficult to customize the server, as most of the business logic is
described by configuration files. Some parts of the system are still being developed, so to set
them up, you need to add and connect specialized modules that only the authors of the system
can perform. Another serious drawback is that the PCSM2 server supports only the Windows
operating system, which makes it difficult to run the system on servers that use Linux [3].
   The qualification phases of the ACM/ICPC contests are managed by the ejudge system [4],
which is significantly different from PCSM2. The system was created using the C programming
language, it supports only the Linux operating system, has a web interface for administration
and detailed documentation, but also has a number of disadvantages. The most important of
these is the inefficient allocation of resources between the system and processes with user’s
solutions. As a result, incorrect verdicts may occur due to exceeding the time limit. The system
also doesn’t support scaling out — you can’t connect a new machine to an existing one. The
only way to improve parallel code execution is to increase the number of processes on the
server, which can lead to competition for process access to RAM. An equally important factor
is linking the system to the operating system. This dependency makes it impossible to deploy
the project on servers that do not support Linux.

2.2. Analysis of approaches of running participants’ code
Automation of contest processes has become a necessary condition for such events, because
with the increase in the number of teams and tasks, the required amount of time for receiving
solutions, checking them, and summing up results has also significantly increased. And, al-
though such systems have existed for decades, with the introduction of new technologies, new
opportunities for their creation appear.




                                              105
Figure 1: Component hierarchy for virtualization (a) and containerization (b) approaches


   To protect such systems from malicious user code actions, the common practice is to run the
code in some isolated environment. This makes the system protected from malicious solutions
that may attempt to interfere with the evaluation process [5].
   One potential solution to this problem can be virtual machines that emulate a hardware
server. In this event, all components of a real computer are virtualized – I/O devices, hard
disk, ports, etc., followed by the installation of the operating system. Although such system is
isolated from the host, using virtual machines means running the entire operating system and
allocating resources to emulate virtualization, which often negatively affects the performance
of the platform.
   An alternative way to achieve process isolation is containerization, in which the source code
of the program is encapsulated along with dependencies to run on any infrastructure in an
isolated environment [6]. Unlike virtual machines, containers allow you to run software in a
single process, isolated from each other, on a single host, using the resources of an existing
operating system. Since containers are only a part of the operating system, they are sometimes
less flexible to use, for example, they can only run programs that are compatible with the
current system [7].
   Despite mentioned limitations, containers are widely used to create an isolated process en-
vironment. One of the most well-known examples of such containers is “chroot jail”. The idea
is to copy (or create) links to the system files needed to run processes. After that, restrictions
are set for the created processes — the root directory of the system is changed to the root di-
rectory of the environment. Since processes cannot refer to paths outside the modified root,
they cannot perform malicious operations in these locations [8]. Containerization is the best
option for the system being created, because containers allow you to run programs in an iso-
lated environment with restrictions on system resources and at the same time work only in
one process of the operating system.




                                                106
2.3. Docker usage
One of the tools for working with containerization is Docker, which allows you to create an
isolated space for a process using the Linux kernel namespace. Each container creates its own
spaces with unique access, including the following:

    • PID namespace (for process isolation);

    • NET namespace (for managing network interfaces);

    • IPC namespace (for managing access to IPC resources);

    • MNT namespace (for managing file system mounting points), etc.

   Docker also uses kernel control groups to allocate resources and isolate them. These groups
set limits for the program for certain resources, including:

    • memory control groups;

    • CPU control groups;

    • control groups of devices, and so on.

  The containers must be used in our platform for the next purposes:

    • compiling the user’s code;

    • running the user’s code.

   Therefore, it is necessary to have two containers for each programming language in the sys-
tem – one container compiles the code, the second executes it. Creating containers is achieved
by running images, which in turn encapsulate all the components and dependencies needed to
run the application. Images are created using Dockerfile - text files with instructions created
according to the rules of a Dockerfile syntax.
   For example, let’s take a DockerfileBase file for creating images for the Python programming
language:

FROM python:3.7.5-slim
COPY compile_py.py .

   This file describes the image that will be based on the python:3.7.5-slim image, the official
Python version 3.7.5 image, the slim build. Copy the script to the virtual address space com-
pile.py, which is responsible for compiling the user’s code. The contents of the file are shown
below:

import pathlib
import py_compile
import sys




                                               107
if len(sys.argv) != 3:
    raise ValueError(’Wrong amount of arguments!’)
_, input_file, output_file = sys.argv
input_file_path = pathlib.Path(input_file)
if not input_file_path.exists():
    raise ValueError(’There is no user file!’)
py_compile.compile(input_file, output_file, doraise=True)

  The base image (python-base) is created before the platform starts working. Based on this
image, we create two new images – DockerfileCompiler and DockerfileRunner for compiling
and running code respectively. The content of DockerfileCompiler is shown below:

FROM python-base
COPY ./code /code
CMD ["python", "compile_py.py", "./code/main.py", "./code-compiled/main.pyc"]

  The content of the DockerfileRunner file is as follows:

FROM python-base
COPY ./code-compiled /code-compiled
CMD ["python", "/code-compiled/main.pyc"]

   For each new user solution, a pair of such images will be created. An image based on Dock-
erfileCompiler copies the code directory to its virtual address space and runs the script com-
pile.py, which compiles the source code to byte-code. Due to the presence of volume (which
must be configured before starting the container), the contents of the directory will remain
available to other processes, in particular for the image created from the DockerfileRunner file,
on the basis of which the container will execute the compiled code.
   To simplify interaction with the Docker Engine API, which is an interface in the form of an
HTTP client for other applications, a facade is implemented that is a wrapper over the client.
Its main task is to define the interface of a real client by transferring the necessary methods to
a single class:

    • build-creates an image based on a specific Docker file and assigns it a name;

    • run-starts a container with a specific configuration based on the specified image and
      returns the result of its operation;

    • remove-deletes a specific image.

  This class is used in “workers” – components that encapsulate the logic of working with
containers and images for a given set of programming languages. Workers are waiting for the
user’s solution, which is used to create a context for running code, namely:

    • creating a directory with further configuring volumes;




                                               108
    • building a “Compiler” – an image and creating a one-time container based on it;

    • building a “Runner” image based on a compiled solution.

   To avoid creating new “Runner” images to run the solution with different tests, input data
is passed in arguments to run the container. After testing the solution, the docker context is
destroyed (images and containers are deleted).
   After implementing a software component to run user solutions, the next step is to create a
system that meets business requirements.

2.4. System’s architecture
The client-server architecture was chosen as the basis for the created software, so the selection
of frameworks for developing both the backend and the frontend turned out to be an important
issue.
   The Python programming language (specifically version 3.7.4) was used to develop the back-
end. Although Django and Flask are the leading frameworks for creating Python web applica-
tions, a relatively new aiohttp framework was chosen to develop our system. The framework
uses new features of the language, namely support for asynchronous programming at the syn-
tax level [9]. The main concept of this paradigm is the use of deferred calls, which violate the
usual order of instructions execution. At the same time, the resource usage model significantly
differs from the model using processes and threads – there is only one thread in an asyn-
chronous application, and new requests are served using asynchronous I/O primitives of the
operating system – as a result, a small amount of resources is used for allocating new connec-
tion. Although the framework was created relatively recently (the first official “stable” release
dates back to September 16, 2016), 3 major updates were released in this short period of time,
and the framework repository on GitHub became the “main” one in AIO-libs, a community
of programmers who develop Python packages and modules for asynchronous programming
[10].
   The choice of such a framework affected the choice of database, because there is only one
adapter written for Python that supports asynchronous database access - that is psycopg2, a
connector for PostgreSQL. Based on this adapter, the aiopg library package was created, which
implements a DBAPI interface with asynchronous syntax support and is responsible for sup-
porting SQLAlchemy, a library for working with relational databases using ORM Technology
[11].
   It is worth noting that not only PostgreSQL implements support for asynchronous opera-
tions. The MySQL DBMS also has it, but there is no official client for the Python programming
language that would support this mode, so the PostgreSQL was chosen [12].
   The React framework was chosen for the frontend. The programming code created using
this framework is modular, i.e. it consists of loosely coupled components that can be reused
in several places at once. Thanks to the virtual DOM, applications created using React run
much faster than alternative frameworks (for example, Angular). The Redux library, a plat-
form with unidirectional data flow and centralized data storage, was used to manage the appli-
cation status. These features of the platform allow you to implement a predictable and easy-
to-understand system for moving an application from one state to another.



                                              109
  REST was chosen as the architectural style of interaction between the backend and the fron-
tend. Some features of this architecture are described below [13]:

    • client-server architecture – separating the interface from business logic simplifies the
      portability of the user interface to different platforms and increases scalability by sim-
      plifying server components;

    • state absence – each request to the server must contain all the necessary information
      for its successful execution, i.e. the server does not store any context between different
      requests (for example, in the form of sessions), and all information needed for the user’s
      “session” is stored on the client’s side (for example, an access token);

    • uniform interface – following REST involves creating a “virtual” resource system, in
      which each of the resources has universal methods for working with it, including creat-
      ing, reading, updating, and deleting. However, the true location of the entity (for exam-
      ple, in a database) may be located in a different virtual space.

  The functional diagram shows a graph with transitions from one state of the program to
another. When initializing the system, connections to the Docker Engine API are created;
connecting to the database and starting the web server. After that, the system waits for a
request from the user.
  Each request to the system’s API is accompanied by user authorization – it checks whether
the user can have access to the specified resource. If authorization fails, the user is sent a
message describing the cause of the error. In other case, the request goes further through the
system.
  There are two main types of API requests:

    • a “CRUD request” is a request for manipulating an entity that requires interaction with
      the database;

    • a code execution request is a request to execute code from the user in order to get the
      result of the program. The request requires interaction with the Docker Engine API.

2.5. User interface and user experience
One of the necessary requirements for the system is the speed and convenience of creating and
conducting competitions, so certain restrictions were set on the system interface for effective
user experience.
   The most important of them is that the user should not be focusing on the elements that are
not related to the context of the current resource - it is necessary to create a virtual space that
does not allow the user to move randomly around the system, but on the contrary, suggests
the right actions to achieve the goal.
   For example, the pages “view available competitions” and “create a new competition” belong
to the same type of system resources - “competitions”, so manipulations on this resource are
“close” to each other in the virtual space of the system.




                                               110
Figure 2: Functional diagram of the system


   When viewing a specific competition, the user has more features, so the header has signifi-
cantly more elements – the virtual space has expanded significantly at this stage, and links to
loosely linked pages (creating a new competition) are not displayed.
   The user experience of the system is based on building clear sequences of actions that lead
to resources in one most intuitive way. This design allows you to focus the user’s attention on
performing the planned action, instead of confusing them with oversaturated pages and long
transitions.


3. Conclusions
Research on technologies for creating isolated environments has shown that containerization,
despite a number of disadvantages, is well suited for running processes isolated from each
other. The use of virtual machines, on the contrary, could lead to irrational use of system
resources, so it was decided to use containers as components for running user code.



                                             111
Figure 3: Contest list view page


  After the development of this component, a system for holding contests was created, which
can be used by both participants and contests organizers. A scheme for a relational database is
designed for the system. The software is designed to emulate the client/server architecture, us-
ing Python and JavaScript. The system has passed several tests, which have shown an effective
system operation and a great potential for further development.


References
 [1] O. M. Markova, S. O. Semerikov, A. M. Striuk, The cloud technologies of learning: Origin,
     Information Technologies and Learning Tools 46 (2015) 29–44. URL: https://journal.iitta.
     gov.ua/index.php/itlt/article/view/1234. doi:10.33407/itlt.v46i2.1234.
 [2] D. Irtegov, T. Nesterenko, T. Churina, Systems for automated evaluation of programming
     tasks: Development, use and perspectives, Vestnik NSU. Series: Information Technologies
     17 (2019) 61–73. doi:10.25205/1818-7900-2019-17-2-61-7.
 [3] D. Irtegov, T. Nesterenko, T. Churina, Development of automated evaluation systems
     for programming tasks, System Informatics Journal (2017) 91–116. doi:10.31144/si.
     2307-6410.2017.n11.




                                              112
Figure 4: Contest creation page


 [4] ejudge system, 2020. URL: https://ejudge.ru/wiki/index.php/%D0%A1%D0%B8%D1%81%
     D1%82%D0%B5%D0%BC%D0%B0_ejudge.
 [5] Selected papers ofthe International Conference joint withthe XXII International Olympiad
     in InformaticsWaterloo, Canada, August 14–21, 2010, volume 4, Institute of Mathematics
     and Informatics, Vilnius, Lithuania, 2010. URL: https://ioinformatics.org/files/volume4.
     pdf.
 [6] IBM Cloud Education, Containerization explained, 2019. URL: https://www.ibm.com/
     cloud/learn/containerization.
 [7] J. Turnbull, The Docker Book: Containerization Is the New Virtualization, 2014. URL:
     https://dockerbook.com/.
 [8] chroot “jail” - what is it and how do I use it?, 2010. URL: https://unix.stackexchange.com/
     questions/105/chroot-jail-what-is-it-and-how-do-i-use-it.
 [9] Y. Selivanov, PEP 492 – Coroutines with async and await syntax, 2015. URL: https://www.



                                              113
Figure 5: Contest resources overview page


     python.org/dev/peps/pep-0492/.
[10] aio-libs: The set of asyncio-based libraries built with high quality, 2021. URL: https://
     github.com/aio-libs.
[11] A. Svetlov, A. Firsov, Welcome to AIOPG, 2020. URL: https://aiopg.readthedocs.io/en/
     stable/.
[12] Is       there      an      asynchronous        Python        client      for    MySQL
     with        pooling      features?,       2015.       URL:        https://www.quora.com/
     Is-there-an-asynchronous-Python-client-for-MySQL-with-pooling-features.
[13] restfulapi.net, What is REST, 2020. URL: https://restfulapi.net/.




                                             114