Рабочий стол > DL Руководство пользователя > ... > Вспомогательные средства установки задач по программированию > Модификация testlib для DL > Просмотр
Модификация testlib для DL Войти | Зарегистрироваться   Просмотр версии для печати текущей страницы.

Добавлено Гуленко Алексей, последний раз изменено Гуленко Алексей Oct 15, 2023  (просмотр изменений)
Метки: 
(нет)

Библиотека testlib-dl

Многие из российских задач используют для тестирования checker'ы и player'ы, использующие для общих задач тестирования (ввод-вывод, выдача результата) библиотеку testlib.h. Для использования этих программ на DL можно воспользоваться модификацией этой библиотеки для DL (из форка на Github) – чекер, скомпилированный с этой библиотекой, будет обрабатывать аргументы командной строки и делать вывод в соответствии с протоколом DL.

Данная модификация имеет несколько релизов, последний основан на testlib версии 0.9.40
Модификация совместима с testlib, но поддерживает только функционал чекеров и player'ов. Также может играть роль конкретная версия библиотеки, а в некоторых олимпиадах может использоваться собственная кастомная модификация – в частности, форк включает версии для IOI-2021 и IOI-2022.

Для использования достаточно скомпилировать программу (checker.cpp или interact.cpp) положив в ту же папку модифицированный testlib.h вместо оригинального. (Проверялось только на g++ версии 7.3+)

 
Также для интерактивных задач доступны следующие директивы компилятора (добавляются в параметры компиляции):

  • -DINFILE="имя-файла" (файл ввода данных для player'а; значение по умолчанию: "$player$.in")
  • -DOUTFILE="имя-файла" (файл вывода данных для player'а; значение по умолчанию: "$player$.out")
  • -DLOGFILE="имя-файла" (файл логирования данных для player'а; по умолчанию отсутствует)
  • -DPLAYER_ADAPT (несовместим с -DLOGFILE; включает режим совместимости интерактивных задач – см. ниже)
примеры строки компиляции
g++ -O2 -o checker checker.cpp
g++ -O2 -o player interact.cpp
g++ -O2 -o player interact_new.cpp -DINFILE="eq.in" -DOUTFILE="eq.out"
INFILE, OUTFILE и LOGFILE должны содержать корректные строки в формате C; в зависимости от особенностей используемого shell'а, может потребоваться экранировать их, скажем, взяв дополнительно в одинарные кавычки (например: -DINFILE='"eq.in"')

Для интерактивных задач, помимо исполнимых файлов checker и player, обычно нужно изменить task.cfg и добавить stdswp.cfg:

task.cfg (изменения)
TYPE = INTERACTIVE
INFILE = FILE($player$.in)
OUTFILE = FILE($player$.out)
CHECKER = 1
CHECKSUBJECT = FILE
CHECKFILES = {stdswp.cfg}
stdswp.cfg
KillSolution=Yes

Режим совместимости интерактивных задач (-DPLAYER_ADAPT)

Как правило, в интерактивных задачах большая часть проверок производится player'ом (interact.cpp в исходном архиве); в этом случае чекеру достаточно просто скопировать содержимое $player$.out в $result$.txt, умножив выведенное число очков на максимальное за тест. Однако есть и такие задачи, в которых чекеру необходимо читать как файл ответа жюри (1.out и т.п.) так и вывод чекера; в этом случае testlib-задачи как правило используют костыль в виде отправления этих данных в LOGFILE (т.к. в OUTFILE отправляется статус самого тестирования) – ему соответствует глобальная переменная tout.

В testlib-dl реализован режим совместимости, позволяющий заметно упростить установку подобных задач; это достигается путём совмещения файлов (а именно, при положительном результате тестирования, вместо комментария в OUTFILE выводится текст, который должен был отправляться в LOGFILE. Для его применения требуется выполнить следующее:

  1. перенести команду quitf(_ok, ...); из player'а в чекер (по обстоятельствам – это комментарий, который пойдёт в протокол при пройденном тесте);
  2. добавить в player на место этой команды вызов dl_playerDone(); – это выполняет успешное завершение player'а с выводом данных из tout;
  3. добавить в чекер в начало (сразу после registerTestlibCmd(argc, argv);) вызов dl_playerCheck(); – это инициирует проверку статуса завешения player'а и вывод отрицательного статуса;
  4. компилировать и player и чекер с директивой -DPLAYER_ADAPT для включения означенного режима совместимости.
оригинальный interact.cpp
#include <cstdint>
#include <iostream>
#include "testlib.h"

using namespace std;

int const Q_MAX = 42;

int main(int argc, char *argv[]) {
    registerInteraction(argc, argv);

    int n = inf.readInt();
    int c = inf.readInt();
    vector<int> a = inf.readInts(n);

    cout << n << endl << flush;

    vector<int> qs;
    int queries = 0;
    while (true) {
        string action = ouf.readToken("!|\?");
        if (action == "!") {
            int res = ouf.readInt(0, n - 1, "c");
            tout << "answer " << res << "\n";
            tout << "queries " << queries << "\n";
            break;
        }

        if (++queries > Q_MAX) {
            cout << "-1\n" << flush;
            quitf(_wa, "too much queries");
        }
        int x = ouf.readInt(1, n);
        qs.push_back(x);
        cout << a[(x - 1 + c) % n] << "\n" << flush;
    }


    quitf(_ok, "%d queries processed", n);  // BEFORE
}
адаптированный player.cpp (скомпилированный с -DPLAYER_ADAPT)
#include <cstdint>
#include <iostream>
#include "testlib.h"

using namespace std;

int const Q_MAX = 42;

int main(int argc, char *argv[]) {
    registerInteraction(argc, argv);

    int n = inf.readInt();
    int c = inf.readInt();
    vector<int> a = inf.readInts(n);

    cout << n << endl << flush;

    vector<int> qs;
    int queries = 0;
    while (true) {
        string action = ouf.readToken("!|\?");
        if (action == "!") {
            int res = ouf.readInt(0, n - 1, "c");
            tout << "answer " << res << "\n";
            tout << "queries " << queries << "\n";
            break;
        }

        if (++queries > Q_MAX) {
            cout << "-1\n" << flush;
            quitf(_pe, "too many queries");
        }
        int x = ouf.readInt(1, n);
        qs.push_back(x);
        cout << a[(x - 1 + c) % n] << "\n" << flush;
    }


    dl_playerDone();  // AFTER
}
оригинальный checker.cpp
#include <cstdint>
#include "testlib.h"

using namespace std;

typedef long long ll;
const int MAX_QUERIES = 42;
  // BEFORE

int readAnswer(InStream &inStream, int n, const vector<int> &a, int c) {
    inStream.readToken("answer", "_");
    int answer = inStream.readInt(0, n - 1, "ans");

    inStream.readToken("queries", "_");
    int queries = inStream.readInt(0, INT_MAX, "queries");  // BEFORE
    inStream.ensuref(queries < MAX_QUERIES,
                     "too match queries was done (%d)", queries);

    return answer;
}

int main(int argc, char *argv[]) {
    registerTestlibCmd(argc, argv);

      // BEFORE
    int n = inf.readInt();
    int c = inf.readInt();
    vector<int> a = inf.readInts(n);

    ll juryAnswer = readAnswer(ans, n, a, c);
    ll pAnswer = readAnswer(ouf, n, a, c);
    if (juryAnswer != c) {
        quitf(_fail, "jury's answer is not equal to c");
    }
    if (pAnswer != c) {
        quitf(_wa, "participant's answer is not equal to c");
    }
    quitf(_ok, "%lld", juryAnswer);  // BEFORE
}
адаптированный checker.cpp (скомпилированный с -DPLAYER_ADAPT)
#include <cstdint>
#include "testlib.h"

using namespace std;

typedef long long ll;
const int MAX_QUERIES = 42;
int queries;  // AFTER (for printing success message)

int readAnswer(InStream &inStream, int n, const vector<int> &a, int c) {
    inStream.readToken("answer", "_");
    int answer = inStream.readInt(0, n - 1, "ans");

    inStream.readToken("queries", "_");
    queries = inStream.readInt(0, INT_MAX, "queries");  // AFTER
    inStream.ensuref(queries < MAX_QUERIES,
                     "too many queries were done (%d)", queries);

    return answer;
}

int main(int argc, char *argv[]) {
    registerTestlibCmd(argc, argv);

    dl_playerCheck();  // AFTER
    int n = inf.readInt();
    int c = inf.readInt();
    vector<int> a = inf.readInts(n);

    ll juryAnswer = readAnswer(ans, n, a, c);
    ll pAnswer = readAnswer(ouf, n, a, c);
    if (juryAnswer != c) {
        quitf(_fail, "jury's answer is not equal to c");
    }
    if (pAnswer != c) {
        quitf(_wa, "participant's answer is not equal to c");
    }
    quitf(_ok, "%d queries processed", queries);  // AFTER
}
Powered by Atlassian Confluence, the Enterprise Wiki. (Version: http://www.atlassian.com/software/confluence Build:#2.6.1 916) - Ошибка/новая особенность - Свяжитесь с Администраторами