VEU.WathBody/1-docs/4-modules/m05-progression-rules/api_specs/04-breaks.md

4.3 KiB
Raw Permalink Blame History

Спецификация 04: перерывы — BreakEngine (Ф-14, документ перерывов 3.1–3.3)

1. Сигнатуры

public bool DetectBreak(int athleteId, DateOnly today);          // true — break открыт
public ProgramVersion? CloseOnReturn(int athleteId, Guid workoutId, DateOnly today);

(today — явный параметр для тестируемости; sync передаёт текущую дату UTC. CloseOnReturn сам читает тренировку по id — в sync есть только идентификатор.)

Вызов из sync (spec 05): DetectBreak — до записи пакета не нужен; вызывается после коммита пакета вместе с правилами. CloseOnReturn — когда пакет содержит workout (первая сессия после break).

2. DetectBreak — авто-детект (Ф-14.1)

  1. Открытый break есть (BreakRepository.Select, ended_on = NULL, последний по started_on) → false.
  2. Активной версии нет → false.
  3. Окно [today − MissDaysForBreak + 1 .. today] (умолчание 4 дня). Плановые дни недели в окне — по body.weeks[].sessions[].day (v1 все недели одинаковы). День плановый и по нему нет тренировки (workout с датой started_at::date = день) — пропуск.
  4. Пропущены все плановые дни окна → BreakRepository.Insert (source=auto, kind=NULL, started_on = первый пропущенный день, note «авто: пропущены все сессии за N дней»). → true.
  5. Есть хотя бы одна тренировка в окне → false.

Атлет может объявить break заранее — телефон вставляет source=manual (m09); авто-детект видит открытый manual и не дублирует.

3. CloseOnReturn — закрытие и формула возврата (Ф-14.3–14.5, правило 17)

Первый workout в пакете при открытом break:

  1. break_update: ended_on = дата тренировки (kind/note не трогаем — ответ атлета придёт отдельным каналом, m08/m09).
  2. Длительность простоя days = ended_on − started_on; коэффициент по таблице документа перерывов (разд. 3.2), фактор зажат конфигом [ReturnMinFactor; ReturnMaxFactor]:
Простой Коэффициент Режим
kind=illness (любой длительности) 0.6 (нижняя граница) перезапуск, rationale «болезнь»
4–6 дней 1.0 (веса без снижения) первая сессия: подходы −1, target_rpe 5
7–13 0.9 возврат 1–2 недели
14–27 0.85 1 вводная неделя
28–59 0.75 2 вводные недели
60+ ReturnMinFactor (0.6) перезапуск цикла
  1. Draft-версия возврата (одна на break; повторный вызов того же break — дедупликация по rules-draft на активную версию, как в spec 02/03): deep-copy body, week 1:
    • веса × коэффициент, округление к 0.5 кг; вес null не трогаем;
    • session_kind: days < 14 → "return", days ≥ 14 → "test" (правило 17), для illness → "return";
    • simple 4–6 дней: подходы −1 (мин 1), target_rpe = 5;
    • cardio_after_min не меняется (кардио возвращается со 100 %, Аттия);
    • rationale — «возврат после break N дней (тип T): веса ×K».
  2. SessionKinds (domain Workout) — константы normal/return/deload/test; в body week 1 sessions пишется "session_kind"; телефон при старте тренировки проставит workout.session_kind из активной версии.

🛡 Версии неизменяемы; активация — только человеком (Ф-14.4).