---
metadata:
  - name: generator
    content: Diplodoc Platform v5.48.2
alternate:
  - https://admin.contest.yandex.ru/docs/en/problem/postprocessors.md
  - https://admin.contest.yandex.ru/docs/ru/problem/postprocessors.md
---
> **Documentation Index:** Fetch the complete configuration index at https://admin.contest.yandex.ru/docs/ru/llms.txt

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

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

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

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

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

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

Обратите внимание, что баллы за задачу с помощью постпроцессора будут выставляться только в соревнованиях с типом монитора **SCORING**. Подробнее см. [Мониторы](https://admin.contest.yandex.ru/docs/ru/contest/monitors-description.md).

## Загрузка в систему {#uploading}

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

{% note alert %}

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

{% endnote %}

## Реализация {#realization}

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

* Содержит переносы строк вида ``\n`` (<q>unix-переносы</q>). Если переносы будут другого вида (например, `\r\n`&nbsp;— <q>windows-переносы</q>), система не сможет запустить файл.
* Является исполняемым. Для неисполняемых файлов некомпилируемых языков программирования необходимо указывать окружение (также, как это делается в [чекере](https://admin.contest.yandex.ru/docs/ru/problem/checkers.md)).

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

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

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

import json

data = json.loads(input())
```

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

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

## Структура JSON {#json-structure}

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

```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`&nbsp;— баллы в целых числах;
- `double`&nbsp;— баллы в дробных числах.
||
||**score.longScore**|
**integer**

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

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

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

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

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

## Корректный запуск {#correct-launch}

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

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

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

- [Прерывать тестирование при первой ошибке](https://admin.contest.yandex.ru/docs/ru/guide/contest/submissions.md)&nbsp;— выключить, если постпроцессор определяет баллы на основе количества тестов.
- [Прерывать тестирование при первой ошибке внутри набора тестов](https://admin.contest.yandex.ru/docs/ru/guide/contest/submissions.md)&nbsp;— включить, чтобы сэкономить время проверки посылки, когда разные группы тестов проверяют разные свойства решения участника и проверить другую группу тестов нужно, но тестирование в рамках текущей группы тестов уже не имеет смысла.
- [При непройденных тестах из условия](https://admin.contest.yandex.ru/docs/ru/guide/contest/submissions.md)&nbsp;— установить в состояние **Остановить тестирование**, чтобы сэкономить время тестирования и быстрее отдать вердикт участнику соревнования.

## Примеры постпроцессоров  {#examples}

> {% cut "В процентах от прорешанных тестов: 0-100" %}
> 
> В настройках соревнования установить значения:
> 
> - прерывать тестирование при первой ошибке&nbsp;— **Выкл**;
> - прерывать тестирование при первой ошибке внутри набора тестов&nbsp;— **Выкл**.
> 
> ```python
> #!/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))
> ```
> 
> {% endcut %}
> 
> {% cut "Разные баллы за разные группы тестов" %}
> 
> В настройках соревнования установить значения:
> 
> - прерывать тестирование при первой ошибке&nbsp;— **Выкл**;
> - прерывать тестирование при первой ошибке внутри набора тестов&nbsp;— **Вкл/Выкл**&nbsp;— в зависимости от ситуации.
> 
> Рекомендуем не используйте набор тестов **All tests** (в настройка задачи)&nbsp;— применяйте только группы тестов с понятными обозначениями.
> 
> ```python
> #!/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)
> ```
> 
> {% endcut %}
> 
> {% cut "Переопределение баллов чекера с выводом лога расчета" %}
> 
> Настройки соревнования могут быть любые.
> 
> Рекомендуем не используйте набор тестов **All tests** (в настройка задачи)&nbsp;— применяйте только группы тестов с понятными обозначениями.
> 
> Этот постпроцессор переопределяет стоимость теста, изменяя его значение на соответствующий множитель в зависимости от группы теста.
> 
> В лог делаются записи о том, на сколько какой тест был оценен в итоге .
> 
> ```python
> #!/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))
> ```
> 
> 
> {% endcut %}
> 
> {% cut "Постпроцессор с гибкой настройкой" %}
> 
> Постпроцессор с гибкой настройкой разработан пользователем Яндекс Контест.
> 
> Особенности:
> 
> - можно скорректировать для различных систем подсчета очков;
> - считает оценку за тест и групповой зачет;
> - создает пользовательские отчеты;
> - формирует различные виды обратной связи для участников.
> 
> О порядке использования постпроцессора с гибкой настройкой см. на [github.com](https://github.com/nsychev/contest-valuer).
> 
> {% endcut %}

<!-- source: ru/_includes/reusables/support-button.md -->
<a href="../../troubleshooting">
  <span class="button">Написать в службу поддержки</span>
</a>



<!-- endsource: ru/_includes/reusables/support-button.md -->

