Problemsetting¶
What is a problem?¶
A problem is actually a piece of software usually developed by contest organizers. Generally, it is an interactor, which executes user’s solutions, controls their interaction with the problem and finally generates game logs.
It’s a good idea to make the problem’s source code open, however, you may want to keep some files (e.g. hidden levels) secret until the end of your official contest. It’s convenient to develop problems in teams using git version control system, that’s why we have wide GitHub integration. However, it’s not a must.
You can take a look at these example problems if you would like to have some guidance.
Tron (TODO addreference)
Problem files are hosted on an AIForces server and can be uploaded directly,
using a web interface or fetched from a remote repository (GitHub, BitBucket,
etc). Only source files (and sometimes tests or statements) should be uploaded.
We recommend to build problem from sources on the server by creating a
build.sh script. It’s prohibited to upload executable files.
Typical toolstack for problemsetting is:
Python
HTML
CSS
JavaScript
LaTex
Bash
The system interacts with the problem using bash scripts, so it is possible to customize how Python and LaTex are called or use other tools. A plethora of default scripts is also available. The web visualizer (which is an important part of the problem) requires HTML, CSS and JS and has no default implementation.
Problem files are stored in a single folder (may be a git repo), and usually have the following structure:
- Before build:
├── bin ├── config ├── lib │ ├── olymp.sty │ ├── problem.tex │ └── statements.ftl ├── private ├── problem.yaml ├── public │ ├── change_log.txt ├── scripts │ ├── build.sh │ ├── check.sh │ └── validator.sh ├── solutions │ ├── ermolin.cpp │ ├── starkov.cpp │ └── useless.cpp ├── src │ ├── check.py │ ├── test_generator.py │ ├── tron.tex │ └── validator.cpp ├── statements │ ├── eng │ └── rus ├── tests └── visualizer ├── eng │ ├── visualizer-eng.css │ ├── visualizer-eng.html │ └── visualizer-eng.js └── rus ├── visualizer-rus.css ├── visualizer-rus.html └── visualizer-rus.js- After build:
├── bin │ └── validator ├── config │ └── tests.json ├── lib │ ├── olymp.sty │ ├── problem.tex │ └── statements.ftl ├── private │ ├── 01_notes.txt │ ├── 02_notes.txt │ ├── 03_notes.txt │ ├── 04_notes.txt │ ├── 05_notes.txt │ ├── 06_notes.txt │ ├── 07_notes.txt │ ├── 08_notes.txt │ ├── 09_notes.txt │ └── 10_notes.txt ├── problem.yaml ├── public │ └── change_log.txt ├── scripts │ ├── build.sh │ ├── check.sh │ └── validator.sh ├── solutions │ ├── ermolin.cpp │ ├── starkov.cpp │ └── useless.cpp ├── src │ ├── check.py │ ├── test_generator.py │ ├── tron.tex │ └── validator.cpp ├── statements │ ├── eng │ │ ├── statements-eng.html │ │ └── statements-eng.pdf │ └── rus │ ├── statements-rus.html │ └── statements-rus.pdf ├── tests │ ├── 01.txt │ ├── 02.txt │ ├── 03.txt │ ├── 04.txt │ ├── 05.txt │ ├── 06.txt │ ├── 07.txt │ ├── 08.txt │ ├── 09.txt │ └── 10.txt └── visualizer ├── eng │ ├── visualizer-eng.css │ ├── visualizer-eng.html │ └── visualizer-eng.js └── rus ├── visualizer-rus.css ├── visualizer-rus.html └── visualizer-rus.js
You can use your own folder structure (it’s not recommended) and describe it in
the problem.yaml.
Problem consists of the following parts:
Configuration
Tests (may be not needed for some problems)
Builder
Checker
Validator (recommended, but not mandatory)
Solutions (recommended, but not mandatory)
Statements
Visualizer
Let’s talk them over one by one.
General rules¶
All folder names starting with
__aiare reserved by the AIForces. Please use other folder names.All files must have different filenames (not paths, but filenames including the extension)
You can’t have binary files in the problem, unless they are created by
build.shAll filenames must only contain ASCII characters
All scripts will run in a firejail. Use only software you’re allowed. No internet access, no filesystem access outside the problem folder.
All the source files must not take more than 5 megabytes.
Use ISO-639-2 Codes for the Representation of Names of Languages.
Available software¶
All your scripts will run in a firejail, which means you can’t access any files outside your folder. It means that you can use only the software listed below.
Additionally, all the necessary binaries will be added to PATH for the
current session. You can use this software as usual:
List of software
gcc
python2.7
python3.8
pypy2.7
pypy3.8
java smth
pascal smth
haskell smth
latexpdf
latex
dvipdf
A LOT MORE
In all python venvs the following packages are installed
aitestlib
numpy
loguru
A LOT MORE
Configuration file¶
In the root directory of the problem folder, you must include a problem
configuration file named problem.yaml.
Below is an example of a correct configuration file:
# problem.yaml
# AIforces problem configuration file.
# See https://aiforces.readthedocs.io/en/latest/problemsetting.html#configuration-file for details
---
# Config file version
version: "1.0"
# Default settings for the problem
# They will be imported to the aiforces,
# but might be changed by the managers.
short-name: tic-tac-toe
name:
rus: Крестики-Нолики
eng: Tic Tac Toe
# Brief description
description:
rus: Просто классика
eng: The game may be a bit boring, but don't you like it after all?
# Per-move time limit
time-limit: 5 s
# RAM limit
memory-limit: 512 MB
# Players number. May be a single integer or range (e.g 2-4)
players: 2
# Author's and tester's solutions.
solutions:
ermolin:
name: Nikolay Ermolin.
file: solutions/ermolin.cpp
language: g++17
access: public
type: pretest
starkov:
name: Svyatoslav Starkov.
file: solutions/starkov.cpp
language: g++17
access: private
type: checker-verifier:TL
kekov:
name: Useless solution
file: solutions/useless.cpp
language: pypy3
access: private
# Relative paths to problem's files
# Test set configuration
# Might be created during build of the problem
tests_config: config/tests.json
# Scripts to build/clean the problem and checker script
scripts:
builder: scripts/doall.sh
validator: scripts/validate.sh
checker: scripts/check.sh
# Localized visualizers
visualizer:
rus:
html: "/visualizer/rus/visualizer-rus.html"
css: "/visualizer/rus/visualizer-rus.css"
js: "/visualizer/rus/visualizer-rus.js"
eng:
html: "/visualizer/eng/visualizer-eng.html"
css: "/visualizer/eng/visualizer-eng.css"
js: "/visualizer/eng/visualizer-eng.js"
# Localized statements
statements:
rus:
pdf: "/statements/rus/statements-rus.pdf"
html: "/statements/rus/statements-rus.html"
eng:
pdf: "/statements/eng/statements-eng.pdf"
html: "/statements/eng/statements-eng.html"
# Other files you want to share with users.
public_files:
- public/instruction.txt
- public/change.log
...
Supported settings¶
Note
The presence of any key that isn’t documented here will make the build fail. This is to avoid typos and provide feedback on invalid configurations.
version¶
Required: true
Version of the configuration file. You’re currently reading about 1.0
Warning
Please, put the version into quotes. Otherwise, YAML may mark it as a floating point number.
- Example
version: "1.0"
short-name¶
Required: true
Short name of the problem (not the displayname), matches ^[a-zA-Z0-9_-=+.,!]{4,20}$.
Example
short-name: tic-tac-toe
name¶
Required: false
Display name of the problem given in all needed languages.
- Example
name: rus: Крестики-Нолики eng: Tic Tac Toe
description¶
Required: false
Suggested brief description of the problem (localized).
- Example
description: rus: Просто классика eng: The game may be a bit boring, but don't you like it after all?
time-limit¶
Required: false
Suggested per-move time limit for the problem. You can use following units:
ms - millisecond (1/1000 of a second)
s - second
Value can’t be more than 1 minute.
- Example
time-limit: 5 s
memory-limit¶
Required: false
Suggested per-move memory limit for the problem. You can use following multiples:
B for bytes
kB for kilobytes
KiB for kibibytes
MB for megabytes
MiB for mebibyte
GB for gigabyte
GiB for gibibyte
Value can’t exceed 1 GiB.
- Example
memory-limit: 512 MB
players¶
Required: true
Number of players which compete together. May be a single integer or a range.
- Example
players: 2players: 2-4
solutions¶
Required: false
Describes author’s and tester’s solutions.
accessmay be private, protected or public.
languageis one of the supported programming languages.You may set the
typeof the solution topretestorchecker-verifier:[VERDICT], where[VERDICT]is one of system verdicts. If you omit this field, the solution will not serve any purpose, but still will be saved on disk.Read more about Solutions
- Example
# Authors and testers solutions. solutions: ermolin: name: Nikolay Ermolin. file: solutions/ermolin.cpp language: g++17 access: public type: pretest starkov: name: Svyatoslav Starkov. file: solutions/starkov.cpp language: g++17 access: private type: checker-verifier:TL kekov: name: Useless solution file: solutions/useless.cpp language: pypy3 access: private
tests_config¶
Required: true
JSON file which stores the test configuration. May be created by the
build.shscript.
- Example
tests_config: config/tests.json
scripts¶
Problem script files.
Builder script compiles the task into a ready state. Validator script reads a test file and checks it for validity. Checker script starts and runs challenges and produces logs.
- builder
Required: false
- validator
Required: false
- checker
Required: true
- Example
scripts: builder: scripts/doall.sh validator: scripts/validate.sh checker: scripts/check.sh
visualizer¶
Required: true
Visualizer web page files, localized for several languages.
- Example
visualizer: rus: html: "/visualizer/rus/visualizer-rus.html" css: "/visualizer/rus/visualizer-rus.css" js: "/visualizer/rus/visualizer-rus.js" eng: html: "/visualizer/eng/visualizer-eng.html" css: "/visualizer/eng/visualizer-eng.css" js: "/visualizer/eng/visualizer-eng.js"
statements¶
Required: true
Problem statements in different formats and different languages.
- Example
rus: pdf: "/statements/rus/statements-rus.pdf" html: "/statements/rus/statements-rus.html" eng: pdf: "/statements/eng/statements-eng.pdf" html: "/statements/eng/statements-eng.html"
public_files¶
Required: false
Any other files that you want to share with the participants.
- Example
public_files: - public/instruction.txt - public/change.log
Tests¶
One challenge configuration is called a Test. It can be, for example, one level of the game. If you need to prepare files describing the tests, you can do it while building or upload them together with the problem.
What you must create is a test configuration file and add its path to the problem config. This file, however, may be generated by the Builder. This file looks like the following JSON:
[
{
"id": 0,
"name": "Mega Level 1",
"file": "tests/01",
"public-description": "First and most simple test in the testset",
"hidden-description": "The solution is quite simple, just ..."
}
{
"id": 1,
}
]
Actually, you may omit all keys except the id. If your problem does not have
different levels, you can create only one test.
Scripts¶
The system is interacting with your problem via bash scripts so you can run another scripting language in it (e.g. Python). All arguments are passed to the script as JSON strings through the env vars.
File descriptors for I/O are inherited from the parent, their integer values are also passed through env vars.
Your stdout/stderr will be saved for internal use.
Builder¶
The builder script produces end files from sources. It usually includes a:
Compiling visualizer
Compiling checker, test_generator, validator
Generating tests and test config
Current problem settings are presented as JSON in the AI_PROBLEM_SETTINGS
env variable the same way they are described in problem.yaml.
{
"short-name": "tic-tac-toe",
"name": {
"rus": "Крестики-Нолики",
"eng": "Tic Tac Toe"
},
"description": {
"rus": "Просто классика",
"eng": "The game may be a bit boring, but don't you like it after all?"
},
"time-limit": "5 s",
"memory-limit": "512 MB",
"players": "2"
}
Any builder logs written to stderr will be saved for internal use.
Checker¶
The checker is the script that governs players and their interaction. It has the following interface:
Arguments are provided in the AI_CHECKER_ARGS env variable as JSON
- players_cmds
Pre-made bash commands to start solutions
- players_files
The solutions binary files (needed for firejail)
- test_id
Current test id
- test_description_fd
File descriptor integer value for the test file (if such was provided)
- time_limit
Per move time limit in milliseconds
- memory_limit
RAM limit in bytes.
- result_log_fd
File descriptor integer value to write result_log JSON
- game_log_fd
File descriptor integer value to write game_log file
- streams_log_fd
File descriptor integer value to write interaction logs
{
"players_cmds": [
"python /path/to/file.py",
"/path/to/exec"
],
"players_files": [
"/path/to/file.py",
"/path/to/exec"
],
"test_id": 1,
"test_description_fd": 3,
"time_limit": 1000,
"memory_limit": 536870912,
"result_log_fd": 4,
"game_log_fd": 5,
"streams_log_fd": 6
}
Any checker logs written to stderr will be saved for internal use.
Stream logs should have the following format, integer keys represent time moments (ticks):
[
{
"stdin": {
"0": "Stdin",
"3": "Followed stdin given after 3 tick."
},
"stdout": {
"0": "First response",
"3": "Last response"
},
"stderr": {
"0": "My debug output",
"3": "My last debug output"
}
},
{
"..." : "Same for all other players"
}
]
Result logs should have the following format
[
{
"verdict": "OK",
"score": 500,
"comment": "solution worked OK"
},
{
"verdict": "TL",
"score": 200,
"comment": "solution experienced TLE on tick 678."
}
{
"..." : "Same for all other players"
}
]
Game logs are designed by you, so make sure they are constructed in a way, what would be easy for a visualizer to process.
Validator¶
A validator is a script which reads test files from stdin and checks them for
validity. Any logs written to stderr will be saved for internal use. If the test
happens to be incorrect, the validator must finish with a non-zero code.
Validation is performed automatically by the problem-verifier.
Solutions¶
Solutions are created by problem authors and testers. They serve 3 purposes:
Show examples of solutions to the participants
Verify that the checker works correctly
Pretest the submissions
Solution access modifiers are supported. Solutions can be either public, private or protected.
Public solutions are used as example solutions for participants
Protected solutions can be played against, but the source code is kept private
Private solutions can’t be interacted with directly
Solutions marked as pretests must finish with the OK verdict. They are
used as opponents for the participant solutions on pretests. The only aim of a
pretest is to warn participants in case their solution behaves badly. Bear in
mind that it’s a good idea to make pretests public or at least protected, so
that participants could see why their solution fails the pretests.
When you create a checker verifier, design it in such a way, that it would get the same verdict with any opponent and test number. Use this expected verdict in the solution configuration.
Also, all solutions used for pretests are used as checker verifiers and are
expected to have OK verdicts. You don’t have to add them to the list
explicitly.
Statements¶
Statements are usually written in LaTex and compiled into several different
formats (like pdf or html) for the sake of convenience. You have to compile
separate statement files for each language. They should be compiled by
build.sh or by you before the upload.
Visualizer¶
A visualizer is a webpage which uses the Challenge API (TODO Addreference) to
access logs of a challenge and visualize the game in a convenient way. It will
be embedded in a webpage using an iframe.