|
Просмотр источника
h1. Альтернативная установка задач с интерактивным вводом-выводом
{note:title=Данная инструкция описывает усложнённый процесс установки} Здесь описан минимальный процесс конверсии задачи, установленной под *StdSwp*, для запуска *tester*'ом. Это следует делать в случае если требуется использовать групповое тестирование, или для обхода проблем запуска глобально установленного *StdSwp* на новых DelTA'х. {note} *Tester* (программа, изначально предназначенная для тестирования задач IOI) с некоторых пор поддерживает тестирование задач с интерактивным вводом-выводом, запускаемых через *StdSwp*. По умолчанию под Windows используется путь {{D:\DelTA\stdswp}} (под Linux/Mac - локальный файл {{./stdswp}}); однако в конфигурации можно указать путь к альтернативному исполнимому файлу. Также (в отличие от DelTA) у *tester*'а нет проблем с использованием группового тестирования для интерактивных задач. Более подробная инструкция по использованию *tester*'а находится [тут|Установка задач IOI]; с общей инструкцией по установке задач с интерактивным вводом-выводом (*StdSwp*) можно ознакомиться [здесь|Интерфейс тестирования задач с интерактивным вводом-выводом]. {warning:title=При несоблюдении данной инструкции тестирование работать не будет!} Креативная замена важных файлов (из описания ниже) на какие попало (особенно *{{checker.exe}}*, который должен быть скомпилирован из *{{checker.pas}}*) помешает работе системы тестирования. Также, нижеописанные операции _не рассчитаны_ на [интерактивные задачи NEERC|Установка интерактивных задач NEERC (Питер)]; их можно опознать по файлам *{{coact.exe}}*, *{{coact.bat}}*, *{{Check.jar}}*, *{{Interact.jar}}*, *{{InteractChecker.jar}}* и т.п. {warning} h2. Конверсия интерактивной задачи под Tester * файл чекера ({{checker.exe}}) следует переименовать в {{check.exe}} (из-за особенностей реализации tester'а) * программа взаимодействующая с решением всё так же зовётся player'ом * файл {{stdswp.cfg}} работает так же как описано в инструкции по StdSwp * также нужны файлы конфигурации и исходники для tester'а (помимо {{src/CheckLib.pp}} и {{src/TesterLib.pp}}) нижеследующего содержания {code:title=src/checker.pas (выполняет запуск отдельного теста)} Uses CheckLib; BEGIN Run(ProgName, OutFile); Prepend(OutFile, 'OK'); END. {code} {code:title=src/tester.pas (выполняет процесс тестирования)} Uses TesterLib; BEGIN Body(); POut(); END. {code} {code:title=task.cfg (передаёт контроль над тестированием задач Tester'у)} TYPE = USERS CHECKSUBJECT = FILE CHECKFILES = {*.*} CHECKER = 'tester.exe $SOLUTION$' {code} {code:title=tester.cfg (управляет поведением Tester'а)} PreRun = prepare.bat # скрипт компиляции решения! Program = yes # решение - не библиотека а программа Interactive = yes # тестировать с интерактивным вводом-выводом InFile = input.txt # название input-файла OutFile = output.txt # название output-файла ExtChecker = check # название оригинального чекера (без расширения) < # сюда внести описание групп тестов, по одной на строку # (для раздельного тестирования достаточно указать число баллов за соответствующий тест) > {code} {code:title=prepare.bat (отвечает за компиляцию файла решения на Pascal, C/C++, Java или Python3)} @echo off for %%f in ("%~n1") do ( if /i %%~xf==.java goto rename ) set sol=%1 set solext=%~x1 set runnerfile=solution.bat set runner=%~n1.exe if not exist 2.in cmd /C unrar -o- x tests if /i %solext%==.pas goto pascal if /i %solext%==.ppw24 goto pascal if /i %solext%==.c goto c if /i %solext%==.cpp goto cpp if /i %solext%==.g54 goto cpp if /i %solext%==.g73 goto cpp if /i %solext%==.java goto java if /i %solext%==.py goto py3 echo not found @exit /B 1 :pascal echo %runner%> %runnerfile% cmd /C D:\DelTA\Lngs\compile_ppw302 %sol% . @exit /B %errorlevel% :c echo %runner%> %runnerfile% cmd /C D:\DelTA\Lngs\compile_c73 %sol% . @exit /B %errorlevel% :cpp echo %runner%> %runnerfile% cmd /C D:\DelTA\Lngs\compile_g73_old %sol% . @exit /B %errorlevel% :java echo %runner%> %runnerfile% cmd /C D:\DelTA\Lngs\compile_java8 %sol% . @exit /B %errorlevel% :py3 echo %runner%> %runnerfile% cmd /C D:\DelTA\Lngs\compile_py %sol% . @exit /B %errorlevel% :rename copy %1 %~n1 prepare %~n1 {code} {code:title=limiter.bat (обёртка вокруг системного Limiter'а)} @echo off if "%~4" == "" goto 5 if "%~5" == "" goto 4 D:\DelTA\DelTA3DL\limiter %1 %2 "%3 < %4 > %5" %6 > lim.log 2> lim.err goto :eof :4 D:\DelTA\DelTA3DL\limiter %1 %2 "%3 < %4" %6 > lim.log 2> lim.err goto :eof :5 @if "%~5" == "" goto 0 D:\DelTA\DelTA3DL\limiter %1 %2 "%3 > %5" %6 > lim.log 2> lim.err goto :eof :0 D:\DelTA\DelTA3DL\limiter %1 %2 "%~3" %6 > lim.log 2> lim.err {code} h2. Альтернативный StdSwp При наличии проблем с версией StdSwp используемой по умолчанию, можно использовать какую-нибудь альтернативную версию (лично я предлагаю использовать скрипт на Python). Пример такой конфигурации: {code:title=tester.cfg (добавить перед описанием тестов)} StdSwp = stdswp-py.cmd {code} {code:title=stdswp-py.cmd (обёртка для запуска Python)} D:\DelTA\Lngs\Python-3.11.3\python stdswp.py %* {code} {code:title=stdswp.py (простая реализация, игнорирует stdswp.cfg и подразумевает KillSolution=yes)} #!/usr/bin/env python from concurrent.futures import wait, ThreadPoolExecutor, FIRST_COMPLETED from subprocess import Popen, PIPE from sys import argv def interact (player, solution, kill_player=False, kill_solution=True): player = Popen(player, stdin=PIPE, stdout=PIPE) solution = Popen(solution, stdin=player.stdout, stdout=player.stdin) try: executor = ThreadPoolExecutor(max_workers=2) futures = [executor.submit(x.wait) for x in (player, solution)] wait(futures, return_when=FIRST_COMPLETED) if kill_player and solution.returncode is not None: player.terminate() assert {solution.returncode} <= {0, None} elif kill_solution and player.returncode is not None: solution.terminate() assert {player.returncode} <= {0, None} else: assert {player.returncode, solution.returncode} <= {0, None} wait(futures) assert {player.returncode, solution.returncode} <= {0, None} finally: player.kill() solution.kill() if __name__ == '__main__': interact(argv[1], argv[2]) {code} |