76 lines
4.8 KiB
Markdown
76 lines
4.8 KiB
Markdown
# Спецификация 05: «Профиль», «Библиотека», «Настройки», ZoneCalculator
|
||
|
||
Источники: Ф-6 (профиль/зоны), Ф-4 (библиотека), tech-req 4.1
|
||
(настройки+валидация), ОВ-1 (Танака). Единицы 7–9 + сервис 11.
|
||
|
||
## 1. «Профиль» (Ф-6)
|
||
|
||
`ProfileViewModel`: `profile` (Flow), сохранение —
|
||
`WorkoutCore.saveProfile(sex, birthYear, weightKg, hrMax)` →
|
||
sync-сущность `profile` (guid-стабильность — m09).
|
||
|
||
| Поле | Ввод | Диапазон |
|
||
|---|---|---|
|
||
| Пол | сегмент м/ж/не указан | — |
|
||
| Год рождения | пикер | 1930–2010 |
|
||
| Вес | пикер шаг 0,5 кг | 30–300 |
|
||
| Макс. пульс | пикер 120–240 или «считать по формуле» (Танака) | 120–240 / авто |
|
||
|
||
`ZoneCalculator` (чистая): `maxHr = hrMax ?: 208 − 0,7 × возраст`
|
||
(округление до целого; возраст = текущий год − birthYear; без
|
||
birthYear и hrMax — зоны не показываются); зоны по Ф-6.2:
|
||
z1 < 50 %, z2 50–69 %, z3 70–84 %, z4 ≥ 85 % (границы в уд/мин,
|
||
таблица; те же единицы, что на часах). Зоны — показ; на часы — m12.
|
||
|
||
## 2. «Библиотека» (Ф-4)
|
||
|
||
`LibraryViewModel`: `exercises` (Flow), переключатель «показать
|
||
исключённые». Операции:
|
||
|
||
- «Добавить» — диалог: название (уникальность проверяет БД,
|
||
UNIQUE `exercise.name` — сообщение «уже есть»), группа (сегмент
|
||
из 5), базовое/изоляция (переключатель);
|
||
- «Переименовать» — диалог с текущим названием (UUID не меняется 🛡
|
||
Ф-4.3);
|
||
- «Исключить» — подтверждение «История тренировок сохранится;
|
||
упражнение исчезнёт из выбора» → `deactivateExercise` (🛡 только
|
||
логическое удаление, Ф-4.2; восстановления в v1 нет — решение
|
||
З-41/m02);
|
||
|
||
Запись — `WorkoutCore.saveExercise`; is_active=false уходит на сервер
|
||
повторной отправкой упражнения (контур З-41(а)).
|
||
|
||
## 3. «Настройки» (tech-req 4.1)
|
||
|
||
`SettingsViewModel`: чтение/сохранение `AppSettings` (расширение
|
||
m09: + `hrMaxBpm`, `hrStrengthMax`); валидация перед сохранением
|
||
(«Сохранить» неактивна, ошибки — построчно):
|
||
|
||
| Поле | Правило |
|
||
|---|---|
|
||
| `baseUrl` | абсолютный `https://` URL (host непустой); http допустим только для отладки — предупреждение текстом (docker-сервер) |
|
||
| `apiKey` | непустой; поле-пароль (маска), 🛡 не логируется и не выводится полностью |
|
||
| `wifiOnly` | — |
|
||
| `hrMaxBpm` | 120–240 или пусто (авто-Танака) |
|
||
| `restDefaultSec` | 30–600 |
|
||
| `bpCancelSys/bpCancelDias` | 120–200 / 70–130 |
|
||
| `bpCardioSys/bpCardioDias` | 120–200 / 70–130; ≤ соответствующего Cancel (tech-req 4.1) |
|
||
| `restingHrSitting` | 40–120 (умолчание 90) |
|
||
| `hrStrengthMax` | 100–180 (умолчание 120, З-20; применяется в m12) |
|
||
|
||
Секция «Синхронизация»: счётчик очереди, кнопка «Синхронизировать
|
||
сейчас» → `SyncWorker.scheduleNow` (spec 01 п. 4), результат —
|
||
баннер (spec 01 п. 3). Первый запуск — экран открывается гейтом
|
||
(spec 01 п. 2).
|
||
|
||
## 4. Тесты (unit, pure JVM)
|
||
|
||
| # | Проверка | Ожидание |
|
||
|---|---|---|
|
||
| 1 | `ZoneCalculator`: 1980 г.р. в 2026, без hrMax | maxHr 176 (208 − 0,7×46 = 175,8, математическое округление) |
|
||
| 2 | `ZoneCalculator`: ручной hrMax 190 | границы 95/133/162; ручной приоритетнее формулы |
|
||
| 3 | `ZoneCalculator`: нет данных | зоны не показываются (null) |
|
||
| 4 | Валидация baseUrl: `https://host/path` ок; `http://…` предупреждение; `ftp://`, `host`, пусто | ошибка/предупреждение по правила |
|
||
| 5 | Валидация Safety: bpCardioSys > bpCancelSys | ошибка «кардио-порог выше порога отмены» |
|
||
| 6 | Валидация диапазонов (restDefaultSec 10; hrMaxBpm 250; hrStrengthMax 90) | построчные ошибки |
|