5.3 KiB
Спецификация 02: экран «Сегодня» и поток «Допуск»
Источники: Ф-13.1 (дневник-минимум), Ф-13.2 (предстартовый допуск),
Ф-14.5 (session_kind), m09 WorkoutCore/AdmissionChecker/spec 02.
Единицы 2–3.
1. «Сегодня» (дневник)
TodayViewModel: dailyLog(today) (Flow), pendingCount (Flow),
сохранение — WorkoutCore.saveDailyLog (merge, день уникален).
Поля (ввод за 2–3 касания — заполненные поля не переспрашиваются, пустые необязательны, кроме самочувствия-подсказки):
| Поле | Ввод | Диапазон |
|---|---|---|
| АД систола | пикер шаг 5 | 70–250 |
| АД диастола | пикер шаг 5 | 40–150 |
| Вес тела | пикер шаг 0,5 кг | 30–300 |
| Пульс покоя | пикер шаг 1 | 30–130 |
| Самочувствие | сегмент 1–5 (подписи: 1 плохо … 5 отлично) | 1–5 |
Кнопка «Сохранить» (нижняя треть) — доступна всегда; после — тихое подтверждение «Сохранено». Кнопка «Начать тренировку» → «Допуск». Счётчик «в очереди: N» — из баннер-состояния (spec 01).
2. «Допуск» (модальный экран перед стартом силовой)
AdmissionViewModel: читает дневник дня (АД), поля: «АД из дневника
за сегодня» (если пусто — пикеры прямо здесь, сохранение в дневник),
«Пульс сидя» (пикер 30–180, вручную — с часов подтянется в m12).
Расчёт: AdmissionChecker.check(safety, bpSys?, bpDias?, hrSitting?)
(порядок CANCEL → CARDIO_ONLY → POSTPONE → ALLOW; null пропускает
проверку — m09 spec 02). Если и АД, и пульс не введены — проверка не
выполняется, исход ALLOW с пометкой «данные не введены».
Экран исхода (спокойные формулировки, статус дублируется текстом):
| Исход | Заголовок/текст | Кнопки |
|---|---|---|
| ALLOW | «Допуск получен» | «Начать тренировку» (+ выбор вида) |
| CARDIO_ONLY | «Давление повышено — сегодня только лёгкое кардио или дыхание. Силовые заблокированы.» | «Закрыть»; тихая ссылка «Всё равно начать силовую» (2 тапа) 🛡 |
| CANCEL | «Давление высокое — тренировку не начинаем. Рекомендуется прогулка.» | «Отменить» (закрыть); тихая ссылка «Всё равно начать» (2 тапа) 🛡 |
| POSTPONE | «Пульс сиди высокий — лучше перенести тренировку.» | «Перенести» (закрыть); тихая ссылка «Всё равно начать» (2 тапа) 🛡 |
🛡 Обход блокировки (любой из трёх): «Всё равно начать» → подтверждение
вторым тапом → WorkoutCore.startAnyway(programVersionId) — в журнал
команд пишется accepted=false, semantics={"override":"permission"}
(Ф-13.5, m09). Обход всегда виден в журнале.
Выбор вида тренировки (при «Начать»): сегмент — обычная (normal,
умолчание) / возврат (return) / делоад (deload) / тест (test) —
Ф-14.5. Старт: startWorkout(activeVersionId, kind) → переход на
вкладку «Тренировка». Активная версия отсутствует — старт без
привязки (startWorkout(null, kind)), на экране тренировки пометка
«вне программы».
3. Правила
- пороги — только из
Safety.*настроек (Р3-А), в потоке допуска не редактируются; - п. 1 «дневник» и п. 2 «допуск» пишут через
saveDailyLog(merge) — повторное сохранение не затирает утренние значения, введённые раньше (одна запись на день); - после старта —
SyncWorker.schedule(spec 01 п. 4).
4. Тесты (unit, pure JVM)
| # | Проверка | Ожидание |
|---|---|---|
| 1 | Слияние дневника: утро (АД 120/80) + допуск ввёл пульс | запись дня одна: 120/80 + пульс |
| 2 | Допуск без данных (все null) | ALLOW, пометка «данные не введены» |
| 3 | Исходы CANCEL/CARDIO_ONLY/POSTPONE → «всё равно» | вызов startAnyway, лог override (по m09 — уже покрыто тестами ядра; здесь — маппинг исход→кнопка) |