November 1, 2023

Система невидимой автоматической проверки заданий LightPT. Часть 1

В PascalABC.NET встроена система автоматической проверки LightPT, которая позволяет легко составлять автоматически проверяемые задания.

Рассмотрим данный процесс на примере.

Начальные действия

Чтобы задания проверялись автоматически, необходимо создать Урок с заданиями. Урок представляет собой папку, в которой находятся .pas-файлы - заготовки с формулировками заданий, а также специальный файл lightpt.dat. Этот файл может быть пустым или содержать название урока. Именно этот файл является маркером того, что все задания в этой папки будут проходить через невидимую проверяющую систем

Итак, создадим папку Lesson1 и в ней файл lightpt.dat, в котором напишем одну строчку в кодировке Windows 1251: Урок-1. Задания на массивы

Создание задания

Теперь создадим в этой папке первый файл с заданием ArrTask1.pas со следующим содержимым:

Обязательно сохраним указанный файл в папку с уроком.

Создание модуля проверки заданий

Теперь создадим модуль, который будет проверять все выполненные задания в уроке (в олимпиадном программировании такие подпрограммы называются чекерами). Для этого в той же папке создадим файл Tasks.pas со следующим содержимым (важно использовать именно это имя файла):

Вот полный текст проверяющего модуля Tasks:

unit Tasks;

uses LightPT;

procedure CheckTaskT(name: string);
begin
  case name of
    'ArrTask1': begin

    end;
  end;
end;

initialization
  CheckTask := CheckTaskT;
end.

Код проверки задания

Далее напишем самую главную часть - код проверки:

Вот полный текст модуля:

unit Tasks;

uses LightPT;

procedure CheckTaskT(name: string);
begin
  case name of
    'ArrTask1': begin
      var N := Int;
      CheckData(Input := |cInt| + |cRe| * N);
      var a := ReArr(N);
      var cnt := a.Count(x -> x > 5);
      CheckOutput(cnt);
    end;
  end;
end;

initialization
  CheckTask := CheckTaskT;
end.

Поясним отдельные строки.

1. Введенное учеником первое целоезначение, характеризующее размер массива, запоминается в переменной N

var N := Int;

2. В процедуре CheckData указывается, что входные данные Input должны состоять из целого числа (константа cInt) и N вещественных чисел (константа cRe). Все данные объединяются в массив входных данных с помощью конструктора массива |cInt| + |cRe| * N.

CheckData(Input := |cInt| + |cRe| * N);

Константы cInt, cRe, cStr, cBool, cChar хранят в себе элементарные типы значений - именно из них конструируются типы входных данных и соответствие именно этим типам проверяются чекером у входных данных.

Если мы введем неверное количество входных данных или неверно укажем их типы, система проверки выведет соответствующее сообщение об ошибке.

3. С помощью функции ReArr введенные учеником N вещественных значений заносятся в массив a

var a := ReArr(N);

4. Количество элементов, больших 5, вычисляется с помощью стандартного метода массива a.Count и заносится в переменную cnt.

var cnt := a.Count(x -> x > 5);

5. Проверка правильности вывода осуществляется с помощью процедуры CheckOutput:

CheckOutput(cnt);

Всё!

Решение задания учеником

Теперь всё готово к выполнению задания под управлением системы невидимой автоматической проверки.

Закроем среду PascalABC.NET и промоделируем действия ученика на уроке.

Ученик обязательно должен запустить PascalABC.NET из файла урока щелчком мыши на файле с заданием:

Кнопка белого человечка на тулбаре является признаком того, что задание находится под управлением системы невидимой проверки.

Наберем часть решения и запустим:

Мы видим, что система автоматической проверки начала свою работу и показала, что необходимо ввести дополнительные данные.

Введем массив N вещественных любым доступным способом:

Здесь мы ошиблись - надо ввести вещественный массив:

Это сообщение системы невидимой проверки выводится серым, что означает, что ошибки нет, и мы на верном пути.

Попытаемся обмануть систему и выведем неверное значение:

Система невидимой проверки показала, что результат неверен.

И наконец правильно решим задачу:

Система невидимой проверки зеленым вывела, что задание выполнено.

Поздравляем! Вы составили и выполнили первое задание под управлением системы невидимой автоматической проверки!

Составление нескольких тестов

Ученик может обмануть данный алгоритм проверки. Например, он может ввести три единицы и не записывая алгоритм, вывести 0 в качестве результата:

