make - FrBrGeorge/HWorker GitHub Wiki
Некоторый аналог GNU Make, с тремя базовыми функциями.
- Знает, как делать объект-генерат из других объектов. Для этого читает конфиги, и/или использует хардкоднутые правила; используется API других модулей.
- Умеет удалять генераты, исходный объект которых удалён из depot (например, удалили чекер — удалить все результаты проверки с его помощью)
- Умеет выделять объекты, исходные материалы которых обновились, и их надо переделать. Строит список — линеаризацию зависимостей таких объектов. Умеет обходить этот список, изготавливая новые акутальные объекты.
- В числе прочего умеет вычислять отбъекты, которые в данный момент отсутствуют, но создавать их надо. Например, при появлении нового задания (и объектов-домашек) из них нужно сконструировать отъекты-решения и объекты-чекеры, которыех в данный момент нет в depot.
На первое время вместо приведённой ниже логики предлагается полностью переделывать всё дерево объектов. Можно ограничиться хардкоднутой схемой с проверкой актуальности (см. Proposal 2 вообще без графов). Как минимум проверка актуальности нужна для обновления CheckResult (см. Proposal 0).
Наиболее тяжёлый компонент системы — пересчёт CheckResult, особенно runtime; его стоит оптимизировать в первую очередь. Полная перегенерация при этом выгляит так:
- Раскрываем все актуальные домашки в
Check-и иSolution-ы - Для каждого актуального
Solution- Берём список чеков
- Составляем список предполагаемых ID
CheckResult-ов - Нужно запустить
Checkна данномSolutionи создать новый (обновить имеющийся)CheckResult, если- Соответствующий
CheckResultне существует -
CheckResult.SolutionTimestampменьше (более ранний), чемSolution.timestamp -
CheckResult.CheckTimestampменьше (более ранний), чемCheck.timestamp
- Соответствующий
- Полное пероценивание
CheckResult→TaskScore - Полное пероценивание
TaskScore→UserScore - Полное пероценивание
UserScore→FinalScore
Полое скачивание и публикацию в процедуру полной перегенерации включать не надо: скачивание зависит от работы сети и может отвалиться, а публикатор по дизайну работает отдельным процессом.
Есть у нас подсистема depot, которая хранит объекты и их паспорта (включая timestamp-ы). Есть описания вида «При проверке решения задачи №7 используется чекер WhatCheck». 0. Загружаем в память все паспорта объектов. Это узлы графа, однако дуг ещё нет.
- Парсим описания, выделяя из них зависимости одних объектов от других, создавая при необходимости новые объекты, и расставляем дуги вида «Объект A нужен для объекта B»
- Например, правило выше интерпретируется так: для всех объектов-решений SolutionID, при условии, что это решение задачи №7, создать пустой (сверхстарый) объект ResultID, если его нет, и поставить две дуги: SolutionID → ResultID и WhatTest → ResultID.
- Выделяем (взможно, несвязный) подграф, состоящий из вершин и дуг вида Старый объект → Более новый объект (пользуять timestamp)
- Возвращаем линеаризацию этого подграфа, то есть последовательность вершин A₀, A₁, A₂ …, такую что для вершины An не нужны вершины An-i, т. е. An→Am ⇒ n < m
На основании знаний о том, какие объекты изготавливаются из каких, располагаем их по уровням (возможно, хардкодом): для объектов очередного уровня нужны только объекты строго более низких уровней (например, для промежуточных оценок нужны результаты, значит оценки уровнем выше результатов; для результатов нужны решения и чекеры — они ещё одним уровнем ниже). Затем проходим по каждому уровню, начиная с нижнего, и изготавливаем каждый объект, если он просрочен (для него нужны более новые объекты более нижнего уровня).