Всероссийский школьный этап всероссийской олимпиады по информатике

Правка ru8, от dkirienko, 2021-11-03 12:39:48

В этом году случилось уникальное событие — для большинства школьников России школьный этап всероссийской олимпиады школьников по информатике проводился по едиными правилам, общим комплектам задач (всего было 4 варианта заданий на всю страну), с использованием тестирующей системы.

Организация

Организационной стороной занимался образовательный центр "Сириус", который взялся провести школьный этап всероссийской олимпиады по шести предметам — математике, информатике, физике, химии, биологии, астрономии. В прошлом году уже была апробация для шести регионов, в этом году всем желающим регионам было предложено принять участие. Согласились почти все — проще перечислить регионы, которые не участвовали (по убыванию численности населения): Московская область, Красноярский край, Вологодская область, Алтайский край, Омская область, Республика Крым, Пермский край, Пензенская область, Тверская область, Забайкальский край, Амурская область, Республика Марий Эл, Республика Карелия, Новгородская область, Республика Хакасия, Республика Ингушетия, Республика Алтай, Чукотский автономный округ, Ненецкий автономный округ. Я не включил в этот список Москву — хотя она и не участвовала в школьном этапе, проводимом Сириусом, но всё равно школьный этап для Москвы проводился по тем же заданиями и тем же правилам. На самом деле наоборот — правила и принципы составления задания были взяты московские, и московский формат проведения школьного этапа олимпиады был применён на всю страну.

Всего вместе с Москвой участвовало свыше 80% регионов России (если считать по численности населения).

Все регионы были разбиты на четыре группы, примерно равной по численности населения, расположенные примерно в одних часовых поясах. Первая и вторая группа — это московский часовой пояс, третья группа — это MSK+1 и MSK+2, четвёртая группа — от MSK+4 до MSK+9. Тут я (и многие коллеги) впервые узнали, что в зоне MSK+3 находится всего лишь один регион — Омская область, которая не участвовала в проекте. Для каждой группы был установлен свой день проведения — с 26 по 29 октября.

Авторы заданий

Задания разрабатывал большой коллектив авторов, разбитый на четыре рабочие группы. Огромная благодарность всем авторам за то, что они сделали четыре хороших комплекта заданий. Также отдельное спасибо MikeMirzayanov за систему полигон, которая использовалась для подготовки всех заданий.

Логины для участия в олимпиаде распространялись по школам через ФИС ОКО (федеральная информационная система оценки качества образования), доступ к которой есть у всех школ. Школам выдавались логины по числу учащихся +10% запаса. Регламент проведения олимпиады предусматривал возможность участия с 8 до 20 часов по местному времени, реально же возможность участия была от 8 утра в самом раннем регионе до 20 часов в самом позднем.

Содержание заданий

Олимпиада проводилась для 5-11 классов по формату заданий, принятому в Москве в последние годы.

Для 9-11 классов предлагалось 5 задач по программированию на двухчасовой тур. Примерный план варианта — формула (целочисленная арифметика), задача на использование if, задача на цикл, задача на массив, идейная задача. Система оценивания — потестовая, все тесты независимые, хотя в условия и выделяются подзадачи по ограничениям или частным случаям, но групп тестов и зависимостей между тестами нет. Задачи доступны в тренировках: первая группа, вторая группа, третья группа, четвёртая группа.

Для 7-8 классов предлагается смешанный вариант. Статистика показывает, что лишь небольшая часть школьников 7-8 классов, участвующих в олимпиаде умеет программировать (например, статистика этого школьного этапа — около 10% участников сдавало задачи по программированию), поэтому участникам предлагается 4 задачи с вводом ответа и 3 задачи по программированию. Задачи с вводом ответа — это по-сути output-only задачи, которые, скорее всего, можно решить без использования компьютера. Ответ на них нужно записать в поле ввода ответа. Это похоже на формат олимпиад по математике в дистанционной форме, но благодаря чекеру можно выставляють произвольные баллы за решения, например, оценивать алгоритм для исполнителя по числу использованных команд. Об этом формате проведения олимпиады было опубликовано несколько статей. При этом считает, что 7 задач много для тура, а школьники могут выбирать понравившиеся задачи, поэтому оцениваются только 5 задач из 7 с наилучшим результатом. Продолжительность тура — 2 часа.

При этом сильные программирующие школьники 7-8 классов могли писать олимпиаду за 9 класс.

Для 5-6 классов предлагается вариант без программирования, только из 5 output-only задач. Продолжительность тура — 45 минут.

Условия задач, решения, архивы и видеоразборы опубликованы: группа 1, группа 2, группа 3, группа 4.

Тестирующая система

Тестирующая система должна удовлетворять ряду требований: держать несколько десятков тысяч пользователей одновременно, справляться с проверкой задач по программированию (тут в пиковые моменты нужно было порядка 40 инвокеров, благо при составлении задач было требование не делать большое число тестов по задачам), поддерживать output-only задачи. И выполнить все эти требования одновременно вместе оказалось довольно сложно.

Для проведения дистанционных олимпиад по другим предметам Сириус использует собственную тестируюущую систему. Она специально была разработана для проведения подобных мероприятий, поэтому там довольно просто реализован механизм входа и регистрации (вместо пары логин-пароль используется один "ключ", затем нужно ввести фамилию-имя, затем можно переходить к олимпиаде) и умеет держать нужную нагрузку. В ней уже есть поддержка задач по программированию и проведены соревнования на несколько сотен участников, однако, на соревнованиях по программированию на тысячах участников система ещё не использовалась. Кроме того, поддержка output-only задач в настоящий момент не достигла нужного нам уровня, например, нет возможности выставлять в качестве оценки за решение произвольное число от 0 до 100.

Codeforces хоть и умеет держать нужное количество пользователей (если считать число участников Div.3 раундов, которое превышает 20.000, что примерно нам и нужно), но совсем не поддерживает output-only задачи.

Яндекс-контест мы пробовали использовать в прошлом году в ходе пилотного проведения школьного этапа для нескольких регионов, с его помощью можно добиться желаемого формата проведения олимпиады, однако, это довольно сложно сделать. Например, ввод фамилии-имени участника при регистрации осуществлялся при помощи добавления в контест "нулевой" задачи, без сдачи которой нельзя перейти к следующим задачам, а это усложняет подведение результатов (нужно отдельно выгружать архив сабмитов, считывать его программно и сливать с таблицей результатов). Задачи вида output-only приходится проверять повторно после окончания тура с подменой чекера. Все массовые операции вида "создать пользователей", "выгрузить архив решений", "провести перетестирование" требуют привлечения поддержки и занимают очень много времени. Наконец, у Яндекс-контеста при переходе его на новый уровень нагрузки могут вылезить проблемы в неизвестных ранее местах, так, например, год назад 20 тысяч одновременно пытавшихся открыть страницу Яндекс.контеста пользователей полностью положили его. Допустить что-то подобное на мероприятии такого уровне не хотелось бы.

Поэтому использовался ejudge, который много лет использовался для проведения олимпиад в Москве.

ejudge, разумеется, имеет большое число недостатков, связанных прежде всего с тем, что система разрабатывается более 20 лет и её архитектура соответствует взглядам 20-летней давности. При разработке ejudge просто не закладывалась идея, что в контесте могут быть десятки тысяч одновременных пользователей и сотни тысяч пользователей всего. Все пользовательские запросы, например, обрабатываются процессом ej-contests, который работает в один поток и никак не распараллеливается. Поэтому, кажется, предел возможностей ejudge — это около 4000 одновременных пользователей на мощном компьютере, при большем числе пользователей ej-contests уже не успевает обрабатывать запросы пользователей.

В ejudge плохо организована работа с базой пользователей, например, запуск контеста (и выполнение действия reload config files) влечёт считывание всей базы пользователей в память, что занимает ощутимое время и требует оперативной памяти для хранения ненужной базы пользователей.

Год назад в результате возникших проблем с добавлением пользователей в коде ejudge мною были найдены вшитые ограничения:

#define EJ_MAX_USER_ID  999999
#define MAX_USER_ID_32DIGITS 4

Последняя строчка ограничивает размер поля для хранения USER_ID 20 битами. При этом для проведения школьного этапа в этом году было сгенерировано порядка 10 миллионов логинов в систему. При этом сразу же после проведения тура все "неиспользованные" логины

Но при этом ejudge проверена и предсказуема. Известно, что один сервер ejudge может держать 3000 одновременных пользователей, и дальше можно распределить нагрузку можно созданием отдельных серверов так, чтобы на каждый из них приходилось не более 3.000 одновременных пользователей (и около 15.000 пользователей за день проведения тура).

Поэтому для проведения олимпиады использовалось несколько независимых серверов так, чтобы ожидаемое максимальное число пользователей составляло порядка 2000 на одном сервере. Каждая из четырёх групп регионов разбивалась на подгруппы по ожидаемому числу участников: первая и третья группы были разбиты на две подгруппы, вторая группы — на три подгруппы, четвёртую восточную группу разбивать не пришлось. Итого получилось 8 подгрупп и 24 сервера (для групп классов также использовались отдельные сервера), плюс 3 сервера для Москвы. Но для проведения туров одновременно использовались только сервера одной группы, то есть при проведении школьного этапа для второй группы + Москвы было задействовано 12 одновременно работающих фронтенд-серверов.

Все сервера находятся в облаке AWS, благодаря чему процесс клонирования серверов довольно прост.

Таким образом, для участия в олимпиаде школьник должен иметь помимо логина и пароля ещё и ссылку на вход в тестирующую систему, которая разная для разных серверов. Для этого мы в последние годы используем сервис сокращения ссылок to.click, которому мы благодарны за поддержку и всяческую помощь.

Проблемы

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

Проблемы с серьёзными DDOS-атаками в последние годы возникали у организаторов школьного этапа в Московской области, я же некоторое время считал, что лучший способ защиты от DDOS-атак — это просто хранить в секрете адреса серверов, не публикуя ссылки на вход в тестирующую систему в открытом доступе. Но при увеличении масштаба мероприятия этот метод уже перестал работать. Впервые c DDOS-атакой при проведении школьного этапа мы столкнулись год назад, тогда без видимых причин выросла нагрузка на CPU и сеть на одном из серверов и происходило ощутимое замедление отклика сервера (это было год назад на московском сервере для олимпиады 9-11 классов), но точно идентифицировать атаку по логам не удалось.

Поэтому (по примеру Московской области) теперь все сервера находятся за Cloudflare. Но оказалось, что недостаточно просто завести сервера за Cloudflare, нужно ещё и с настройками разобраться.

Первая DDOS-атака началась 27 октября в 20:00. В это время заканчивался тур для Москвы, поскольку для регионов проведение тура по регламенту до 20:00. Атака заключалась в загрузке страницы входа в систему, в минуту число запросов доходило до 2 миллионов. При этом Cloudflare распознал атаку и успешно блокировал запросы, т.е. тестирующая система продолжала работать. Но часть участников (по-видимому, те участники, у которых массово совпадали IP-адреса) также были "распознаны" Cloudflare, как атака, и им тоже был заблокирован доступ в тестирующую систему.

Вторая DDOS-атака случилась 28 октября в 13:13 по московскому времени (если "автор" этой атаки читает этот пост, то да, мы "оценили" его шутку). Она была гораздо более длительной и продолжалась свыше 5 часов. Мне кажется, что вторая атака не связана с первой — первая была направлена на московский сервер, здесь атака шла на сервер для регионов. Но сценарий оказался точно таким же — Cloudflare начал блокировать атаку и некоторых участников. По моим оценкам, трудности доступа к тестирующей системе из-за блокировки Cloufflare возникли у 30% участников олимпиады, для остальных же тур продолжался, т.к. с тестирующей системой проблем не было.

Примерно через 1 час 10 минут после начала атаки удалось разобраться с настройками Cloudflare, и вместо блокировки атакующих была включена капча, т.е. все заблокированные участники могли добраться до тестирующей системы при помощи ввода капчи. После этого атака продолжалась ещё более 4 часов, но никаких затруднений (помимо ввода капчи) у участников уже не было. Для компенсации трудностей тур был продлён до ночи, а участникам, которые не смогли сдать решения, предлагалось сделать это повторно под новым логином.

Списывания

К сожалению, при таком формате проведения олимпиады задания сливаются в интернет в течение первого часа, а вскоре появляются и их решения. Главный вред от этого в том, что большое число копи-пастеров найденных решений вытесняют из таблицы результатов честных участников и не дают им возможности пройти на муниципальный этап, поскольку число участников муниципального этапа ограничено. Возникает необходимость очистить результаты от "мусорных" участников. Но стандартные алгоритмы, которые используются на подобных соревнованиях, предполагающие попарное сравнение решений членом жюри, здесь не сработают, потому что решений очень много и списываний очень много, сравнивать попарно решения нет никакой возможности. Да и сценарий списываний тут другой — есть некоторое количество решений, которые были слиты в интернет, и участники сдавали эти решения, как правило, без каких либо модификаций. Хотя модицификации возникают, например, при копи-пасте решений часто появляются лишние пустые строки. Или есть другой интересный эффект, при копировании решений с одного из сайтов участники зачастую копирую и номера строк, которые записаны в первом столбце таблицы вёрстки кода, получается такой код:

1
2
3
4
5
6
7
N = int(input())
K = int(input())
if 1 <= N <= 10 ** 4:
    if (1 <= K <= N) and ((N % K) == 0):
        print(2 * N * (N // K - 1))
else:
    print(0)

Но этот код с точки зрения языка Python является корректным и набирает столько же баллов!

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

Печальная статистика заключается в том, что в целом среди участников 9-11 классов, которые набрали больше 0 баллов, минимум 58% использовало чужие решения. Доля "списывальщиков" разнится от региона к региону, в отдельных регионах доходя до 90% участников.

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

Статистика

Публикую два файла со статистикой.

  1. Число участников по регионам в каждой группе. Здесь удалены найденные списанные решения и в 9-11 классах посчитано число участников, имеющих ненулевые баллы после этого.

  2. Статитистика по используемым языкам программирования. Учитывается только 9-11 класс, после проверки на списывание. Считается, что участник использовал язык программирования, если набрал больше 0 баллов, сдавая решения на этом языке.

История

 
 
 
 
Правки
 
 
  Rev. Язык Кто Когда Δ Комментарий
ru30 Русский dkirienko 2021-11-08 19:51:29 391
ru29 Русский dkirienko 2021-11-08 18:37:10 32
ru28 Русский dkirienko 2021-11-07 21:30:55 45
ru27 Русский dkirienko 2021-11-07 20:31:55 189 Ссылка на московскую статистику по языкам программирования.
ru26 Русский dkirienko 2021-11-07 20:14:25 10
ru25 Русский dkirienko 2021-11-07 20:04:10 0 (опубликовано)
ru24 Русский dkirienko 2021-11-07 20:02:22 11 Мелкая правка: 'сценария. Трудностей с тестиру' -> 'сценария. Проблем с тестиру'
ru23 Русский dkirienko 2021-11-07 20:00:21 95
ru22 Русский dkirienko 2021-11-07 19:57:06 488
ru21 Русский dkirienko 2021-11-07 19:43:05 2261
ru20 Русский dkirienko 2021-11-03 15:19:15 1 Мелкая правка: 'ую копирую и номера ' -> 'ую копируют и номера '
ru19 Русский dkirienko 2021-11-03 14:21:16 5
ru18 Русский dkirienko 2021-11-03 13:57:49 238
ru17 Русский dkirienko 2021-11-03 13:37:28 111
ru16 Русский dkirienko 2021-11-03 13:28:45 71
ru15 Русский dkirienko 2021-11-03 13:23:15 2 Мелкая правка: 'ровки Cloufflare возн' -> 'ровки Cloudflare возн'
ru14 Русский dkirienko 2021-11-03 13:20:39 2 Мелкая правка: 'орая группы &mdash; н' -> 'орая группа &mdash; н'
ru13 Русский dkirienko 2021-11-03 13:16:38 866
ru12 Русский dkirienko 2021-11-03 13:13:32 176
ru11 Русский dkirienko 2021-11-03 13:08:15 143
ru10 Русский dkirienko 2021-11-03 13:02:06 2 Мелкая правка: 'n2. [Статитистика по' -> 'n2. [Статистика по'
ru9 Русский dkirienko 2021-11-03 12:59:11 1170
ru8 Русский dkirienko 2021-11-03 12:39:48 890
ru7 Русский dkirienko 2021-11-03 11:40:40 2329
ru6 Русский dkirienko 2021-11-03 10:40:46 2886
ru5 Русский dkirienko 2021-11-03 10:18:06 1097
ru4 Русский dkirienko 2021-11-03 10:01:19 7674
ru3 Русский dkirienko 2021-11-02 22:47:02 1666
ru2 Русский dkirienko 2021-10-31 21:07:27 2223
ru1 Русский dkirienko 2021-10-31 20:34:21 1676 Первая редакция (сохранено в черновиках)