Постпроцессоры

Постпроцессор — это программа, которая выдает результирующий балл по отправленному решению участника.

В отличие от чекера, эта программа запускается один раз на все тесты, когда выполнение всех тестов завершено. Постпроцессор не управляет вердиктом посылки и не может на него влиять.

В самом простом случае постпроцессор суммирует баллы всех чекеров.

Постпроцессор используют, если нужно:

  • получать общий балл за посылку;
  • реализовать сложную логику определения баллов за посылку, например по группам тестов или в процентном соотношении от количества пройденных тестов;
  • изменить логику суммирования баллов за каждый тест.

Обратите внимание, что баллы за задачу с помощью постпроцессора будут выставляться только в соревнованиях с типом монитора SCORING. Подробнее см. Мониторы.

Загрузка в систему

  1. Откройте нужную задачу и слева в меню выберите Настройки.
  2. Внизу списка найдите Дополнительные файлы и обработки.
  3. В разделе Файлы постпроцессора нажмите Выбрать файл.
  4. В системном окне выберите нужный файл и подтвердите его загрузку.
    • Первым добавьте исполняемый файл постпроцессора.
    • Далее добавляйте дополнительные файлы для работы постпроцессора.
  5. Выберите оружение для запуска постпроцессора.

Внимание

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

Реализация

Требования к файлу с постпроцессором:

  • Содержит переносы строк вида \n (unix-переносы). Если переносы будут другого вида (например, \r\n — windows-переносы), система не сможет запустить файл.
  • Является исполняемым. Для неисполняемых файлов некомпилируемых языков программирования необходимо указывать окружение (также, как это делается в чекере).

Получить данные для работы постпроцессора можно из stdin. Данные приходят в формате json, поэтому сразу подключите необходимые библиотеки.

На примере Python3 это может быть команда:

#!/usr/local/bin/python3.7

import json

data = json.loads(input())

Результат работы постпроцессора определяет баллы за посылку. Для этого в первой строке output постпроцессора должно содержаться число (long / double).

Пример: print(10).

Структура JSON

Структура данных с результатами тестирования, которые доступны постпроцессору.

{
  "tests": [
    {
      "testName": "tests/01",
      "sequenceNumber": 1,
      "testsetIdx": 0,
      "testsetName": "All tests",
      "verdict": "ok",
      "score": {
        "scoreType": "long",
        "longScore": 10
      },
      "runningTime": 39,
      "memoryUsed": 4648960,
      "startTimeMillis": 1626862111771
    },
    {
      "testName": "tests/02",
      "sequenceNumber": 2,
      "testsetIdx": 0,
      "testsetName": "All tests",
      "verdict": "ok",
      "score": {
        "scoreType": "double",
        "doubleScore": 9.27
      },
      "runningTime": 52,
      "memoryUsed": 162270,
      "startTimeMillis": 1626862113546
    },
  ]
}

Параметр

Описание

tests

array of objects

Корневой список с данными каждого из тестов.

testName

string

Путь к файлу теста в файловой системе задачи.

sequenceNumber

integer
Порядковый номер теста (начиная с 1).

testsetIdx

integer

Уникальный идентификатор набора тестов.

testsetName

string

Название набора тестов.

verdict

integer

Вердикт теста.

score

object

Баллы за тест.

score.scoreType

boolean

Тип поля с баллами. Допустимые значения:

  • long — баллы в целых числах;
  • double — баллы в дробных числах.

score.longScore

integer

Количество начисленных баллов (целые числа). Доступно, если "scoreType": "long".

score.doubleScore

double

Количество начисленных баллов (дробные числа). Доступно, если "scoreType": "double".

runningTime

integer

Время выполнения кода участника в мс.

memoryUsed

integer

Использование памяти в байтах.

startTimeMillis

integer

Отметка времени старта тестирования посылки (Unix Timestamp в миллисекундах).

Корректный запуск

Корректный запуск постпроцессора зависит от правильности настройки соревнования. Например, если постпроцессор выставляет баллы в зависимости от количества пройденных тестов из числа всех тестов — система должна запускать все тесты и не останавливать тестирование при первой ошибке.

Правильность настройки влияет на скорость проверки посылки участника — чем больше тестов, тем дольше выполняется тестирование.

Для настройки постпроцессоров необходимо проверить корректность настроек соревнования. Обратите внимание на следующие параметры:

Примеры постпроцессоров

В процентах от прорешанных тестов: 0-100

В настройках соревнования установить значения:

  • прерывать тестирование при первой ошибке — Выкл;
  • прерывать тестирование при первой ошибке внутри набора тестов — Выкл.
#!/usr/bin/python3

import json

maxValue = 100

testData = json.loads(input())
testsCount = len(testData["tests"])
acceptedTestsCount = len(list(filter(lambda n: n["verdict"] == "ok", testData["tests"])))

print(int(acceptedTestsCount / testsCount * maxValue))
Разные баллы за разные группы тестов

В настройках соревнования установить значения:

  • прерывать тестирование при первой ошибке — Выкл;
  • прерывать тестирование при первой ошибке внутри набора тестов — Вкл/Выкл — в зависимости от ситуации.

Рекомендуем не используйте набор тестов All tests (в настройка задачи) — применяйте только группы тестов с понятными обозначениями.

#!/usr/bin/python3

import json

config = [
  { "testsetName": "samples", "scoreByTest": 0 },
  { "testsetName": "All tests", "scoreByTest": 0 },
  { "testsetName": "1", "scoreByTest": 1 },
  { "testsetName": "2", "scoreByTest": 10 },
]

testData = json.loads(input())

finalScore = 0

for elem in testData["tests"]:
  if elem["verdict"] == "ok":
    scoreByCurrentTest = list(filter(lambda x: elem["testsetName"] == x["testsetName"], config))[0]["scoreByTest"]
    finalScore += scoreByCurrentTest

print(finalScore)
Переопределение баллов чекера с выводом лога расчета

Настройки соревнования могут быть любые.

Рекомендуем не используйте набор тестов All tests (в настройка задачи) — применяйте только группы тестов с понятными обозначениями.

Этот постпроцессор переопределяет стоимость теста, изменяя его значение на соответствующий множитель в зависимости от группы теста.

В лог делаются записи о том, на сколько какой тест был оценен в итоге .

#!/usr/bin/python3

import json

config = {
  "All tests": 0,
  "samples": 0,
  "1": 1,
  "2": 2
}

testData = json.loads(input())["tests"]

finalScore = 0

log = []

for elem in testData:
  if "score" in elem:
    currentScore = 0
    try:
      currentScore = elem["score"]["doubleScore"]
    except KeyError:
      currentScore = elem["score"]["longScore"]

    newScore = currentScore * config[elem["testsetName"]]

    log.append("Test: {}-{}. Score: {} * {} = {} ".format(
        elem["testsetName"],
        elem["testName"],
        currentScore,
        config[elem["testsetName"]],
        newScore
      ))
    finalScore += newScore

print(finalScore)
print("\n".join(log))
Постпроцессор с гибкой настройкой

Постпроцессор с гибкой настройкой разработан пользователем Яндекс Контест.

Особенности:

  • можно скорректировать для различных систем подсчета очков;
  • считает оценку за тест и групповой зачет;
  • создает пользовательские отчеты;
  • формирует различные виды обратной связи для участников.

О порядке использования постпроцессора с гибкой настройкой см. на github.com.

Написать в службу поддержки
Предыдущая