lct-50: таймеры ДДС — 30 с до открытия карточки, 3 минуты до первой записи
This commit is contained in:
parent
8ff51a8955
commit
51ef99c472
18 changed files with 169 additions and 169 deletions
|
|
@ -22,7 +22,7 @@ from app.domain.statuses import (
|
|||
)
|
||||
from app.domain.taxonomy import Competency, ErrorCode, Finding, FindingSource
|
||||
from app.domain.events import Metric
|
||||
from app.domain.timers import GOST_REF
|
||||
from app.domain.timers import GOST_REF, TimerCode
|
||||
|
||||
#: Статусы, означающие, что реагирование действительно шло.
|
||||
PROGRESS = (ServiceStatus.RESPONDING, ServiceStatus.ARRIVED, ServiceStatus.WORKING)
|
||||
|
|
@ -161,37 +161,37 @@ def evaluate_dispatcher(
|
|||
),
|
||||
))
|
||||
|
||||
# D1 — первичного статуса нет либо он проставлен позже норматива.
|
||||
# D1 — карточка открыта позже норматива или не открыта вовсе. 30 с идут
|
||||
# от появления карточки в строке сообщений до её открытия (ответ
|
||||
# заказчика, П.5); `elapsed_ms` — зафиксированное время открытия.
|
||||
if elapsed_ms is None or elapsed_ms > deadline_ms:
|
||||
findings.append(
|
||||
_finding(
|
||||
ErrorCode.D1,
|
||||
(f"{service}: карточка открыта с нарушением срока"
|
||||
if elapsed_ms is not None else f"{service}: карточка не открыта"),
|
||||
fact=(
|
||||
f"открыта через {elapsed_ms // 1000} с"
|
||||
if elapsed_ms is not None
|
||||
else "карточка не открыта до конца занятия"
|
||||
),
|
||||
norm=f"открыть карточку в течение {deadline_ms // 1000} с",
|
||||
)
|
||||
)
|
||||
|
||||
# D1 — первичного статуса нет: карточка ушла в «Не оповещено».
|
||||
primary = next((mark for mark in marks if mark.status in PRIMARY), None)
|
||||
if primary is None:
|
||||
findings.append(
|
||||
_finding(
|
||||
ErrorCode.D1,
|
||||
f"{service}: статус реагирования не проставлен",
|
||||
fact=(
|
||||
f"прошло {elapsed_ms // 1000} с"
|
||||
if elapsed_ms is not None
|
||||
else "карточка осталась без отметки"
|
||||
),
|
||||
norm=f"первичный статус в течение {deadline_ms // 1000} с",
|
||||
fact="карточка осталась без первичного статуса",
|
||||
norm="проставить «Принята» или «Не принята» с комментарием",
|
||||
)
|
||||
)
|
||||
continue
|
||||
|
||||
if elapsed_ms is None or elapsed_ms > deadline_ms:
|
||||
findings.append(
|
||||
_finding(
|
||||
ErrorCode.D1,
|
||||
f"{service}: первичный статус проставлен с нарушением срока",
|
||||
fact=(
|
||||
f"прошло {elapsed_ms // 1000} с"
|
||||
if elapsed_ms is not None
|
||||
else "время первичной отметки не зафиксировано"
|
||||
),
|
||||
norm=f"первичный статус в течение {deadline_ms // 1000} с",
|
||||
)
|
||||
)
|
||||
|
||||
for mark in marks:
|
||||
# D4 — отказ без комментария.
|
||||
if mark.status in REFUSAL_COMMENT_REQUIRED and not mark.comment.strip():
|
||||
|
|
@ -307,13 +307,14 @@ def dispatcher_metrics(
|
|||
))
|
||||
|
||||
primary = next((mark for mark in marks if mark.status in PRIMARY), None)
|
||||
elapsed = (int((primary.at - state.dispatched_at).total_seconds() * 1000)
|
||||
if primary and state.dispatched_at else None)
|
||||
# Время открытия — то, что зафиксировал таймер событием, а не разница
|
||||
# отметок: 30 с по ответу заказчика идут до открытия карточки.
|
||||
elapsed = state.timers.measured_ms(TimerCode.DDS_ACK)
|
||||
add("dds_primary", "решение по карточке", primary is not None,
|
||||
primary.status.value if primary else "решение отсутствует", "Принята или Не принята", 2.0)
|
||||
add("dds_ack", f"первичная отметка за {deadline_ms // 1000} с",
|
||||
add("dds_ack", f"открытие карточки за {deadline_ms // 1000} с",
|
||||
elapsed is not None and elapsed <= deadline_ms,
|
||||
f"{elapsed / 1000:.1f} с" if elapsed is not None else "не отмечено",
|
||||
f"{elapsed / 1000:.1f} с" if elapsed is not None else "карточка не открыта",
|
||||
f"≤ {deadline_ms // 1000} с")
|
||||
if primary is None:
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ def to_csv(report: SessionReport) -> bytes:
|
|||
row("Занятие", "", "Сценарий", report.scenario_id)
|
||||
row("Занятие", "", "Режим", report.mode.value)
|
||||
row("Занятие", "", "Попытка", report.attempt)
|
||||
row("Критерии", "", "Лимит решения ДДС, с", report.criteria.decision_time_limit_seconds)
|
||||
row("Критерии", "", "Лимит открытия карточки ДДС, с", report.criteria.decision_time_limit_seconds)
|
||||
row("Критерии", "", "Допустимо ошибок", report.criteria.allowed_errors)
|
||||
row("Критерии", "", "Грамматика обязательна", "да" if report.criteria.require_correct_grammar else "нет")
|
||||
row("Критерии", "", "Переопределения весов", report.criteria.score_weights or "стандартные")
|
||||
|
|
@ -150,7 +150,7 @@ def to_pdf(report: SessionReport) -> bytes:
|
|||
("Сценарий", report.scenario_id),
|
||||
("Режим", report.mode.value),
|
||||
("Попытка", report.attempt),
|
||||
("Лимит решения ДДС", f"{report.criteria.decision_time_limit_seconds} с"),
|
||||
("Лимит открытия карточки ДДС", f"{report.criteria.decision_time_limit_seconds} с"),
|
||||
("Допустимо ошибок", report.criteria.allowed_errors),
|
||||
("Грамматика обязательна", "да" if report.criteria.require_correct_grammar else "нет"),
|
||||
("Переопределения весов", report.criteria.score_weights or "стандартные"),
|
||||
|
|
|
|||
|
|
@ -44,11 +44,11 @@ CARD_FILL_TIME = TimeNorm(
|
|||
)
|
||||
DDS_WORK_TIME = TimeNorm(
|
||||
key="dds_work_time",
|
||||
title="Отработка карточки ДДС",
|
||||
summary="ДДС: норматив времени отработки карточки не выполнен",
|
||||
action="завершить",
|
||||
unmeasured="время обработки не зафиксировано",
|
||||
incomplete="карточка не завершена",
|
||||
title="Первая запись по карточке ДДС",
|
||||
summary="ДДС: первая запись по карточке позже норматива",
|
||||
action="открыть карточку и добавить первую запись (статус и текст)",
|
||||
unmeasured="карточка не открыта",
|
||||
incomplete="первая запись не добавлена",
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue