TJudge - турнирная платформа для соревнований по теории игр. Участники загружают программы-стратегии, программы играют друг против друга в нескольких играх, а система считает рейтинг ELO и ведёт таблицы лидеров.
Доступ к сервису: главная страница - https://<ваш-домен> (локально: http://localhost:8080).
Кратко, как всё устроено:
- Регистрируетесь и создаёте либо присоединяетесь к команде.
- Команда участвует в турнире.
- Для каждой игры в турнире загружаете программу-стратегию (один код - одна игра).
- Система запускает матчи программ между командами, считает результат и обновляет рейтинг.
- Текущее положение видно в таблице лидеров турнира и в кросс-игровом рейтинге.
- Откройте
/loginи нажмите «Регистрация» (или сразу перейдите на/register). - Заполните:
- Имя пользователя - латиница, без пробелов, уникальное.
- Email - используется для уведомлений.
- Пароль - минимум 8 символов.
- Нажмите «Зарегистрироваться».
После регистрации вы сразу авторизованы.
На странице /login введите имя пользователя и пароль, нажмите auth.login(). Сессия JWT хранится в localStorage и продлевается, пока вы пользуетесь сайтом (до 24 часов по умолчанию, до 7 дней с refresh-токеном).
Через меню профиля (верхний правый угол). Токен попадает в blacklist немедленно.
Страница /profile - смена имени, email, пароля.
Команды - единица участия в турнире. В турнире от команды играет один набор программ (одна программа на игру).
- Откройте турнир, нажмите «Создать команду».
- Введите название. Система выдаст invite-код и ссылку-приглашение.
- Отправьте ссылку товарищам. Они войдут в команду, перейдя по ней.
Максимальный размер команды задаётся админом турнира (обычно 1-5 человек).
На странице турнира: «Вступить в команду» -> ввести код.
Страница команды (/teams/:id) -> «Покинуть». Лидер команды покинуть не может - сначала передайте лидерство или распустите команду.
Создатель команды становится лидером. Лидер может:
- Исключать участников.
- Переименовывать команду.
- Удалять команду (если турнир ещё не начался).
/tournaments показывает активные и завершённые турниры. У каждого турнира отображается название, статус (ожидание, идёт, завершён) и число участников.
/tournaments/:id содержит:
- Описание и правила.
- Список игр, которые включены в турнир.
- Кнопка «Присоединиться» (видна, если турнир принимает участников).
- Таблица лидеров - общий кросс-игровой рейтинг.
- Вкладка по каждой игре: отдельная таблица и список матчей.
- Админ создаёт турнир, указывает описание и добавляет игры.
- Команды регистрируются и загружают программы.
- Админ запускает турнир - команды больше не принимаются.
- Планировщик формирует пары round-robin, матчи уходят в очередь воркерам.
- По мере готовности результатов рейтинг обновляется в реальном времени (WebSocket).
- После прохождения всех запланированных раундов турнир помечается как завершённый.
- Один файл или архив.
- Язык любой, главное - исполняемость внутри изолированного Docker-контейнера
tjudge-cli. - Лимиты по умолчанию: 512 МБ памяти, 60 секунд на матч, сеть отключена.
- Интерфейс ввода-вывода описан в правилах каждой игры (stdin/stdout текстом).
Со страницы своей команды в турнире (/tournaments/:id/my-team):
- Выберите игру.
- Загрузите файл или архив.
- Укажите язык (или «auto»), точку входа, если нужна.
- Нажмите «Загрузить».
Сервер выполняет первичные проверки (размер, формат, базовый статический анализ) и отправляет программу в очередь на компиляцию/подготовку.
Для каждой команды в каждой игре хранятся все загруженные версии. Актуальная - последняя успешно скомпилированная. Старые версии остаются в истории, их можно скачать.
Если компиляция или первый тестовый запуск падает, статус программы - error. Детали видны на странице программы (/programs/:id). Типичные причины:
- Синтаксическая ошибка.
- Программа не читает stdin или не печатает ответ в stdout.
- Превышены лимиты по памяти или времени.
- Попытка сетевого доступа (запрещена).
После исправления загрузите новую версию.
У каждой программы свой рейтинг для каждой игры. Старт - 1500. После матча оба рейтинга корректируются по классической формуле ELO: победитель растёт, проигравший падает, ничья сдвигает слабо. K-фактор задан в конфиге игры.
- Кросс-игровой лидерборд турнира: сумма или взвешенная сумма ELO по играм.
- Лидерборд конкретной игры в турнире: только рейтинг этой игры.
- Глобальный рейтинг (вне турниров): опционально, см. главную страницу.
Страница турнира подписывается на WebSocket /api/v1/ws/tournaments/:id и сразу показывает новые результаты. Авторизация не требуется для чтения публичных лидербордов, но требуется для WebSocket-подключения.
Два игрока одновременно выбирают: сотрудничать (C) или предать (D). Повторяется N раундов.
Выплаты за раунд:
| Я \ Оппонент | C | D |
|---|---|---|
| C | 3, 3 | 0, 5 |
| D | 5, 0 | 1, 1 |
Программа читает историю раундов со stdin и отвечает C или D. Побеждает программа с большей суммой очков.
Две команды выставляют силы на флаг. Чьё суммарное усилие больше - тот сдвинул канат. Общий ресурс усилий ограничен, распределяется по раундам стратегически.
Двое независимо объявляют цену от 2 до 100. Оба получают меньшую из двух объявленных цен. Тот, кто назвал меньшее число, получает бонус, кто большее - штраф. Равновесие по Нэшу - 2, но оптимальная игра сложнее.
N игроков решают, сколько вложить в общее благо. Общая сумма умножается на множитель и делится поровну между всеми независимо от вклада. Классическая задача о безбилетниках.
Аукцион, в котором второй по величине ставщик тоже платит свою ставку (но ничего не получает). Простой, если остановиться, но участники легко «попадают в ловушку».
Точные параметры (число раундов, множители, лимиты) задаёт админ при добавлении игры в турнир.
Доступ: роль admin (назначается через CLI make admin EMAIL=...). Интерфейс - /admin.
Основные возможности:
- Управление турнирами: создание, добавление игр, запуск, завершение, удаление.
- Ручной перезапуск пачки матчей (
run-matches,run-game-matches,retry-matches). - Завершение/сброс раунда по игре внутри турнира.
- Включение авто-раунда: система сама запускает следующий раунд, когда пулл матчей исчерпан.
- Массовая загрузка программ команд по zip-архиву (скачивание в админ-интерфейсе).
- Управление командами: дисквалификация, восстановление, удаление.
- Управление играми: добавление, редактирование, удаление (кроме встроенных).
- Просмотр audit-лога:
/admin-> «Audit». - Очередь матчей: статистика, очистка, удаление невалидных записей.
Все админские действия пишутся в audit_log с привязкой к admin-пользователю.
Сервер документируется через Swagger: /swagger/ (требует admin-токен). Полный справочник - docs/API_GUIDE.md.
Ключевые группы:
/api/v1/auth/*- регистрация, вход, refresh, профиль./api/v1/tournaments/*- CRUD и управление турнирами./api/v1/teams/*- команды./api/v1/programs/*- загрузка и скачивание программ./api/v1/games/*- метаданные игр./api/v1/matches/*- матчи и очередь./api/v1/ws/tournaments/:id- real-time обновления лидерборда.
Авторизация: Authorization: Bearer <JWT>.
Смотрите детали на странице программы. Типичные причины перечислены в §5. Для воспроизведения локально можно запустить tjudge-cli в Docker с теми же лимитами.
Сразу после обработки матча воркером. Если страница открыта, обновление приходит через WebSocket. Если WebSocket отключён, используйте ручной refresh.
Да, пока раунд по этой игре не стартовал. Если раунд уже начат, новые версии попадут в следующий раунд.
Админ: на странице турнира -> programs/download-zip. Обычный участник - через свою страницу команды.
GitHub issues репозитория. Приложите request-id из ответа сервера (заголовок X-Request-ID) - оператор найдёт контекст в логах.