VEU.WathBody/1-docs/4-modules/m13-fenix-data-field/api_specs/03-screen.md

83 lines
5.3 KiB
Markdown
Raw Permalink 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.

# Спецификация 03: экран поля — макет и отрисовка
Источники: module_reqs разд. 1 (единица 5) и 2, Ф-2.1/Ф-2.2 (с
errata), ui-ux разд. 2 (glanceable, цвет дублируется текстом),
tech-req 6 п. 1. Единица 5.
## 1. Макет (resources\layouts\layout.xml)
Параметрический макет семейства квадратных MIP-экранов — якоря
(`loc="center"` и верх/низ), без единой фиксированной координаты:
позиции и шрифты вычисляются от `dc.getWidth()/getHeight()` в
`onLayout`. Один макет на всё семейство (fenix6x 280×280, fenix6
260×260, fenix6s 240×240 — добавление таргета без правок, инвариант
5).
Элементы (сверху вниз):
| Элемент | Содержимое | Шрифт |
|---|---|---|
| `zoneLbl` | подпись зоны + цветная плашка-ободок | FONT_TINY |
| `hrLbl` | текущий пульс или «—» | FONT_NUMBER_LARGE (запасной FONT_NUMBER_MEDIUM — §3) |
| `unitLbl` | «уд/мин» | FONT_TINY |
| `stateLbl` | «ОТДЫХ mm:ss» / «ПОДХОД mm:сс · ср N» | FONT_SMALL |
## 2. Содержимое и цвета
- фон — чёрный (`COLOR_BLACK`), текст — белый; MIP, читаемость на
солнце без подсветки;
- **зона**: плашка/ободок цвета зоны (`COLOR_BLUE/GREEN/YELLOW/RED`
по ZoneCalc) вокруг подписи зоны; подпись текстом — цвет не
единственный носитель (ui-ux): «восстановление»/«лёгкая»/
«средняя»/«высокая»; нет пульса → NONE: серая плашка
(`COLOR_DK_GRAY`), подпись «—»;
- **пульс**: крупное число `currentHeartRate`; null → «—»
(unitLbl гасится);
- **строка состояния**:
- идёт отдых (`RestTimer.isResting`) → «ОТДЫХ 1:48» — обратный
отсчёт остатка (mm:сс, при остатке ≥ 10 мин «мм:сс» с ведущими
разрядами не рвётся — формат `m:ss`/`mm:ss`);
- иначе → «ПОДХОД 2:05 · ср 132»: `SetTracker.elapsedMs` (время с
последнего Lap — errata Ф-2.1) и `SetTracker.avgBpm`; среднее
null → «ср —»;
- форматирование времени — чистая функция `mmss(ms)` (округление
вниз до секунд; часы не нужны — интервалы < 10 мин).
## 3. Шрифт пульса (адаптивный)
`onLayout`: берётся `FONT_NUMBER_LARGE`; если высота глифов +
прочих элементов не влезает в высоту области (мелкие страницы
данных, 2+ поля на странице) — шаг вниз до `FONT_NUMBER_MEDIUM`.
Пульс — главное число экрана (Ф-2.1: шрифт пульса максимальный из
доступных на области).
## 4. Класс `FenixDataField` (связка)
- `initialize()`: создание ядра (SetTracker/RestTimer/ZoneCalc/
Vibe/FieldSettings), начальное состояние — «нет данных»
(переменные инициализируются здесь, не в `compute` — асинхронность
compute/onUpdate по документации);
- `compute(info)`: раз в секунду — `currentHeartRate` →
`SetTracker.onSample`, кэш пульса; `RestTimer.onEnd(timerTime)`
→ лёгкая вибрация; `Vibe.onZone(zone, timerTime)` → двойная при
красной (гистерезис);
- `onTimerLap()`: `SetTracker.onLap` + `RestTimer.start` — Lap =
конец подхода = старт отдыха (errata Ф-2.3);
- `onTimerStart/Reset`: `SetTracker` к нулю, `RestTimer` не активен;
- `onUpdate(dc)`: отрисовка по кэшу (§2); данные могли ещё не
прийти — рисуем прочерки;
- `onTimerPause/Resume`: без кода — `timerTime` стоит/идёт, таймеры
замирают сами (спека 02 §3).
## 5. Симуляторный смок (критерий приёмки 2, шаг 3)
1. Поле добавляется в профиль Strength симулятора, отображается без
ошибок отрисовки;
2. симуляция пульса: число обновляется ≈1/с, плашка зоны и подпись
соответствуют порогам (прогнать пульс через все 4 зоны);
3. Lap (симулятор): метрики обнуляются, строка «ОТДЫХ …» тикает
вниз, по нулю — однократная вибрация (лог симулятора);
4. пульс в красной зоне — двойная вибрация, повтор не чаще 60 с;
5. пауза активности — отсчёты стоят; resume — продолжаются;
6. нулевой/отсутствующий пульс — «—», поле живое (не падает).