lct-03 и lct-04: журнал сессий и библиотека сценариев
БД: 11 таблиц, первая миграция. Группы и связь trainee → group заложены
сразу, даже пустыми — размечать накопленные сессии задним числом значит
делать лишнюю миграцию. Номер попытки живёт в сессии, отдельной таблицы
попыток нет: дельта считается запросом по (trainee_id, scenario_id).
Сценарии: строгая схема — опечатка в имени поля падает на старте, а не
игнорируется молча. ground_truth собирается кодом, попытка задать
incident_type, dds или required_facts в YAML отвергается: иначе генератор
разведёт факты и эталон и курсанта оштрафуют за правильный ответ. Руками
задаются только нормализованные адрес и число пострадавших — из фразы
«улица Ленина, 14, квартира 47, 5-й этаж» кодом «улица Ленина, 14»
не достать.
GET /api/scenarios/{id} больше не отдаёт чек-лист. Это содержимое
подсказок: отдать его целиком значит выдать в контрольном режиме то,
чего там быть не должно, в обход выдачи по одному пункту.
Тесты базы поднимают свой движок на каждый тест: глобальный кэшируется
и привязывается к первому событийному циклу.
This commit is contained in:
parent
59d5a6a26d
commit
6b2c96bab6
22 changed files with 1380 additions and 8 deletions
|
|
@ -4,17 +4,36 @@ from contextlib import asynccontextmanager
|
|||
|
||||
from fastapi import FastAPI
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from app.api.http import scenarios as scenarios_api
|
||||
from app.api.http import sessions
|
||||
from app.config import get_settings
|
||||
from app.scenarios import store
|
||||
from app.scenarios.loader import ScenarioError
|
||||
|
||||
|
||||
LIBRARY = Path(__file__).resolve().parents[2] / "scenarios"
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
# Прогрев моделей и валидация сценариев — карточки lct-04 и lct-06.
|
||||
# Библиотека проверяется на старте целиком: сломанный сценарий, найденный
|
||||
# посреди занятия, — сценарий, которого не должно случиться.
|
||||
try:
|
||||
loaded = store.load_from_disk(LIBRARY)
|
||||
except ScenarioError as exc:
|
||||
raise RuntimeError(f"библиотека сценариев не прошла проверку: {exc}") from exc
|
||||
app.state.scenarios_loaded = len(loaded)
|
||||
|
||||
# Прогрев моделей — карточка lct-06.
|
||||
app.state.models_ready = False
|
||||
yield
|
||||
|
||||
|
||||
app = FastAPI(title="Учебный симулятор занятия для системы 112", lifespan=lifespan)
|
||||
app.include_router(sessions.router)
|
||||
app.include_router(scenarios_api.router)
|
||||
|
||||
|
||||
@app.get("/api/health")
|
||||
|
|
@ -24,5 +43,6 @@ async def health() -> dict:
|
|||
return {
|
||||
"status": "ok",
|
||||
"models_ready": getattr(app.state, "models_ready", False),
|
||||
"scenarios_loaded": getattr(app.state, "scenarios_loaded", 0),
|
||||
"offline": settings.offline,
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue