Что такое ada-judge?
ada-judge – это принципиально новая платформа для проведения соревнований по программированию, написанная на языке Rust. Она не зависит от сторонних сервисов, таких как Codeforces Polygon, и является полностью самостоятельной. Основной функционал ada-judge включает:
- Создание контестов в формате IOI
- Создание задач, в том числе интерактивных и с двойным запуском
- Тестирование посылок на языках Rust, C++, C, Go, Python и FreePascal с изолированным запуском решений
- Администрирование контестов, задач и пользователей
Развёртывание
Для того, чтобы развернуть ada-judge на своём сервере, необходимы docker и git.
- Склонируйте основной
git-репозиторийada-judge:
Или зеркало (оно обновляется раз в час):git clone https://codeberg.org/oneprog/ada-judgegit clone https://github.com/OneProgGit/ada-judge - Перейдите в директорию со склонированным репозиторием и создайте там конфигурационный файл
.env, заполните его в следующем формате:# Данные PostgreSQL POSTGRES_USER= POSTGRES_PASSWORD= POSTGRES_DB= # Данные Redis REDIS_PASSWORD= REDIS_USER= REDIS_USER_PASSWORD= # Параметры JWT JWT_SECRET= JWT_EXP_HOURS= # Название контейнера песочницы SANDBOX_IMAGE=ada-judge-sandbox # Количество параллельных инвокеров WORKERS_COUNT= # Url PostgreSQL (для разработки) DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@127.0.0.1:1111/${POSTGRES_DB} - Создайте директорию
submissions_envs, где будут храниться посылки. - Соберите и запустите
ada-judge:docker-compose build; docker-compose up -d
aj-app
aj-app – это нативное GUI-приложение для ada-judge, доступное для Linux, Mac и Windows. Есть два способа его установки:
- Готовые бинарники. Самый простой способ, но недоступны некоторые платформы, такие как Windows/Linux ARM.
- Через
cargo. В этом случае компиляция будет происходить на вашем устройстве. Для этого способа необходим тулчейнRustверсии 1.98.0 и новее. Выполните в терминале команду:cargo install aj-app
aj-cli
aj-cli – это терминальное приложение, созданное для упрощения создания задач для ada-judge. Есть два способа его установки:
- Готовые бинарники. Самый простой способ, но недоступны некоторые платформы, такие как Windows/Linux ARM, и доступны версии только начиная с 0.4.0.
- Через
cargo. В этом случае компиляция будет происходить на вашем устройстве. Для этого способа необходим тулчейнRustверсии 1.98.0 и новее. Выполните в терминале команду:cargo install aj-cli
Регистрация
Самый простой способ создать аккаунт ada-judge – использовать aj-app.
-
Откройте его:
aj-app -
Нажмите :
-
Заполните все поля и снова нажмите :
-
Начиная с версии 0.7.0, первый пользователь автоматически получает права владельца. Чтобы получить права владельца в версии 0.6.6 и ниже, необходимо, находясь в директории с репозиторием, выполнить:
> docker-compose exec -it postgres bash > psql -U <пользователь PostgreSQL> -d <база данных PostgreSQL> > update users set admin_level='owner' where id = <ваш id>; UPDATE 1
Вход
- На приветственной странице нажмите :
2. Заполните все поля и снова нажмите :
Интерфейс домашней страницы
Интерфейс домашней страницы выглядит следующим образом:
Некоторые кнопки доступны только админам.
Интерфейс контестов
Интерфейс контестов выглядит следующим образом:
Некоторые кнопки доступны только админам контеста.
Создание контестов
Для того, чтобы создать контест, нужно:
-
Быть админом
-
Нажать на кнопку на главной странице:
-
В появившемся окне заполнить нужные поля, отметить нужные чекбоксы и cнова нажать :
Интерфейс задач
Интерфейс задач выглядит следующим образом:
Создание задач
ada-judge позволяет создавать задачи удобно и быстро, сочетая aj-cli и aj-app.
Шаги с CLI
- Перейдите в директорию, где будут лежать ваши задачи
- Создайте стандартную задачу:
Либо используйте шаблон:aj-cli problem . prepare <название задачи>aj-cli problem . prepare -t <номер шаблона> <название задачи> - Типичная структура задачи такая:
├── checker.rs ├── config.toml └── tests ├── <тест> │ ├── in # входные данные теста │ └── out # выходные данные теста - Отредактируйте
config.tomlв следующем формате:name_ru = "<название задачи на русском>" name_en = "<название задачи на английском>" type = "<тип задачи>" # default -- обычная задача, interactive -- интерактивная, run_twice -- с двойным запуском, run_twice_interactive -- интерактивная с двойным запуском, run_twice_first_interactive -- с двойным запуском, причём первый из них -- интерактивный, run_twice_second_interactive -- с двойным запуском, причём второй из них -- интерактивный testing_type = "<тип тестирования задачи" # ioi -- формат IOI (подгруппы на баллы), ioi_merge_subgroups -- формат IOI со слиянием подгрупп owner_id = "<ваш id>" contest_id = <id контеста> index = <индекс задачи в контесте, начиная с 0> time_limit_ms = <лимит по времени, мс> memory_limit_mb = <лимит по памяти, МБ> checker_path = "<путь до исходника чекера>" checker_lang = "<язык чекера>" # c/cpp/rust/go/python/free_pascal tests_path = "<путь до директории с тестами>" # Подгруппы [[subgroups]] type = "<тип подгруппы>" # sample -- примеры, main -- основная tests = [<тесты подгруппы>] score = <баллы за подгруппу> # score_per_test = <баллы за каждый тест подгруппы> depends_on = [<индексы подгрупп, прохождение которых требуется для тестирование на этой подгруппе, начиная с 0 в порядке их следования в файле конфига>] - Можно добавить тесты к задаче:
aj-cli problem <путь к задаче> insert-tests <начиная с> <заканчивая на, включительно> - Можно протестировать решение на тестах:
aj-cli problem <путь к задаче> run <путь к бинарнику решения> <начиная с> <заканчивая на, включительно>
Как писать чекеры
Написание кастомного чекера необходимо для многих задач.
Вердикты
- Если чекер возвращает 0, то считается, что вердикт
Ок - Если чекер возвращает 1, то считается, что вердикт
Неправильный ответ - Если чекер возвращает 2, то считается, что вердикт
Неправильный формат вывода - Если чекер возвращает какой-либо другой код, то считается, что вердикт
Баг
Аргументы командной строки
Чекеру передаются аргументы командной строки в следующем порядке:
Обычные задачи
- Путь к тесту
- Путь к ответу участника
- Путь к ответу жюри
Интерактивные задачи
- Путь к ответу участника
- Путь к ответу чекера
- Путь к тесту
Задачи с двойным запуском
- Путь к тесту
- Путь к ответу участника
- Путь к ответу жюри
- Стадия
Задачи с двойным запуском с какими-то из них интерактивными
- Путь к ответу участника
- Путь к ответу чекера
- Путь к промежуточному ответу чекера (ответу между стадиями)
- Путь к тесту
- Стадия
Стадии
Задачи с двойным запуском
- Стадия
0– подготовка теста для первого запуска - Стадия
1– проверка ответа участника на первом запуске и подготовка теста для второго запуска - Стадия
2– проверка ответа участника на втором запуске
Интерактивные задачи с двойным запуском
- Стадия
0– первое интерактивное взаимодействие - Стадия
1– второе интерактивное взаимодействие
Задачи с двойным запуском, причём первый из них – интерактивный
- Стадия
0– интерактивное взаимодействие - Стадия
1– проверка ответа участника на втором запуске
Интерактивные задачи с двойным запуском
- Стадия
0– подготовка теста для интерактивного взаимодействия - Стадия
1– интерактивное взаимодействие
Шаги с GUI
-
Архивируйте задачу:
aj-cli problem <путь к задаче> zip -
Откройте вкладку :
-
Нажмите :
-
Выберите архив задачи
-
Нажмите
Создание условий и разборов задач
Для создания условий и разборов задач рекомендуется использовать aj-templates. В репозитории находятся 2 шаблона: statements.typ для условий и editorial.typ для разборов. Шаблон использует язык Typst. Для его использования нужно вставить содержимое нужного шаблона в свой скрипт и при необходимости изменить первую строчку на
#let lang = "ru"
для того, чтобы весь текст был на русском.
Использование шаблона для условий
#template([<заголовок>], subtitle: [<подзаголовок>],
[
// Условия задач
#problem(
"<название>",
"<лимит по времени>",
"<лимит по памяти>",
[
<легенда>
],
input:
[
<входные данные>
],
output:
[
<выходные данные>
],
interactive_protocol:
[
<протокол взаимодействия для интерактивных задач>
],
first_run:
[
<первый запуск для задач с двойным запуском>
],
second_run:
[
<второй запуск для задач с двойным запуском>
],
(
// Примеры
[
<входные данные>
],
[
<выходные данные>
],
[
<входные данные>
],
[
<выходные данные>
],
// И так далее...
),
comments:
[
<комментарии>
],
subgroups_scoring:
(
// Подгруппы
[
<номер>
],
[
<ограничения>
],
[
<баллы>
],
[
<требуемые подгруппы>
]
),
per_test_scoring:
[
<система оценки для задач с потестовой оценкой>
]
)
// Для переноса условия следующей задачи на следующую страницу необходим #pagebreak()
]
)
Использование шаблона для разборов
#template([<заголовок>], subtitle: [<подзаголовок>],
[
// Разбор задач
#problem(
"<название>",
"<разбор>"
)
// Для переноса разбора следующей задачи на следующую страницу необходим #pagebreak()
]
)