74 lines
5.3 KiB
Markdown
74 lines
5.3 KiB
Markdown
# Спецификация 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 — уже покрыто тестами ядра; здесь — маппинг исход→кнопка) |
|