# Спецификация 05: метрики и план/факт Источники: Ф-9.4/Ф-9.5, m04 (workout_metrics), дизайн LLM-планирования разд. 2 (body). Только чтение (🛡3). ## 1. Метрики `GET /api/admin/metrics?athleteId&dateFrom&dateTo` (Bearer) → ```json {"workouts":[{"workoutId":"…","date":"2026-10-14","adherence":100.0, "tonnage":640.0,"tonnageByGroup":{"push":640.0}, "e1pmByExercise":{"":120.0},"redFlags":[]}], "weekly":[{"week":"2026-10-12","workouts":2,"avgAdherence":85.0, "tonnage":2400.0}]} ``` - по тренировкам — строки `workout_metrics` периода (поля как в БД; JSON-поля — как есть); - `weekly` — группировка по ISO-неделе даты тренировки: число тренировок, среднее adherence, сумма тоннажа. ## 2. План/факт (PlanSummaryService) `GET /api/admin/plan?athleteId` → сводка по активной версии: ```json {"activeVersion":3,"weeks":[{"week":1,"from":"2026-10-05","to":"2026-10-11", "planned":2,"performed":1,"missed":1,"avgAdherence":100.0}]} ``` - неделя N активной версии: `from` = понедельник недели создания версии + 7×(N−1) дней; `to` = from+6; - `planned` — число сессий в `weeks[N-1].sessions` (body; в v1 все недели одинаковые по составу — считаем по своей неделе массива); - `performed` — тренировки атлета за [from..to] **в плановые дни недели** (day-of-week сессии; день без сессии в плане не считается); - `missed` = planned − performed (не < 0); - `avgAdherence` — среднее adherence этих тренировок (нет — null); - активной версии нет → `{"activeVersion":null,"weeks":[]}`.