v2 (2026-06-01): полная переработка под реальный business request — серверная агрегация из ≥3 источников по региону, дедупликация, фильтры по активности и источнику, расширяемость на регионы. Предыдущая v1 трактовала задачу как URL-импорт + OSM live-поиск, что не соответствовало бизнес-цели.
agent:analyst
BRD — ET-008: GPS-треки с публичных платформ на карте
1. Цель
Показать пользователю Enduro Trails реальные GPS-треки, заранее
собранные с публичных платформ (Wikiloc, Offmaps.ru, Тропинки.ру,
EnduroRussia.ru, OSM Public GPS Traces, Nakarte.me, Komoot и т.п.) и
сохранённые на сервере. Цель — три практические задачи мотоэндуриста:
Видеть реальные дороги/тропы, которых нет в OSM. Vector-тайлы
trails показывают только OSM-данные; реальные грунтовки/тропы из
GPS-логов дают информацию, которой в OSM никогда не было.
Понимать, где реально ездят. Плотность публичных треков на
участке — прямая прокси-метрика популярности и проходимости.
Выявлять «мёртвые» дороги. OSM-грунтовка, не покрытая ни одним
публичным треком за последние N лет — кандидат на «давно никто не
ездит, может быть заросла».
ET-008 даёт новый отдельный слой (поверх trails, ниже маршрута
OSRM) с отдельными линиями (не heatmap), цветом по источнику или типу
активности, с UI-фильтрами.
2. Контекст
Vector-тайлы из OSM (/api/tiles/{z}/{x}/{y}.mvt) уже отдают
грунтовки/тропы/POI. ET-008 их не заменяет — добавляет
параллельный слой публичных GPS-треков.
ET-006 реализовал клиентский импорт GPX-файлов пользователем
(window.gpxTracks, #sheet-gpx). Это другой сценарий: ET-006 —
«мой трек в памяти браузера», ET-008 — «треки сообщества с сервера».
Модели данных не пересекаются.
Стек БД: SQLite + Spatialite. Для ET-008 заводится отдельная БД
data/gps_tracks.sqlite — чтобы не смешивать данные с основной
centralfederal.sqlite и иметь независимый цикл обновления / бэкапа.
Pipeline сбора — офлайн-скрипт на cron, не runtime. На запрос
пользователя сервер отдаёт уже собранные данные.
Регион MVP: ЦФО + Чувашия (18 субъектов ЦФО + Чувашская
Республика, площадь ≈ 670 тыс. км²). Расширение на другие регионы —
через конфиг-файл.
3. Scope
In scope
#
Функция
F-01
Pipeline сбора GPX-треков с ≥ 3 публичных источников
F-02
Хранение треков в SQLite + Spatialite: геометрия + метаданные
F-03
Дедупликация: один реальный трек = одна запись, даже если найден в N источниках
F-04
Метаданные трека: источник, URL, тип активности, дата, длина, кол-во точек, автор (если публичен)
F-05
API endpoint GET /api/gps-tracks?bbox=…&activity=…&source=… для отдачи треков клиенту
F-06
Векторные тайлы публичных треков GET /api/gps-tracks/tiles/{z}/{x}/{y}.mvt для эффективной отдачи на низких зумах
F-07
Визуализация отдельными линиями (не heatmap) на карте
F-08
Цветовая дифференциация: палитра по источнику (default) с возможностью переключения на палитру по типу активности
F-09
UI-чекбокс «Публичные треки» в #terrain-popup: включить/выключить весь слой
F-10
UI-фильтр по типу активности (enduro / moto / offroad / bicycle / hike / other), multi-select
F-11
UI-фильтр по источнику, multi-select
F-12
Конфиг-файл регионов: bbox + название + список активных источников
F-13
MVP-датасет: ЦФО + Чувашия, ≥ 5000 треков
F-14
Совместимость со сменой стиля карты (через rebuildMapOverlays() по аналогии с ET-006 REQ-F-13 и ET-007 REQ-F-06)
F-15
Совместимость со спутниковой подложкой (ET-007): треки видны на спутнике с halo для контраста
F-16
Клик по треку → popup с метаданными: имя/тип активности/источник/дата/длина и ссылка на оригинал
F-17
Health-эндпоинт /api/gps-tracks/health: дата последнего сбора, кол-во треков по источникам, ошибки последнего прогона
Out of scope
Real-time сбор: только периодический офлайн (cron, 1–2 раза в неделю).
Wikiloc Premium / Komoot Premium / любые платные API: используем
только бесплатные публичные endpoints и публичные HTML-страницы там,
где это разрешено ToS источника.
Strava Metro как источник линий: это heatmap, не отдельные треки —
не соответствует бизнес-требованию «отдельные линии». Опционально в
будущем — как метрика популярности для валидации, не для MVP.
OAuth-интеграции (вход пользователя в Strava/Komoot со своим
аккаунтом): отдельный work item.
Загрузка пользователем своих треков в общую базу: отдельный work item.
Редактирование/обрезка треков на стороне сервера.
Конвертация из KML/FIT/TCX: pipeline принимает только GPX.
Snap-to-road для треков (выравнивание под дороги OSM).
Учёт сложности (drag-level) внутри трека: фильтр только по типу
активности; сложность — отдельная задача (требует анализа геометрии и
скорости).
4. Источники (с оценкой реализуемости в MVP)
Анализ каждого источника из business request с честной оценкой
доступности и юридических условий:
#
Источник
Тип доступа
MVP
Комментарий
1
OSM Public GPS Traces
Документированный API
да
/api/0.6/trackpoints?bbox=…&page=…. Лицензия ODbL, атрибуция OSM. Объём для ЦФО оценочно ≈ 50–100K точек, тыс. треков.
2
EnduroRussia.ru
Web (HTML + GPX-ссылки)
да
По регионам, есть прямые GPX-ссылки. Лицензия и условия скрейпинга — фиксируются в ADR 06-adr/source-licensing.md до начала разработки.
3
Тропинки.ру / ttrails.ru
Web (GPX/KML)
да
Эндуро-категория, GPX доступен без авторизации. Условия скрейпинга — то же ADR.
4
Offmaps.ru
Web
пилот
Требует ревью формата выдачи и лицензии. Подключаем в пилот-режим если ADR разрешает.
5
Nakarte.me
Public layers + JSON
пилот
Агрегатор: содержит ссылки на треки внешних источников. Может быть «бесплатным» путём к Wikiloc/Strava-treki косвенно. Требует ревью лицензии.
6
Wikiloc
API (премиум)
нет
Бесплатный публичный API не отдаёт GPX. Без премиума — невозможно. Откладываем.
7
Komoot
API (партнёрский)
нет
Публичный API ограничен, нет публичной выдачи GPX по bbox. Откладываем.
8
Strava Metro
API (исследовательский)
нет
Heatmap, не отдельные треки → не соответствует бизнес-требованию. Out of scope.
MVP-минимум: 3 источника живут в продакшне — обязательно OSM
(гарантированно доступен), плюс минимум 2 из (2)–(5) по результатам
ADR-ревью лицензий.
Юридический минимум
Перед началом разработки каждого источника (2)–(5) — обязательный
ADRdocs/work-items/ET-008/06-adr/<source>-licensing.md:
Что говорит ToS источника о скрейпинге / массовой загрузке GPX.
Что говорит robots.txt.
На каких условиях разрешена публикация чужих треков
(имя/анонимизация/атрибуция).
Rate-limit, который мы будем соблюдать (default: 1 req / 5 sec, с
корректным User-Agent: enduro-trails/<v> (+contact)).
Список метаданных, которые нельзя сохранять/публиковать (личные
адреса, имена при отсутствии явного согласия).
Источник без явного зелёного света в ADR — не включается в pipeline.
5. Метрики успеха
Метрика
Критерий MVP
Покрытие региона
≥ 5000 уникальных треков для ЦФО + Чувашии после первого полного прогона pipeline
GET /api/gps-tracks?bbox=… ≤ 300 мс p95 на z ≥ 10 (≤ 500 треков в видимой области)
Производительность отдачи тайлов
GET /api/gps-tracks/tiles/{z}/{x}/{y}.mvt ≤ 200 мс p95 на z = 8–11
Производительность отрисовки
При включённом слое pan/zoom без видимых фризов на десктопе и мобильных с 4 ГБ RAM
Расширяемость на регион
Добавить новый регион (bbox + название + список источников) — ≤ 30 строк YAML-конфига, без правки кода
Скорость UI-фильтров
Переключение фильтра по активности/источнику меняет видимую выборку за ≤ 200 мс (фильтрация на клиенте)
Сохранение слоя при setStyle()
Слой не теряется при переключении тёмной темы / спутника / hillshade — восстанавливается через rebuildMapOverlays()
Pipeline стабильность
Падение парсера одного источника не валит остальных; лог + алерт в /api/gps-tracks/health
Атрибуция
На карте видна атрибуция каждого активного источника; в popup трека — ссылка на оригинал
6. Риски
Риск
Вероятность
Влияние
Митигация
Источник меняет HTML → парсер ломается
Высокая
Среднее
Каждый источник в отдельном модуле, изолированная ошибка. Pipeline пишет статус по источнику в health-эндпоинт. Алерт при 2 неудачных прогонах подряд.
ToS источника запрещает скрейпинг
Средняя
Высокое
Обязательный ADR с фиксацией лицензии до подключения источника. Источник без явного разрешения — не включается.
Дубли треков из разных источников (один и тот же трек выкладывают на 2 платформах)
Высокая
Среднее
Spatial+temporal hash: bbox округлённый до 0.01° + длина ± 5% + дата ± 1 день → одна запись. Алгоритм в TRZ §6.
Перегрузка карты на низких зумах (10K+ треков в видимой области)
Высокая
Высокое
На клиенте: на z < 10 — отдача через MVT-тайлы с упрощением геометрии (как simplify_coords для trails). На z ≥ 10 — JSON с лимитом 500 треков.
Размер БД растёт неконтролируемо (миллионы треков при расширении на РФ)
Низкая
Среднее
Отдельная gps_tracks.sqlite. Ротация: треки старше N лет (по конфигу, default 5) удаляются. Метрика размера БД в health.
Скрейпер банится по IP
Средняя
Среднее
Rate-limit + backoff + User-Agentс контактом. Сбор по cron 1–2 раза в неделю, не чаще. Per-source конфигурируемый delay.
Персональные данные в треках (точки «дом», имена)
Низкая
Высокое
Не сохраняем waypoint без явного публичного флага. Не сохраняем author если ToS требует анонимизации. Список запрещённых полей — в 08-data-requirements.md.
Лицензия источника обязывает менять/удалять данные по требованию автора
Средняя
Среднее
Сохраняем external_id и external_url — можем удалить точечно по запросу. Pipeline уважает «удалённое на источнике» → удалять и у нас.
Pipeline ест слишком много трафика mva154
Средняя
Низкое
Per-source лимит на прогон (например, max 1000 новых треков за прогон). Метрики в health.
Отдача больших MVT тайлов медленная
Средняя
Среднее
Серверный кэш тайлов (LRU 1024 записи, как уже сделано для trails). Упрощение геометрии по зуму.