21 KiB
21 KiB
type, work_item_id, title, version, status, created_at, updated_at, authors, related
| type | work_item_id | title | version | status | created_at | updated_at | authors | related | |||
|---|---|---|---|---|---|---|---|---|---|---|---|
| brd | ET-012 | BRD: Показывать пользовательские треки с зума z5 (сейчас с z8) | 1 | draft | 2026-06-04 | 2026-06-04 |
|
|
BRD — ET-012: Показывать пользовательские треки с зума z5
1. Цель
Снизить нижний порог видимости слоя публичных GPS-треков
(gps-tracks-layer-mvt) с z8 до z5, чтобы пользователь
видел общее покрытие сети треков на средних/мелких масштабах
(z5 ≈ ¼ Европы в кадре, z7 ≈ область размером с ЦФО) и мог
«с высоты птичьего полёта» искать интересные треки.
На сегодня (после ET-008/ET-009) слой публичных треков физически скрыт ниже z8 двумя механизмами:
- vector-source задаёт
minzoom: 8(тайлы не запрашиваются); - клиентский visibility-фильтр
zoom >= GPS_TRACKS_MIN_ZOOM(8) в_syncGpsLayersVisibilityиapplyGpsHaloVisibility; - UI-hint «Зум 8+» (
#public-tracks-zoom-hint) висит как обоснование «почему пусто».
ET-012 = снизить порог + сохранить читаемость и производительность на новых зумах z5-z7.
2. Контекст
2.1 Текущее поведение (после ET-009)
- Источник
gps-tracks-tiles(MVT):tiles: /api/gps-tracks/tiles/{z}/{x}/{y}.mvt,minzoom: 8,maxzoom: 11. - Источник
gps-tracks-geo(GeoJSON, через/api/gps-tracks?bbox=…) включается приzoom >= GPS_TRACKS_ZOOM_CUTOFF = 12— ET-012 в этом регионе ничего не меняет. build_gps_mvt(src/api/gps_tracks/mvt.py) уже содержит zoom-aware упрощение и пороги:_simplify_coords: tolerance0.008°(~800м) на z≤7,0.002°(~200м) на z8-9,0.0005°(~50м) на z10-11, без упрощения на z≥12.- В
build_gps_mvt: при z≤7 —min_length_m=2000,limit=3000features на тайл; на больших зумах limit/min_length мягче.
- Endpoint
/api/gps-tracks/tiles/{z}/{x}/{y}.mvtпринимает любой0 ≤ z ≤ 22; никакой пре-нарезки тайлов нет — каждый тайл строится из БД on-demand и кэшируется в FIFO размером 1024. - На клиенте используется LRU-кэш MapLibre и сетевой кэш браузера.
- Текущая БД (test-среда) содержит порядка нескольких сотен треков (ожидаемо ≤ 5000 в горизонте года), геометрия каждого трека — десятки-тысячи точек.
2.2 Почему это бизнес-важно
- На малых масштабах (z5-z7) пользователю сейчас негде искать треки: при первом открытии карта по умолчанию показывает обзор региона; чтобы увидеть хоть что-то из публичных треков, нужно сразу зумить до z8 — это лишний шаг и плохой UX.
- Видимость на z5-z7 = понимание «где вообще катаются» в масштабах целого региона/страны, что помогает планировать выезды и оценивать покрытие.
- Конкуренты (Wikiloc, Komoot) показывают clustered/density слои с z3-z4; для нас достаточно начать с z5.
2.3 Открытые вопросы из бизнес-запроса — ответы по результатам анализа
| Вопрос | Ответ |
|---|---|
| Где задаётся minzoom слоя? | Клиент: src/web/gps_tracks.js, константа GPS_TRACKS_MIN_ZOOM = 8 (используется в source.minzoom, visibility, halo, hint). |
| Тайлы уже нарезаны до z5 или нужно догенерить? | Нарезки нет вообще — тайлы строятся on-demand из SQLite по bbox. Никакой генерации/инвалидации делать не нужно. |
| Нужна ли генерализация линий на малых зумах? | Базовая уже есть в _simplify_coords (DP-tolerance 800м при z≤7). Для z5-z6 нужно ужесточить пороги (min_length, limit, tolerance) — F-04..F-06. |
3. Scope
In scope
| # | Функция |
|---|---|
| F-01 | Снизить клиентскую константу GPS_TRACKS_MIN_ZOOM с 8 до 5 в src/web/gps_tracks.js. |
| F-02 | Уменьшить minzoom vector-source gps-tracks-tiles с 8 до 5 (использует ту же константу). |
| F-03 | На бэкенде в build_gps_mvt расширить tier-структуру: добавить уровни z5, z6 с более жёсткими min_length_m и limit. |
| F-04 | В _simplify_coords добавить tier для z5-z6: tolerance ~0.02° (~2 км) на z5, ~0.01° (~1 км) на z6. |
| F-05 | Расширить line-width (основной слой) и line-width (halo) для z5: явные stops чтобы линия читалась. |
| F-06 | UI-hint #public-tracks-zoom-hint: либо обновить текст до «Зум 5+», либо скрывать всегда (после снижения порога порог фактически недостижим в обычных сценариях). |
| F-07 | Halo на спутнике активируется на z5-z11 (как и основной MVT-слой). |
| F-08 | Производительность: p95 generation одного MVT-тайла z5 ≤ 500 мс при размере БД ≤ 5000 треков; p95 endpoint не выше +50 мс относительно baseline ET-009. |
| F-09 | Читаемость: на z5 с включённым слоем при ≥ 200 треках по ЦФО карта остаётся «читаемой» — линии не сливаются в сплошную кашу. Критерий приёмки качественный, см. AC-08. |
| F-10 | Halo на спутнике на z5-z7: не «глушит» подложку. Halo-width на z5 ≤ 2 px. |
| F-11 | Регрессия: поведение на z8-z11 (MVT) и z12+ (GeoJSON) не меняется. |
| F-12 | Регрессия: фильтры по activity / source работают на z5-z7 так же, как на z8+. |
| F-13 | Регрессия: popup трека и кнопка «Скачать GPX» (ET-011) работают при клике на трек на z5-z7. (Замечание: на низких зумах кликнуть в линию пальцем сложнее — оставляем как есть, hit-area не расширяем.) |
Out of scope
- Clustering / heat-map на z3-z4. Идея здравая, но требует отдельной серверной агрегации (например, h3-cell counts) и нового UI-слоя. Делаем отдельным work item.
- Пре-нарезка тайлов на диск. Не требуется при текущем размере БД; on-demand + LRU справляются.
- Изменение поведения GeoJSON-слоя на z12+. Не трогаем.
- Изменение фильтров по activity/source. Не трогаем.
- Изменения popup'а трека. Не трогаем.
- Расширение
gps_tracks_minzoomв админ-конфиг. Константа остаётся хардкодом — менять через релиз. Если в будущем появится потребность в feature-flag — отдельный work item. - Изменения схемы БД и dedup-алгоритма. Не трогаем.
- Изменения OSRM / routing. Не трогаем.
4. Метрики успеха
| # | Метрика | Критерий |
|---|---|---|
| M-1 | Видимость на z5 | При включённом чекбоксе «Публичные треки» и zoom = 5 слой gps-tracks-layer-mvt имеет visibility: visible. На карте отображаются линии треков. |
| M-2 | Видимость на z6, z7 | Аналогично M-1 для z6 и z7. |
| M-3 | Поведение на z8-z11 не изменилось | Регрессия: на z8-z11 виден тот же набор треков, что и до ET-012 (с поправкой на улучшенную z5-z7 генерализацию — не считается регрессией). |
| M-4 | Поведение на z12+ не изменилось | Регрессия: GeoJSON-слой включается ровно на z=12 как раньше; MVT слой скрывается ровно на z=12. |
| M-5 | Hint «Зум 5+» / «Зум 8+» | После ET-012: при включённом слое и zoom ≥ 5 hint скрыт. (До ET-012 hint показывал «Зум 8+» при zoom < 8.) |
| M-6 | p95 MVT tile generation на z5 | ≤ 500 мс на test-среде при размере БД до 5000 треков; ≤ 1 с при размере до 20 000 треков (запас). |
| M-7 | p95 endpoint /api/gps-tracks/tiles/5/x/y.mvt |
cold ≤ 700 мс, hit ≤ 50 мс (кэш). |
| M-8 | Размер MVT тайла z5 | ≤ 200 KB после генерализации и фильтра min_length (защита от мобильного трафика). Если больше — F-03/F-04 переусиливают (ужесточить limit). |
| M-9 | Читаемость z5 | На скриншоте z5 с ≥ 200 треков по ЦФО видны минимум 3 разных линии в разных частях кадра; нет «сплошной заливки» одной зоны. Качественная проверка по TC-UI-12-Z5-Q. |
| M-10 | Регрессия фильтров | Снятие галки «EnduroRussia» в #sheet-gps-filters на z=6 убирает соответствующие линии (как и на z=10). |
| M-11 | LRU-кэш не переполняется ненужно | После панорамирования по миру на z5-z6 (≈ 50 уникальных тайлов) кэш-хит на повторных тайлах ≥ 80 %. |
5. Риски
| # | Риск | Вероятность | Влияние | Митигация |
|---|---|---|---|---|
| R-1 | На z5 слишком много фич в одном тайле → MVT > 1 MB, тормоза рендера на мобильном. | Средняя | Высокое | F-03: жёсткий min_length_m и limit для z=5. Метрика M-8 (≤ 200 KB) — гейт. При нарушении — ужесточить limit/min_length. |
| R-2 | На z5 линии после Douglas-Peucker превращаются в «обрубки» (трек из 1000 точек → 3 точки). | Средняя | Низкое | Качественная проверка по TC-UI-12-Z5-Q. Tolerance подобрана так, чтобы трек ≤ 5 км превращался в прямую — это норма на z5. |
| R-3 | Линия line-width: 0.5 px на z5 невидима на retina-дисплеях. |
Низкая | Низкое | F-05: явные stops interpolate linear zoom 5 0.8 8 1.0 12 2.0 16 3.0. Проверка по TC-UI-01-Z5. |
| R-4 | Бэкенд-запрос к БД с огромным bbox (z5 тайл ~1250×1250 км) тянет ВСЕ треки региона. | Средняя | Среднее | Запрос уже идёт через индекс по min_lon/max_lon/min_lat/max_lat в SQLite; при ≤ 5000 строк это < 100 мс. M-7 — гейт. При деградации — добавить индекс length_m. |
| R-5 | На z5 buffer 10 % bbox в endpoint раздувает запрос до 130 % площади. | Низкая | Низкое | На z5 это уже не имеет смысла (соседний тайл всё равно отрисует пограничные фичи). Опционально — снизить buffer до 5 % для z≤6. См. TRZ §3.10. |
| R-6 | LRU-кэш в 1024 тайла на z5 (всего 32×32 = 1024 тайла в мире) — теоретически переполняется на «walk through world». | Низкая | Низкое | На практике пользователь видит ~10-20 тайлов одновременно на z5; ротация работает. Опционально — увеличить _GPS_TILE_CACHE_MAX до 2048. См. TRZ §3.11. |
| R-7 | Hint «Зум 8+» забыли удалить → пользователь видит и линии, и подсказку «увеличь зум». | Средняя | Низкое | F-06 явно: либо hide-always при GPS_TRACKS_MIN_ZOOM = 5, либо текст «Зум 5+». См. AC-05. |
| R-8 | Регрессия halo на спутнике: halo на z5 «закрывает» линию. | Низкая | Низкое | F-10: halo-width ≤ 2 px на z5; проверка по TC-UI-09-Z5-SAT. |
| R-9 | Пользователи на мобильном с медленным интернетом получают раздутые тайлы z5-z6 при первом открытии. | Средняя | Среднее | Размер ≤ 200 KB (M-8) + gzip на nginx + браузерный кэш. Опционально — отсрочить включение слоя до первого panMove (не в scope ET-012). |
| R-10 | Конфликт с поведением другого слоя gps-tracks-halo-mvt-satellite: оба используют те же фичи MVT — на z5 halo и линия должны быть согласованы. |
Низкая | Низкое | Используют тот же source/source-layer; видимость синхронизируется через _syncGpsLayersVisibility + applyGpsHaloVisibility. Регрессионная проверка TC-UI-09-Z5-SAT. |
6. Зависимости
Backend
src/api/gps_tracks/mvt.py:build_gps_mvt— расширить tier-таблицу для z5, z6 (F-03).src/api/gps_tracks/mvt.py:_simplify_coords— добавить tier для z5-z6 (F-04).src/api/gps_tracks/endpoint.py— без изменений логики, опциональная правка buffer для z≤6 (R-5). По умолчанию не меняем.- Endpoint
/api/gps-tracks/tiles/{z}/{x}/{y}.mvtуже принимает z 0..22 — не трогаем.
Frontend
src/web/gps_tracks.js:- константа
GPS_TRACKS_MIN_ZOOM = 5(F-01, F-02). _gpsLayerDefpaint.line-width — расширить interpolate-выражение для z5 (F-05)._gpsHaloDefpaint.line-width — то же (F-05, F-10).
- константа
src/web/index.html:#public-tracks-zoom-hint— обновить текст или скрыть навсегда (F-06).
- Стили
style.json/style-dark.json— без изменений (минзум слоя в стилях не задаётся; он живёт в коде клиента).
Тесты
- Новые unit-тесты
tests/unit/test_gps_mvt_zoom_tiers.py(новый файл): тиры min_length и limit для z=5..z=12. - Новые unit-тесты
tests/unit/test_gps_mvt_simplify.pyили расширение существующих: tolerance для z5-z6. - Новые integration-тесты
tests/integration/test_gps_tile_z5_z7.py: endpoint отдаёт непустой MVT для z=5/6/7 на регионе с ≥ 10 треками. - UI-тесты см.
04b-ui-test-cases.md.
Документация
01-brd.md(этот файл).02-trz.md,03-acceptance-criteria.md,04-test-plan.yaml,04b-ui-test-cases.md— этот пакет.- Опциональный ADR не требуется: tile-pipeline уже спроектирован
под динамические тиры в ET-008/ET-009; это calibration, а не
архитектурное решение. Если разработчик в реализации обнаружит
нужду в смене политики (например, переход к heat-map на z5) —
добавляет ADR в
06-adr/.
Инфра / Данные
- Test-среда
https://openclaw.mva154.duckdns.org/enduro/— существующий деплой. - БД
data/gps_tracks.sqlite— без миграций. - nginx gzip уже включён.
Связи с другими work items
- ET-008 — родительский слой публичных GPS-треков.
- ET-009 — заполнил БД треками EnduroRussia/Wikiloc; без этих данных z5-z7 будет визуально пустым в test-среде.
- ET-011 — кнопка «Скачать GPX» в popup'е; регрессия покрывается.
- PH-3 Smart Route — независимо.
- Будущий work item «Heat-map / clustering на z3-z4» — отдельная задача.
7. План в одну строку
Снижаем константу GPS_TRACKS_MIN_ZOOM с 8 до 5, расширяем
zoom-tier структуру в build_gps_mvt и _simplify_coords для z5-z6,
добавляем явные line-width stops для z5, скрываем/обновляем hint,
гарантируем читаемость и производительность тестами и
скриншот-тестами.