"""Thư viện drill chuẩn hệ thống — đọc từ `app/drills.json` (BRIEF 04/08/2026). File JSON trong repo chứ KHÔNG phải bảng `drills` trong DB, cố ý (khác design FullVision §7): Space không có Postgres vẫn phải demo được F3 — degraded mode là công dân hạng nhất. Bảng `drills` (tenant/HLV soạn) thuộc BRIEF sau khi có auth/roles. Vì thế `/api/drills` sống từ giây đầu boot, không cần engine/DB. Module cố ý KHÔNG import pooltool/poolcoach_rl — cùng lý do `app/db.py`: đọc drill không được kéo 40s JIT vào. """ from __future__ import annotations import json from pathlib import Path DRILLS_FILE = Path(__file__).resolve().parent / "drills.json" _cache: dict[str, dict] | None = None def all_drills() -> dict[str, dict]: """{id: drill} theo thứ tự file — nạp lần đầu rồi cache (file nằm trong repo, đổi nội dung là một lần deploy mới, không cần invalidate).""" global _cache if _cache is None: data = json.loads(DRILLS_FILE.read_text(encoding="utf-8")) _cache = {d["id"]: d for d in data["drills"]} return _cache def get_drill(drill_id: str) -> dict | None: return all_drills().get(drill_id)