Перейти к основному содержимому

Как устроено

Четыре понятия, через которые описывается всё остальное: пак, вариант данных, проверка и закрытая часть пака.

Пак — контракт между автором и студентом

Пак это git-каталог. Студия автора его пишет, раннер студента читает, CI преподавателя читает то же самое.

структура пака
packs/<практика>/
domain.json описание базы, темы курса, DDL
tasks.json задания
materializations/<id>.json эталон, спека данных, варианты, проверки, негативы
migrations/
common/ создание схемы
tasks/<id>/ INSERT-ы вариантов данных
report/index.md отчёт приёмки этапа 3
theme/ оформление курса
state.json что утверждено, хэши

Утверждения держатся на хэшах, а не на честном слове. domain.json при утверждении получает content_hash, задания запоминают, к какой версии области они сделаны, каждая материализация помнит source_hash своего задания. Поменяли формулировку задания — материализация помечается устаревшей, и студия скажет об этом до того, как пак уедет студентам.

Косметические правки сделаны исключением: у области это документация таблиц, у задания — «человеческая» формулировка business_statement. Их можно править, не переделывая проверки.

Вариант данных

Вариант — это конкретный набор строк, полученный из спеки данных и seed'а. Спека объявляет:

  • классовые колонки — то, что делит строки на смысловые группы: активна кофейня или закрыта, есть у партии регион или NULL;
  • квоты — сколько строк какого класса должно быть в этом варианте;
  • крайние случаи — то, что обязано существовать при любом seed'е: клиент без заказов, нулевая сумма, единственная строка.

Дальше движок строит варианты сам: сначала систематические крайности (каждый класс пуст, каждый класс единственный), потом случайные комбинации квот. Типичное задание получает около пятидесяти вариантов.

53 варианта данных · 49 сошлось · 4 нет

Три варианта — именованные примеры, они открыты студенту: «нет активных», «только активные», «смесь». Вместе они покрывают ветки задания, и по ним студент понимает, что от него хотят.

Проверка

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

Типы проверок:

ТипЧто сравнивает
schemaнабор и порядок колонок результата
cardinalityсколько строк ожидается: одна, много, допустимо ноль
result_exactрезультат построчно (открытые примеры)
result_hashхэш нормализованного результата (скрытые варианты)
table_stateсостояние таблиц после INSERT/UPDATE/DELETE
db_schemaструктура схемы после CREATE/ALTER
sql_constraintsобязательные и запрещённые конструкции в тексте решения

sql_constraints разбирает решение как SQL, а не ищет подстроки: если задание требует DISTINCT, а решение получает уникальность через GROUP BY, проверка это увидит.

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

Что скрыто от студента

Инвариант, который система держит специально: ожидаемые результаты скрытых вариантов не покидают бэкенд.

  • Открытые примеры отдаются целиком — они для этого и сделаны.
  • Скрытый вариант отдаётся студенту только после того, как его решение на этом варианте упало: тогда видны данные варианта, ожидаемый результат и построчное сравнение.
  • Всё остальное лежит в закрытой части пака и наружу не уходит.
Про честность защиты

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

Кто что запускает

автор

gen studio

Студия на localhost:8765. Нужен Docker: под каждый прогон поднимается эфемерный Postgres.

студент

docker compose up

Раннер на localhost:8766 плюс Postgres с живой и проверочной базами.

преподаватель

runner ci

Тот же образ в CI: читает solutions/ студента и выдаёт отчёт по заданиям.