4.8 KiB
Спецификация 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) | построчные ошибки |