Commit graph lct-hack/backend/app/session/timers.py
Author SHA1 Message Date
Ivan Gerasimov
57f4c858b6 lct-22: пульт директив — преподаватель ведёт ситуацию
Мягкие директивы перекрывают дугу сценария и применяются со следующей
реплики: разговор не дёргается от того, что преподаватель что-то нажал.
Жёсткие правят ситуацию — обрыв связи рвёт звук тем же механизмом, что
перебивание, и запускает норматив обратного дозвона; второй пострадавший
правит эталон; неточный адрес снимает раскрытый факт, и оператор обязан
переспросить.

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

Свободный текст честно отказывает: офлайн-дерево предгенерировано,
произвольную фразу взять неоткуда, и преподаватель видит это на пульте.

Ни одна директива не трогает карточку курсанта — он управляет ситуацией,
а не работой обучаемого.

Занятие теперь собирается целиком и только потом регистрируется:
наблюдатель мог увидеть его без слот-автомата и звонящего.
2026-09-17 21:38:43 +03:00
Ivan Gerasimov
f01f2dab76 lct-12: детерминированная оценка по ГОСТ, таксономия, радар
Каждая метрика — факт против норматива со ссылкой: «94 с при ≤ 75 с,
ГОСТ Р 22.7.03-2021», а не балл. По недобытому факту — отдельная отметка
E1 с эталонным вопросом: в разборе нужен конкретный вопрос, не процент.
Радар — проекция тех же метрик без пересчёта весов, коммуникация без
судьи не рисуется нулём.

Таймер, не остановленный событием, — провал, а не зачёт: время
недоказуемо, операция не завершена. Метрика, которую нечем посчитать
(полнота опроса без модели эмбеддингов), видна как «не посчитано» —
молча выброшенная выглядела бы пройденной.

Найдено противоречие: таймеры опроса (75 с) и оповещения ДДС (60 с)
стартовали на ответе и останавливались передачей в ДДС — один отрезок,
два лимита. Опрос за законные 70 с давал E3, а на экране курсанта
краснел таймер посреди нормального разговора. События «опрос закончен»
в контракте нет, поэтому dds_notify снят с учёта, вопрос записан в
CONTRACT.md.

KIO проверяет присваивание: card.dds = "03" клало в карточку сырую
строку вместо кода ДДС, и падала уже оценка, далеко от места ошибки.
2026-09-17 14:06:16 +03:00
Ivan Gerasimov
e7a0798ba7 lct-05: состояние сессии, таймеры по событиям, четыре канала
Таймеры объявлены таблицей «событие → старт/стоп», а не разбросаны
по обработчикам: так видно целиком, что чем запускается, и норматив
нельзя потерять по дороге. Опрос стартует на ответе курсанта и
останавливается передачей в ДДС — событием, а не таймаутом.

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

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

Тикер таймеров гасится при остановке приложения, иначе задачи переживают
выключение и держат событийный цикл.

Проверено вживую через uvicorn: монитор, подключённый посреди занятия,
получает снимок с заполненной карточкой; такт таймера идёт раз в секунду.
2026-09-16 02:07:27 +03:00