Repeat analysis: detect a segment ridden twice (minPasses 3 -> 2); count no longer blocks 2-rep sessions
This commit is contained in:
parent
c5386ae22b
commit
ea462ad9c4
3 changed files with 20 additions and 2 deletions
|
|
@ -152,7 +152,7 @@
|
|||
- Тренировки: showSessionDetail (карта, графики скорости/высоты, секция «Сегменты» - сворачиваемый `<details>`-аккордеон, свёрнут по умолчанию, чтобы кнопки внизу были доступны; пересчёт, оверлей маршрута, панель де-джиттера SG), showRoutesScreen (сохранённые маршруты)
|
||||
- Похвастаться: showShareModal / buildShareImage (сторис-PNG: форма трека + статы; `opts.fields` галочками в модалке, выбор в `localStorage.baldav_share_fields`; прозрачный/фото; в стеке окон - `winPush("share")`), exportShareImage (нативный share/save)
|
||||
- Объединение поездок: в `renderGpsScreen` долгий тап (500мс) по `.gps-session-item` -> режим выделения (`.selected`, плавающая `#gps-sel-bar`), 2+ -> `DB.mergeGpsSessions(idStrs)` (db.js): точки в самую раннюю сессию, `orig_session_id` per-point (реверс), `seq=NULL` (иначе совпадающие seq перемешивают порядок), лишние сессии удаляются; затем `GPS.recalculateSession(target,{noDelete})`. Колонка `gps_points.orig_session_id` (миграция)
|
||||
- Разбор повторов: `GPS.detectRepeats(points)` (gps.js) - самоподобие: сетка ~10м, горячие ячейки (>=3 входов), самый длинный эталонный проход -> опорная линия; каждая точка ПРОЕЦИРУЕТСЯ на неё (cell-индекс, допуск вбок 30м) -> прогресс; проход = прогресс растёт от низа до >=80% (порт идеи `tools/track/pers.py`). Мост через короткие остановки/дрожь; время заезда `movingSec` = только движение (стопы вырезаны). Возвращает `{found,segLength,passCount,passes:[{startIdx,endIdx,movingSec}]}`. Секция «Разбор повторов» в `showSessionDetail` (только вело): таблица + вердикт последний/первый + подсветка участка на карте. Мощность на заезд - `avgPower` (новое поле возврата `GPS.computeStats`)
|
||||
- Разбор повторов: `GPS.detectRepeats(points)` (gps.js) - самоподобие: сетка ~10м, горячие ячейки (>=2 входов = minPasses), самый длинный эталонный проход -> опорная линия; каждая точка ПРОЕЦИРУЕТСЯ на неё (cell-индекс, допуск вбок 30м) -> прогресс; проход = прогресс растёт от низа до >=80% (порт идеи `tools/track/pers.py`). Мост через короткие остановки/дрожь; время заезда `movingSec` = только движение (стопы вырезаны). Возвращает `{found,segLength,passCount,passes:[{startIdx,endIdx,movingSec}]}`. Секция «Разбор повторов» в `showSessionDetail` (только вело): таблица + вердикт последний/первый + подсветка участка на карте. Мощность на заезд - `avgPower` (новое поле возврата `GPS.computeStats`)
|
||||
- Роутинг по проезженному: loadRideGraph (кэш графа из `get_ride_graph`, grid-индекс) / rideRoute (Dijkstra между концами ноги, снап ≤60м, отсев кривого) - в `showRouteEditor` пробуется до BRouter
|
||||
- Прочее: showWeightModal, showSleepModal, showActivityModal, showProfileModal, showBikeModal, showMapDownloadModal, showLogSupplementModal
|
||||
|
||||
|
|
|
|||
|
|
@ -88,6 +88,20 @@
|
|||
вырезан из первого), норм.скор [20.1,21.1,20.9,22.5], посл/перв 112%. 11 сен 5× (16.6..18.8,
|
||||
113%), 17 сен 5× (101%), контроль 5 обычных - 0 ложных, короткие - нет.
|
||||
|
||||
## Фикс 4: детекция при 2 заездах (порог 3 -> 2)
|
||||
- Симптом (пользователь + разбор другого агента): при двух проездах туда-обратно детекции
|
||||
нет по построению.
|
||||
- Проверка по коду + харнесс: `minPasses` (по умолч. 3) работал И как порог «горячей» ячейки
|
||||
(>=3 входов), И как финальный порог числа проходов. Урезанный до 2 заездов трек 16 сен:
|
||||
порог 3 -> НЕ НАЙДЕНО, порог 2 -> найдено (2 заезда, 1555м). Подтверждено.
|
||||
- Фикс: `minPasses` по умолчанию 2. Перекрёстки отсекаются длиной (`minLenM` 300м), не
|
||||
счётчиком; обычная поездка «туда-обратно» (коммьют) не ловится, т.к. проходы считаются
|
||||
монотонно в ОДНУ сторону (спуск/возврат start-guard отсекает).
|
||||
- Проверка: 2-заездный -> 2×; 16 сен 4×, 11/17 по 5× (без изменений); 5 обычных поездок
|
||||
(включая туда-обратно) - 0 ложных. Признаки из разбора агента (возвратный участок, время,
|
||||
высота) не понадобились - длина+направление уже отсекают мусор. Снос вбок и дырки в цепочке
|
||||
уже покрыты (проекция 30м в разметке проходов; gap>5 в эталонном проходе).
|
||||
|
||||
## Не в этой задаче
|
||||
Из того же файла НЕ делалось: поправка модели п.2 (аддитивная мощность вместо max(физика,MET);
|
||||
п.1 про Crr уже был сделан ранее), массовое уточнение высот, ветер (Часть 2 - там вопросы).
|
||||
|
|
|
|||
|
|
@ -105,7 +105,11 @@ GPS.detectRepeats = function(points, opts) {
|
|||
opts = opts || {};
|
||||
let cell = opts.cellM ?? 10; // grid cell ~10 m (as in tools/track heightmap)
|
||||
let minLenM = opts.minLenM ?? 300; // repeated segment must be at least this long
|
||||
let minPasses = opts.minPasses ?? 3; // and ridden at least this many times
|
||||
let minPasses = opts.minPasses ?? 2; // ridden at least this many times (2: a segment ridden
|
||||
// twice is already a repeat; 3 missed the normal "there and
|
||||
// back twice" case. Crossroads are rejected by minLenM, not
|
||||
// by the count; same-direction monotonic passes reject a plain
|
||||
// out-and-back commute - verified 0 false positives on rides)
|
||||
let minFrac = opts.minFrac ?? 0.8; // a pass must cover this fraction of the segment (projection
|
||||
// handles lateral drift, so a full rep reads as full coverage
|
||||
// and this stays strict, as in tools/track pers.py)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue