Repeat/interval analysis: auto-find repeated segments in one ride, table + last/first verdict
This commit is contained in:
parent
6dfe262801
commit
7717a73129
6 changed files with 203 additions and 0 deletions
48
docs/session-logs/2026-09-17_repeat-intervals.md
Normal file
48
docs/session-logs/2026-09-17_repeat-intervals.md
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# Сессия 2026-09-17 - автоматический разбор повторов внутри поездки (интервалы)
|
||||
|
||||
## Контекст
|
||||
Заказ из `docs/gps-model-findings.md` (раздел «БЭКЛОГ: автоматический разбор повторов»).
|
||||
Пользователь катает интервалы: один подъём 5 раз за поездку, один трек, без стоп/старт.
|
||||
Нужно: повторы находятся сами по самоподобию, таблица заездов и число «последний/первый».
|
||||
Действовали по утверждённому плану `~/.claude/plans/merry-discovering-dream.md`
|
||||
(в docs/plans не копировал - план короткий и одноразовый; здесь ссылка).
|
||||
|
||||
## Сделано
|
||||
- `GPS.detectRepeats(points, opts)` (gps.js) - порт `tools/track/pers.py`, но эталонный
|
||||
проход находится сам:
|
||||
1. сетка ~10м (формула из `wind_by_passes`/`heightmap.py`);
|
||||
2. горячие ячейки = >= minPasses (3) входов (заход = смена ключа ячейки);
|
||||
3. эталон = ОДИН чистый проход: от первой горячей ячейки, добавляя новые, до первого
|
||||
возврата к более ранней (склейка кругов давала абсурд - см. баги);
|
||||
4. проходы = порт `passes()`: позиция в seq растёт от старта (допуск назад 3, гэп 25),
|
||||
покрытие >= 80%; старт-гвард `pos<=15%` не даёт спуску открыть заезд;
|
||||
5. нормировка: сравнение по `L_seq / T_прохода` (снимает 5% разброса длины GPS).
|
||||
Направление без явной проверки bearing: seq хранит первую (подъёмную) позицию ячейки,
|
||||
спуск роняет позицию и закрывает заезд.
|
||||
- `avgPower` в возврат `GPS.computeStats` (накопление `power*dt` в вело-ветке / время
|
||||
педалирования) - для колонки «Вт».
|
||||
- UI: секция-аккордеон «Разбор повторов» в `showSessionDetail` (только вело), таблица
|
||||
(№/время/км-ч норм/каденс/Вт), вердикт последний/первый (зелёный >=100%, жёлтый >=90%,
|
||||
красный <90%), подсветка участка на карте (бирюза `#00e5ff`). CSS в styles.css.
|
||||
|
||||
## Баги по пути (и фиксы)
|
||||
- Эталон как «самый длинный горячий ран» склеивал 5 кругов -> segLength 4406м и заезды по
|
||||
9с (норм. скорость 1762 км/ч). Фикс: эталон = один проход до первого возврата.
|
||||
- Следующая точка в ТОЙ ЖЕ ячейке считалась «возвратом» и сразу обрывала seq (seq=1).
|
||||
Фикс: `c===seq[last]` -> продолжить, не обрывать.
|
||||
|
||||
## Проверка
|
||||
- Node-харнесс на `tools/track/baldav.db` (реальные данные):
|
||||
- 11 сен (3214 тчк): участок 1577м, **5 заездов**, норм. скорости 15.0/17.1/17.8/17.9/17.5,
|
||||
последний/первый 117%.
|
||||
- 17 сен (3079 тчк): участок 1630м, **5 заездов**, 16.9/15.8/17.3/16.4/17.7, 105%.
|
||||
Совпадает с находками («11 и 17 сентября, по 5 повторов»).
|
||||
- Контроль: 5 обычных вело-поездок (8-23 км) + 2 короткие -> «повторов не найдено» (0 ложных).
|
||||
- Десктоп (Xvfb): временно подсажена сессия 17 сен в дев-БД (бэкап + точечное удаление
|
||||
после, БД байт-в-байт восстановлена). Секция рисуется, аккордеон работает, таблица 5 строк
|
||||
совпадает с харнессом, вердикт зелёный 105%, участок подсвечен бирюзой на карте. Скрин.
|
||||
- Далее: сборка APK + проверка на телефоне (реальные интервалы там же).
|
||||
|
||||
## Не в этой задаче
|
||||
Из того же файла НЕ делалось: поправка модели п.2 (аддитивная мощность вместо max(физика,MET);
|
||||
п.1 про Crr уже был сделан ранее), массовое уточнение высот, ветер (Часть 2 - там вопросы).
|
||||
Loading…
Add table
Add a link
Reference in a new issue