Это означает, что проверка задания составлена некачественно.

Вернемся к заданию и добавим к проверке дополнительные тесты. Сделать это просто:

Строка

GenerateTests(10,tInt(N,N) + tRe(1,10) * N);

означает "сгенерировать 10 автоматических тестов, каждый тест в качестве входных данных будет содержать одно целое число в диапазоне от N до N (то есть, само число N) и затем N вещественных чисел в диапазоне от 1 до 10".

Здесь tInt, tRe, tChr, tBoo - это функции, которые вызываются только при генерации тестов для задания алгоритма генерации случайного тестового входного значения нужного типа в указанном диапазоне.

После этого запуск предыдущего неправильного решения ученика приведет к следующему выводу:

Итак, произошло следующее:

  1. Ученик попытался обмануть систему, ввел определённые данные, не написал алгоритм и вывел результат для этих данных.
  2. Система невидимой проверки проверила его решение и посчитала его верным.
  3. Система невидимой проверки не поверила ученику и предложила 10 своих тестов, где в качестве входных данных сгенерировала случайные значения по спецификации tInt(N,N) + tRe(1,10) * N
  4. На одном из таких тестов 3 7 8 5 (сгенерировано автоматически 3 вещественных числа 7 8 5) система "поймала" ученика, вывела данные теста, вывела неправильный ответ ученика и правильный результат, который необходимо было вывести если бы эти данные были бы введены.

То есть, систему проверки обмануть не удалось. Теперь только правильный алгоритм будет оценен чекером как выполненное задание:

Протокол выполнения заданий учеником

Протокол выполнения заданий учеником хранится в файле db.txt в папке урока. Он имеет вид:

Урок-1. ArrTask1 2023-11-01 11:36:05Z IOError InputCount(1,4)
Урок-1. ArrTask1 2023-11-01 11:36:59Z IOError InputCount(1,4)
Урок-1. ArrTask1 2023-11-01 11:38:05Z IOError InputCount(1,4)
Урок-1. ArrTask1 2023-11-01 11:56:53Z IOError InputCount(1,4)
Урок-1. ArrTask1 2023-11-01 11:59:13Z IOError InputType(2,real,integer)
Урок-1. ArrTask1 2023-11-01 12:00:05Z IOError OutputCount(0,2)
Урок-1. ArrTask1 2023-11-01 12:46:46Z BadSolution NoInfo
Урок-1. ArrTask1 2023-11-01 12:48:19Z Solved NoInfo

При каждом запуске в конец этого файла добавляется строка, характеризующая текущий запуск. Она содержит имя урока, имя задания, время запуска и результат запуска - степень выполнения и дополнительные параметры. По данному содержимому видно, что ученик 4 раза запустил программу, в которой было введено всего одно число, после этого он ввел неверный тип при вводе массива (ошибка InputType(2,real,integer) во втором элементе), затем он выводил неверное количество данных (ошибка OutputCount(0,2) - выведено 0, а надо вывести 2 элемента), после этого неправильно решил задание (BadSolution) и наконец решил правильно (Solved).

Разработка следующих заданий урока

Следующие задания разрабатываются существенно проще.

Скажем, мы добавляем в папку урока новое задание ArrTask2.pas с формулировкой задания в комментарии. Тогда чтобы оно стало проверяемым, мы также должны добавить в модуль Tasks.pas строки

Мы также должны добавить в модуль Tasks.pas строки

    'ArrTask2': begin
      // Здесь - текст чекера
    end;

Заключение

В данной статье показано использование системы невидимой автоматической проверки, имеющей существенные отличия от всех известных систем автоматической проверки:

1. Разработка заданий осуществляется в той же среде, что и решение заданий учеником

2. Разработка заданий проста и для последующих задач по данной теме занимает 2-3 минуты на задание.

3. Задания проверяют типы при вводе-выводе (в системах олимпиадного тестирования из файла считываются лишь текстовые данные, что крайне бедно)

4. Решение задания учеником выполняется непосредственно в среде PascalABC.NET без каких-то дополнительных действий. Текст программы не надо копировать на интернет-страницу сетевой тестирующей системы.

5. Задание проверяется в момент запуска программы ученика - нет ожидания ответа от сервера.

В следующих статьях о системе LightPT мы рассмотрим более сложные случаи составления заданий.