7.5 KiB
Требования к модулю: m04-metrics-engine
Модуль — сервис
MetricsEngineвServer.WatchBody.Core: детерминированный расчёт метрик тренировки (adherence, тоннаж, оценочный 1ПМ, пульс-метрики, красные флаги) после каждой синхронизированной тренировки →src.workout_metrics(1:1, upsert). Источники: Ф-12.1/Ф-12.5, Ф-13.5, документ метрик (..\..\..\Метрики_тренировок_и_самоконтроля.md, п. 2.5, правила 1–6), архитектура (строкаMetricsEngine), дизайн LLM-планирования разд. 4. Самодостаточная копия требований (d-dev-6).
1. Назначение и границы
В границах модуля:
- класс
MetricsEngine(Server.WatchBody.Core, каталогMetrics\): расчёт метрик одной тренировки атлета по его данным и запись вworkout_metrics(upsert — пересчёт разрешён); - вызов из m02: после успешного коммита пакета sync MetricsEngine пересчитывает затронутые тренировки (Ф-12.1 «после каждой синхронизированной тренировки»); сбой расчёта не откатывает sync (метрики — производные данные, пересчитываются повторно);
- пороги красных флагов — из конфигурации
Safety.*сервера (Р3-А; умолчания — документ метрик, Ф-13.5); - тесты сервиса (интеграционные, docker
watchbody-pg).
Вне границ модуля: правила прогрессии/делоада и создание
draft-версий (m05 — читает workout_metrics и workout_set);
парсинг .fit (m06 — кладёт факты в workout.facts_json/avg_hr/
hr_recovery_s до расчёта); отображение метрик (телефон m09/m10,
AdminWeb m08 — читают workout_metrics_select); расчёт adherence
«за период» и еженедельные сводки (п. 2.5 документа метрик, не
названные в v1) — по потребности m05/m08; перерывы auto по
пропускам (Ф-14.1 — отдельная логика, не метрика).
2. Состав метрик (контракт документа метрик, v1)
Поле workout_metrics |
Расчёт (детерминированно) |
|---|---|
adherence |
% подходов «по плану» (workout_set.in_plan) от планового числа подходов сессии в активной версии программы (body, схема дизайна LLM-планирования разд. 2); план/сессию не удалось сопоставить → % in_plan среди подходов тренировки |
tonnage |
Σ (weight_kg × reps) по всем подходам с weight>0, reps>0 |
tonnage_by_group |
тот же Σ по группам упражнений (exercise.group), код группы → кг |
e1pm_by_exercise |
формула Эпли (ОВ-7): w × (1 + reps/30) по лучшему (максимальному весу) подходу каждого упражнения |
hr_metrics |
из workout.facts_json (.fit, если уже импортирован): средний/пиковый пульс, отдых между подходами; нет фактов → {avg_hr, hr_recovery_s} из workout (то, что прислал телефон/.fit-импорт) |
red_flags |
сработавшие красные флаги (см. разд. 3) |
3. Красные флаги (v1 — документ метрик, правила 1, 6; Ф-12.5)
| Флаг | Условие | Источник данных |
|---|---|---|
bp_over_150_90 |
АД дня тренировки > 150/90 (пороги Safety.BpCancelSys/Dias) |
daily_log дня тренировки |
bp_elevated |
АД в коридоре 140–150/90–95 | daily_log дня тренировки |
hr_resting_up |
пульс покоя ≥ базового +8 уд/мин (Safety.HrRestingRise) 2 дня подряд |
daily_log (тренд за 2 дня до дня тренировки; базовый = среднее за предыдущие 14 дней, при <3 значениях базового флаг не ставится) |
wellbeing_low |
самочувствие ≤ 2 (Safety.WellbeingLow) 2 дня подряд |
daily_log |
cancel_recommendation |
hr_resting_up/wellbeing_low держится 3+ дня → предложение отмены и совет к врачу |
daily_log |
knee_pain_repeat |
боль в колене ≥ 1 (Safety.KneePainMin) в двух занятиях подряд (сеты группы «ноги») |
workout_set.knee_pain предыдущей и текущей тренировки |
Флаги — накопленный список фактов сработавших условий с датами;
значения порогов в red_flags не дублируются. 🛡 Пороги — только из
конфигурации, в коде не хардкодятся (Р3-А).
4. Инварианты (🛡 — нарушать запрещено)
- Изоляция атлета — расчёт только по данным одного
athleteId; все входные выборки — по нему (репозитории m01). - Метрики — производные данные — upsert разрешён всегда (пересчёт); sync атлета не может «сломать» метрики другого.
- Без побочных эффектов на план — MetricsEngine ничего не пишет
в
workout/workout_set/program_version(это m05); толькоworkout_metrics. - Сбой расчёта не ломает sync — исключение расчёта метрик логируется, пакет sync остаётся принятым.
- Детерминированность — тот же вход → тот же выход; никакого LLM.
5. Критерии приёмки модуля
- После sync тренировки с подходами
workout_metricsзаполнен: adherence/tonnage/tonnage_by_group/e1pm (Эпли проверяется вручную посчитанным значением)/hr_metrics. - Повторный расчёт (повторный sync того же пакета) не создаёт вторую строку (upsert 1:1).
- Красные флаги: сценарии АД>150/90, пульс покоя +8 два дня,
самочувствие ≤2, колено ≥1 два занятия — флаги ставятся; чистые
данные —
red_flagsпустой. - Изоляция: расчёт атлета А не видит данные атлета Б.
- Сбой расчёта метрик не мешает принятию пакета sync.
- Тесты интеграционные против docker
watchbody-pg— зелёные; сборка решения без ошибок.