VEU.WathBody/1-docs/4-modules/m13-fenix-data-field/api_specs/04-settings-vibes.md

64 lines
3.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Спецификация 04: настройки поля и вибрации
Источники: module_reqs разд. 1 (единицы 6–7), Ф-2.2 (границы зон —
настройки поля), Ф-2.4 errata (длительность отдыха — настройка,
умолчание `Rest.DefaultSec`), решение гейта 1.3 № 3 (sideload живёт
на умолчаниях) и № 5 (красная зона процентная). Единицы 6–7.
## 1. Properties (resources\settings\settings.xml)
| Свойство | Тип | Диапазон редактора | Умолчание | Смысл |
|---|---|---|---|---|
| `restSec` | numeric | 30–600 | 120 | длительность автономного таймера отдыха, с (= `Rest.DefaultSec` телефона) |
| `hrMaxBpm` | numeric | 0–250 | 0 | макс. ЧСС для зон; 0 — расчёт по формуле Танаки от `age` |
| `age` | numeric | 14–100 | 45 | возраст для формулы Танаки (208 − 0,7 × возраст) |
- подписи/описания — ru/en (строки в settings.xml + strings);
- значения читаются `FieldSettings` при `initialize()`; смена
настроек применяется при следующем запуске активности (поле
перезапускается платформой);
- правка значений на устройстве — только через Garmin Connect
Mobile/Express для приложений из магазина CIQ (решение 3 гейта
1.3): sideload-сборка живёт на умолчаниях, смена поведения =
пересборка.
## 2. `FieldSettings` (клампы — защита от кривых значений)
Чистый класс: чтение property → кламп → поле:
- `restSec`: вне 30–600 или не число → 120;
- `hrMaxBpm`: вне 0–250 → 0 (авто);
- `age`: вне 14–100 → 45.
`maxBpm()` delegирует в `ZoneCalc.maxBpmFor(hrMaxBpm, age)`.
## 3. Вибрации (`Vibe.mc`)
`Attention.vibrate([...])`, до 8 `VibeProfile(duty, мс)`:
| Событие | Паттерн | Вызов |
|---|---|---|
| конец отдыха (RestTimer.onEnd == true) | `[VibeProfile(25, 300)]` — однократная лёгкая | из `compute` |
| красная зона (Vibe-гистерезис сработал) | `[VibeProfile(75, 200), VibeProfile(0, 150), VibeProfile(75, 200)]` — двойная заметная | из `compute` |
- вибрация различается паттерном (ui-ux: паттерны различаются —
отдых/предупреждение);
- недоступность вибрации на модели — вызов молча пропускается
(проверка наличия/`try-catch`; инвариант 4, Ф-2.8);
- гистерезис красной зоны: повторная двойная не раньше 60 000 мс;
выход в GREEN/BLUE/NONE сбрасывает (спека 02 §4);
- вибрации не стекаются: не чаще одной причины за проход `compute`.
## 4. Тесты (Toybox.Test, дополняют спеку 02)
`FieldSettings` (чистые клампы):
1. `clampRest(10) == 120`, `clampRest(600) == 600`, `clampRest(30) == 30`;
2. `clampRest(null) == 120` (property отсутствует);
3. `clampHr(-5) == 0`, `clampHr(250) == 250`;
4. `clampAge(200) == 45`, `clampAge(14) == 14`;
5. `maxBpm()`: hrMaxBpm 190 → 190; hrMaxBpm 0 + age 45 → 177.
`mmss` (форматирование строки состояния, спека 03 §2):
6. `mmss(0) == "0:00"`, `mmss(59_999) == "0:59"`, `mmss(60_000) == "1:00"`,
`mmss(65_000) == "1:05"`, `mmss(600_000) == "10:00"`.