diff --git a/tasks/enduro-trails/BRD_PHASE4.md b/tasks/enduro-trails/BRD_PHASE4.md new file mode 100644 index 0000000..4d379b8 --- /dev/null +++ b/tasks/enduro-trails/BRD_PHASE4.md @@ -0,0 +1,295 @@ +# BRD: Enduro Trails — Фаза 4 «Продвинутый роутинг» + +**Версия:** 1.0 +**Дата:** 2026-05-04 +**Автор:** Стрим 🌊 +**Статус:** На согласовании + +--- + +## 1. Контекст и цели + +### Что уже есть +- Роутинг A→B «Дикий путь» (OSRM, до 5 альтернатив) +- Статистика покрытия (% грунт/асфальт/тропа) +- Промежуточные точки, GPX экспорт +- POI в БД: water, peak, viewpoint, ruins, ford, cave_entrance (14K штук) + +### Проблема +«Дикий путь» даёт маршрут от A до B с максимумом грунтовок. Но эндуристу часто нужно другое: +- **«Покататься красиво»** — замкнутый круг от дома, через живописные места, и обратно +- **«Найти грунтовки рядом»** — не знаешь куда ехать, покажи что есть вокруг +- **«Соединить два трека»** — есть два хороших участка, как их связать грунтовками + +### Цель +Дать эндуристу 3 новых режима роутинга, которые закрывают типичные сценарии: покататься, разведать, связать. + +--- + +## 2. Фичи + +--- + +### F-11: «Красивый маршрут» (Scenic Route) + +#### Описание +Пользователь указывает **точку старта** и **желаемую дистанцию**. Система строит **замкнутый кольцевой маршрут**, который проходит через максимально живописные места: озёра, видовые точки, заброшки, горы. + +#### Зачем +Самый частый сценарий эндуриста: «Хочу покататься км на 150 от дома, но не по асфальту, а красиво». Сейчас нужно вручную ставить точки и строить маршрут. «Красивый маршрут» делает это автоматически. + +#### Use Cases + +**UC-11.1 — Покататься от дома** +> Слава нажимает 🎨 «Красивый маршрут». Кликает на карте — точка старта (дом). Вводит дистанцию: 150 км. Система строит кольцевой маршрут: дом → озеро Сенеж → видовая точка → заброшка → грунтовки → дом. 142 км, 89% грунт. + +**UC-11.2 — Короткая поездка** +> Слава хочет покататься на 50 км. Маршрут: дом → лесной массив → грунтовки → дом. 48 км, 94% грунт. + +**UC-11.3 — Несколько вариантов** +> Система предлагает 2–3 кольцевых маршрута: северный (через озёра), восточный (через леса), южный (через поля). Слава выбирает северный — через озёра красивее. + +**UC-11.4 — Нет красивых мест рядом** +> Слава в степи, рядом нет озёр и видов. Система строит максимально грунтовый кольцевой маршрут, но без бонусных точек. Подпись: «Живописных объектов поблизости не найдено, маршрут по грунтовкам». + +#### Алгоритм + +**Шаг 1: Найти привлекательные POI в радиусе** +- Радиус = желаемая дистанция × 0.6 (примерное кольцо) +- Выбрать POI с оценкой аттрактивности: + +| POI тип | Баллы | Вес | +|---------|-------|-----| +| `natural=water` (озёра, реки) | 10 | Высокий | +| `tourism=viewpoint` (видовые точки) | 15 | Очень высокий | +| `historic=ruins` (заброшки) | 10 | Высокий | +| `natural=peak` (вершины) | 12 | Высокий | +| `natural=cave_entrance` (пещеры) | 8 | Средний | +| `ford=yes` (броды) | 5 | Низкий | + +**Шаг 2: Выбрать 3–5 POI для маршрута** +- Жадный алгоритм: начать со старта, на каждом шаге выбирать ближайший POI с максимальными баллами +- Суммарная дистанция до POI ≤ желаемая дистанция × 0.8 (оставить запас на возврат) +- После последнего POI — маршрут обратно к старту + +**Шаг 3: Построить маршрут через POI** +- Использовать OSRM: старт → POI1 → POI2 → ... → старт +- Каждый сегмент — запрос к OSRM с `alternatives=false` + +**Шаг 4: Проверить дистанцию** +- Если итоговая дистанция > желаемая × 1.3 — уменьшить кол-во POI, перестроить +- Если < желаемая × 0.5 — добавить POI, перестроить + +**Шаг 5: Альтернативы** +- Повторить с другим набором POI (другое направление от старта) +- Дать 2–3 варианта + +#### UI + +**Кнопка:** 🎨 «Красивый маршрут» (рядом с 🗺️ «Дикий путь») + +**Панель:** +``` +┌─────────────────────────────────┐ +│ 🎨 Красивый маршрут │ +│ │ +│ 📍 Точка старта: кликни на карте│ +│ 📏 Дистанция: [150] км │ +│ │ +│ [Построить маршрут] │ +└─────────────────────────────────┘ +``` + +**Карточка маршрута (после построения):** +``` +┌─────────────────────────────────┐ +│ 🎨 Северный маршрут 142 км │ +│ ████████████░░░ 4 ч 20 мин │ +│ 89% грунт · 11% асфальт │ +│ │ +│ 💊 Живописные объекты: │ +│ 💧 Озеро Сенеж │ +│ 👁 Смотровая «Высокая» │ +│ 🏚 Заброшенная ферма │ +│ │ +│ [📥 GPX] [Выбрать маршрут] │ +└─────────────────────────────────┘ +``` + +#### Требования +- Время построения ≤ 15 секунд (несколько OSRM запросов) +- Дистанция: ввод от 20 до 500 км +- Кольцевой маршрут = старт и финиш на одной точке +- POI на маршруте показаны в карточке +- Спиннер на время построения +- До 3 вариантов маршрутов + +--- + +### F-14: «Разведка» (Recon Mode) + +#### Описание +Пользователь кликает на карту → система показывает **все грунтовые дороги в радиусе X км** с краткой статистикой: сколько дорог, какая длина, какие типы. + +#### Зачем +«Приехал на новое место — что тут есть?». Не нужно строить маршрут — просто посмотреть какие грунтовки рядом, оценить стоит ли ехать сюда. + +#### Use Cases + +**UC-14.1 — Разведка в новом месте** +> Слава приехал на дачу в незнакомый район. Нажимает 📍 «Разведка», кликает на карту. Появляется круг радиусом 20 км с выделенными грунтовками. Статистика: «124 грунтовки, 380 км грунтовых дорог, 85% grade3-5, 12 бродов». + +**UC-14.2 — Оценка перед поездкой** +> Слава планирует поездку на выходные. Кликает на место на карте — видит что там всего 3 короткие грунтовки. Решает ехать в другое место. + +**UC-14.3 — Настройка радиуса** +> По умолчанию радиус 20 км. Слава меняет на 50 км — видит больше грунтовок. + +#### Алгоритм + +1. Получить координаты клика (lat, lon) +2. Запрос к БД: +```sql +SELECT highway_type, track_type, surface, length_m, name +FROM trails +WHERE min_lon <= ? AND max_lon >= ? AND min_lat <= ? AND max_lat >= ? + AND length_m >= 100 +``` +где bbox = центр ± радиус (0.18° для 20 км, 0.45° для 50 км) +3. Агрегировать: количество, суммарная длина, распределение по типам +4. Отрисовать круг на карте + подсветить грунтовки внутри + +#### UI + +**Кнопка:** 📍 «Разведка» (рядом с 🗺️ и 🎨) + +**Попап при клике:** +``` +┌─────────────────────────────────┐ +│ 📍 Разведка — 20 км радиус │ +│ │ +│ 🛤 124 грунтовки · 380 км │ +│ │ +│ 🟡 Lev1-2: 45 шт · 120 км │ +│ 🔴 Lev3-5: 68 шт · 210 км │ +│ 🔴 Тропы: 11 шт · 50 км │ +│ │ +│ 💧 Озёра: 3 · 👁 Виды: 2 │ +│ 🌊 Броды: 12 · 🏚 Руины: 1 │ +│ │ +│ Радиус: [20] [50] [100] км │ +└─────────────────────────────────┘ +``` + +**На карте:** +- Круг (Circle) с полупрозрачной заливкой +- Грунтовки внутри круга подсвечены (увеличена толщина / opacity) + +#### Требования +- Радиус по умолчанию: 20 км, опции: 20 / 50 / 100 +- Запрос к БД ≤ 2 секунды +- Круг визуально не мешает карте +- Статистика в попапе обновляется при изменении радиуса + +--- + +### F-13: «Связка» (Link Route) + +#### Описание +Пользователь указывает **два трека / точки на карте** → система строит **маршрут между ними по грунтовкам**, минуя асфальт. + +#### Зачем +«Ехал по отличной грунтовке, потом по другой — а между ними 10 км асфальта. Можно ли как-то по грунтовкам перейти?» + +#### Use Cases + +**UC-13.1 — Связать два участка** +> Слава проехал грунтовку А и грунтовку Б. Между ними 8 км асфальта. Нажимает 🔗 «Связка», ставит конечную точку А и начальную точку Б. Система находит обход по грунтовкам: 12 км вместо 8 км асфальта, но 100% грунт. + +**UC-13.2 — Нет грунтовой связки** +> Между двумя точками нет никаких грунтовок — только асфальт. Система: «Грунтовая связка не найдена, кратчайший путь — 5 км по асфальту». + +#### Алгоритм +Это просто роутинг A→B через «Дикий путь» — уже реализовано. Отличие только в UI: +- Вместо кнопки «Дикий путь» — кнопка 🔗 «Связка» +- Маркеры: не A/B, а «Трек 1 (конец)» и «Трек 2 (начало)» +- Карточка показывает только % грунта (асфальт — нежелательный элемент) + +#### UI + +**Кнопка:** 🔗 «Связка» + +**Панель:** +``` +┌─────────────────────────────────┐ +│ 🔗 Связка │ +│ │ +│ 1️⃣ Конец трека: кликни на карте│ +│ 2️⃣ Начало трека: кликни │ +│ │ +│ [Найти грунтовую связку] │ +└─────────────────────────────────┘ +``` + +**Карточка:** +``` +┌─────────────────────────────────┐ +│ 🔗 Связка 12 км │ +│ ██████████████████░ 24 мин │ +│ 92% грунт · 8% асфальт │ +│ │ +│ [📥 GPX] [Выбрать] │ +└─────────────────────────────────┘ +``` + +#### Требования +- Использует тот же OSRM «Дикий путь» роутинг +- Отличие от «Дикого пути» — только UI (другие маркеры, акцент на минимизацию асфальта) +- До 3 альтернативных связок + +--- + +## 3. Нефункциональные требования + +### Производительность +- «Красивый маршрут» — ≤ 15 сек (3–5 OSRM запросов) +- «Разведка» — ≤ 2 сек (один SQL запрос) +- «Связка» — ≤ 5 сек (один OSRM запрос) + +### UI +- 3 новые кнопки в панели управления: 🎨 🔗 📍 +- Режимы взаимоисключающие: активный режим деактивирует остальные +- При переключении режима — сброс предыдущего состояния + +--- + +## 4. Приоритет реализации + +| # | Фича | Приоритет | Сложность | Ценность | +|---|------|-----------|-----------|----------| +| F-14 | «Разведка» | 🔴 Высокий | Низкая | Высокая | +| F-13 | «Связка» | 🟡 Средний | Низкая | Средняя | +| F-11 | «Красивый маршрут» | 🔴 Высокий | Высокая | Очень высокая | + +**Рекомендуемый порядок:** +1. **F-14 «Разведка»** — простая SQL-агрегация, быстрый результат, высокая ценность +2. **F-13 «Связка»** — почти готово (переиспользуем OSRM), минимум нового кода +3. **F-11 «Красивый маршрут»** — самый сложный (алгоритм выбора POI, несколько OSRM запросов), но самый ценный + +--- + +## 5. Открытые вопросы для Славы + +1. **«Красивый маршрут» — дистанция:** вводишь вручную или слайдер? Предлагаю: текстовое поле + пресеты (50 / 100 / 150 / 200 км). + +2. **«Красивый маршрут» — направление:** хочешь выбрать направление (север/юг/запад/восток) или система сама подбирает? Направление полезно — «хочу на север, к озёрам». + +3. **«Разведка» — радиус:** 20/50/100 км — ок, или хочешь другие значения? + +4. **«Связка» — как указать точки:** просто клик на карте (как «Дикий путь») или клик на конкретную грунтовку? + +5. **Нужно ли «Красивому маршруту» учитывать сезонность?** Например, броды весной непроходимы. Пока не учитываем — это отдельная фича. + +--- + +*Документ готов к согласованию. После ответов — обновлю и передам Dev-агенту.* diff --git a/tasks/enduro-trails/PROJECT.md b/tasks/enduro-trails/PROJECT.md index 5d54269..7d94b0f 100644 --- a/tasks/enduro-trails/PROJECT.md +++ b/tasks/enduro-trails/PROJECT.md @@ -2,7 +2,7 @@ > OSM-карта с фокусом на грунтовые дороги для построения красивых эндуро-маршрутов -**Статус:** active (прототип задеплоен) +**Статус:** active **Старт:** 2026-05-02 **Автор:** Слава @@ -12,147 +12,187 @@ Обычные карты оптимизированы под автомобили — асфальт яркий, грунтовки не видны. Enduro Trails переворачивает эту логику: **грунтовки/тропы — главный слой**, асфальт — тусклый фон. Плюс фичи для поиска и построения красивых маршрутов (минимум асфальта, максимум красоты). -## Ключевые фичи +--- -| Фича | Описание | -|------|----------| -| 🛤️ **"Дикий путь"** | Роутинг А→Б с максимизацией грунтовок (OSRM) | -| 🔍 **"Поиск"** | Поиск населённых пунктов и адресов (Nominatim) | -| 📏 **"Линейка"** | Измерение расстояния между точками на карте | -| 🚩 **"Флажки/метки"** | Расстановка именованных меток на карте | -| 🗺️ **"Умный маршрут"** | Промежуточные точки, % асфальт/грунт/тропа, GPX экспорт | -| 🎨 **"Красивый маршрут"** | Замкнутый круг через водоёмы, виды, заброшки | -| 🏔️ **"Горка"** | Макс набор высоты, мин дистанция (SRTM) | -| 🔗 **"Связка"** | Соединить два трека грунтовками | -| 📍 **"Разведка"** | Грунтовки вокруг точки | -| 🚧 **"Препятствия"** | Броды, шлагбаумы, болота, ЛЭП | -| 🌐 **"Народные треки"** | Сбор и отображение треков с внешних сервисов | -| 🌙 **"День/ночь"** | Переключатель темы — светлая/тёмная карта | -| 🎨 **"Эндуро-дизайн"** | Современный агрессивный UI в духе эндуро/оффроад | - -## Регионы +## Регион 1. **ЦФО + Чувашия** (первый регион, прототип) 2. Расширение на новые ФО по запросу +--- + ## Архитектура ### Стек - - Pyrosm/Osmium → парсинг PBF - Spatialite → хранение (прототип), PostGIS → продакшен - OSRM (кастомный профиль `enduro.lua`) → роутинг - FastAPI + uvicorn (4 workers) → бэкенд - MapLibre GL JS → фронт (веб + PWA) -### Инфраструктура (прототип) - -- **Сервер:** `slin@82.22.50.71`, sudo пароль `motoZ@yaz2010` -- **Контейнер:** `prototype-enduro-trails-1`, порт `5558` +### Инфраструктура +- **Сервер:** `slin@82.22.50.71`, sudo `motoZ@yaz2010` +- **Контейнер приложения:** `prototype-enduro-trails-1`, порт `5558` - **URL:** `https://openclaw.mva154.duckdns.org/enduro/` - **Код на сервере:** `/home/slin/enduro-trails/prototype/` - **Workspace:** `/home/node/.openclaw/workspace/tasks/enduro-trails/prototype/` -- **БД:** `/home/slin/enduro-trails/data/centralfederal.sqlite` (431 MB) - -### OSRM - -- **Данные:** `/home/slin/enduro-trails/data/enduro.osrm.*` -- **PBF:** `/home/slin/enduro-trails/data/enduro.osm.pbf` -- **Профиль:** `/home/slin/enduro-trails/osrm/enduro.lua` -- **Docker compose:** `/home/slin/enduro-trails/osrm/docker-compose.yml` -- **Контейнер:** `osrm-osrm-routed-1`, порт `5559` -- **OSRM_URL в app.py:** `http://172.22.0.1:5559` +- **БД:** `/home/slin/enduro-trails/data/centralfederal.sqlite` (431 MB, 1.1M треков, 14K POI) +- **OSRM контейнер:** `osrm-osrm-routed-1`, порт `5559` +- **OSRM данные:** `/home/slin/enduro-trails/data/enduro.osrm.*` (~5.2 GB) +- **OSRM профиль:** `/home/slin/enduro-trails/osrm/enduro.lua` - **Swap:** `/home/slin/swapfile3` (4 GB), итого 6 GB swap +- **Деплой:** Node.js ssh2 (SSH бинарник в контейнере не работает — glibc 2.36 vs 2.38) -## Текущее состояние (2026-05-03) +### Деплой +```bash +# SFTP через ssh2: /tmp/deploy_app.js +# docker cp + restart (файлы запечены в образ) +docker cp /home/slin/enduro-trails/prototype/app.py prototype-enduro-trails-1:/app/app.py +docker restart prototype-enduro-trails-1 +``` -### ✅ Готово - -**OSRM роутинг:** -- ✅ «Дикий путь» — OSRM с кастомным профилем `enduro.lua` -- ✅ `weight_name = 'routability'` (не `duration` — не оптимизирует по времени) -- ✅ `forward_speed = 30` для всех типов дорог (duration не влияет на выбор) -- ✅ `forward_rate` определяет предпочтительность: track=100, bridleway=90, path=85, motorway=0.1 -- ✅ `tracktype` мультипликатор: grade1×1.3, grade3×1.0, grade5×0.8 -- ✅ U-turn penalty 20s, нет односторонних ограничений -- ✅ Граф: `enduro.osrm.*` (~5.2 GB), собран из `enduro.osm.pbf` (ЦФО + Чувашия) -- ✅ Контейнер `osrm-osrm-routed-1`, порт 5559, OSRM_URL=`http://172.22.0.1:5559` - -**Инфраструктура:** -- Прототип задеплоен: `https://openclaw.mva154.duckdns.org/enduro/` -- БД: 1 141 926 треков, 14 882 POI (Spatialite) -- Векторные тайлы (MVT) через FastAPI, 4 uvicorn workers -- FIFO-кэш тайлов (512 тайлов в памяти) [реализация — FIFO, не LRU] -- Упрощение геометрии по зуму (Shapely simplify) -- Фильтр треков по длине на низких зумах (z8: ≥500м, z9: ≥200м) -- Dockerfile — быстрый старт без apt/pip при рестарте -- Nginx `/enduro/` с HTTPS - -**Карта и UI:** -- MapLibre GL JS, легенда (Lev1-2 / Lev3-5 / Тропа) -- Раскраска: Lev1-2 жёлтый (#FFD700), Lev3-5 красный (#FF4400) -- Тропы (path/footway/bridleway) — красный пунктир (#cc0000) -- Асфальт скрыт (visibility: none) -- Подложка: saturation -0.4, contrast 0.25, brightness-max 0.9 -- Кнопка 🧭 компас (север/свободный режим) -- Кнопка 📍 геолокация с пульсирующим маркером -- Попапы: name, surface, tracktype, length_m, mtb_scale - -**Фичи:** -- ✅ Роутинг "Дикий путь" — кнопка 🗺️, маркеры A/B, карточка с дистанцией и временем -- ✅ Поиск (Nominatim) — строка в хедере, debounce 400ms, flyTo -- ✅ Линейка 📏 — кружки точно на координатах, плашки над ними, крестик удаления, haversine расстояние - -### ⏳ Бэклог - -**Фаза 3 — Умный маршрут:** -- Промежуточные точки (перетаскиваемые) -- Статистика: % асфальт / lev1-2 / lev3-5 / тропа -- Скачать GPX - -**Фаза 4 — Флажки/метки:** -- Расстановка именованных меток на карте -- Сохранение в localStorage - -**Фаза 5 — Редизайн:** -- Тёмная тема, эндуро-стиль, адаптив под мобилку - -**Фаза 6 — SRTM рельеф:** -- "Горка" — макс набор высоты -- Профиль высот на маршруте - -**Фаза 7 — PWA + офлайн:** -- Service Worker, офлайн MBTiles, GPS-трекинг - -**Фаза 8 — Народные треки:** -- Источники: OSM Traces, Wikiloc, Komoot, 4x4travel.ru, Enduroad.ru -- Отдельный слой `community_tracks`, фильтрация по типу активности +--- ## Схема БД ```sql --- trails -id, osm_id, highway_type, track_type, surface, name, length_m, -mtb_scale, visibility, smoothness, access, tags, geom BLOB, -min_lon, max_lon, min_lat, max_lat +-- trails: id, osm_id, highway_type, track_type, surface, name, length_m, +-- mtb_scale, visibility, smoothness, access, tags, geom BLOB, +-- min_lon, max_lon, min_lat, max_lat --- poi -id, osm_id, poi_type, name, geom BLOB, lon, lat --- Примечание: poi НЕ имеет поля tags +-- poi: id, osm_id, poi_type, name, geom BLOB, lon, lat ``` +--- + +## Реестр фич + +| ID | Фича | Описание | Статус | Фаза | +|----|------|----------|--------|------| +| F-01 | Альтернативные маршруты | До 5 вариантов с разным балансом грунт/асфальт | ✅ Готово | 3 | +| F-02 | Статистика маршрута | Карточки с % покрытия, полоска, развёрнутый вид | ✅ Готово | 3 | +| F-03 | Человекочитаемое время | "2 ч 35 мин" вместо "155 мин" | ✅ Готово | 3 | +| F-04 | Промежуточные точки | Добавление, удаление, drag, debounce 300ms | ✅ Готово | 3 | +| F-05 | GPX экспорт | Трек + waypoints + флажки, имя enduro-YYYYMMDDHHMMSS.gpx | ✅ Готово | 3 | +| F-06 | Флажки/метки | localStorage, попап → A / → B / удалить, иконки | ✅ Готово | 3 | +| F-07 | Исключить шлагбаумы | Баррьеры → inaccessible в OSRM | 📋 BRD готов | 3.1 | +| F-08 | Исключить тротуары | footway/pedestrian/steps убрать из графа | 📋 BRD готов | 3.1 | +| F-09 | Больше альтернатив | Penalized re-query + дедупликация | 📋 BRD готов | 3.1 | +| F-10 | Слой препятствий | Шлагбаумы, броды, блокпосты на карте | 📋 BRD готов | 3.1 | +| F-11 | "Красивый маршрут" | Замкнутый круг через водоёмы, виды, заброшки | ⏳ Бэклог | 4 | +| F-12 | "Горка" | Макс набор высоты, мин дистанция (SRTM) | ⏳ Бэклог | 6 | +| F-13 | "Связка" | Соединить два трека грунтовками | ⏳ Бэклог | 4 | +| F-14 | "Разведка" | Грунтовки вокруг точки | ⏳ Бэклог | 4 | +| F-15 | "Народные треки" | OSM Traces, Wikiloc, Komoot, 4x4travel | ⏳ Бэклог | 8 | +| F-16 | Тёмная тема | День/ночь + эндуро-дизайн | ⏳ Бэклог | 5 | +| F-17 | PWA + офлайн | Service Worker, MBTiles, GPS-трекинг | ⏳ Бэклог | 7 | + +--- + +## Выполненные фазы + +### ✅ Фаза 1 — MVP (02.05.2026) +- PBF парсинг (ЦФО + Чувашия) +- Spatialite БД (1.1M треков, 14K POI) +- FastAPI self-hosted MVT тайлы +- MapLibre GL JS карта с кастомным стилем +- Попапы с информацией о дороге +- Контролы слоёв + +### ✅ Фаза 2 — Роутинг + UI (03.05.2026) +- OSRM + кастомный профиль `enduro.lua` (порт 5559) +- Роутинг «Дикий путь» — кнопка 🗺️, маркеры A/B +- Поиск (Nominatim, debounce 400ms) +- Линейка 📏 (haversine) +- Геолокация 📍, компас 🧭 + +### ✅ Фаза 3 — Умный маршрут (04.05.2026) +- **F-01:** Альтернативные маршруты (до 5, цвета: синий/зелёный/фиолетовый/оранжевый/серый) +- **F-02:** Статистика покрытия (карточки: компактные + развёрнутые, полоска покрытия, %) +- **F-03:** `formatDuration()` — "2 ч 35 мин" / "1 дн 2 ч 50 мин" +- **F-04:** Промежуточные точки (до 8, draggable, debounce 300ms) +- **F-05:** GPX 1.1 экспорт (трек + waypoints + флажки) +- **F-06:** Флажки 🚩 (localStorage, 50 лимит, попап → A / → B / удалить) + +**Баги исправлены (04.05):** +- formatDuration(86400) → "1 дн" (не "1 дн 0 ч") +- OSRM TooBig → retry 5→3→1 +- Панель маршрута перекрывала кнопки → CSS right: 56px +- Длинные маршруты не строились → radiuses=5000 + NoSegment retry с 10km + timeout 60s + +--- + +## Бэклог по фазам + +### 📋 Фаза 3.1 — Улучшение роутинга (BRD готов, ожидает согласования) +**BRD:** `BRD_PHASE3.1.md` + +| Фича | Описание | Сложность | Требует | +|------|----------|-----------|---------| +| F-07 | Шлагбаумы → inaccessible в OSRM | Низкая (lua) | Пересборка графа ~40 мин | +| F-08 | Убрать footway/pedestrian/steps из графа | Низкая (lua) | Пересборка графа ~40 мин | +| F-09 | Penalized re-query для разных альтернатив | Высокая | — | +| F-10 | Слой препятствий на карте (🚧🌊⛔) | Средняя | Перепарсинг PBF ~30 мин | + +**Порядок:** F-07+F-08 вместе (одна пересборка) → F-09 → F-10 + +### ⏳ Фаза 4 — Продвинутый роутинг +- F-11 «Красивый маршрут» — замкнутый круг через живописные места (озёра, виды, заброшки) + - Оценка аттрактивности: близость к воде +10, перепад высот +15, viewpoints +20 +- F-13 «Связка» — соединить два трека грунтовками +- F-14 «Разведка» — все грунтовки в радиусе X км от точки + +### ⏳ Фаза 5 — Редизайн +- F-16 Тёмная тема + эндуро-стиль + адаптив под мобилку + +### ⏳ Фаза 6 — SRTM рельеф +- F-12 «Горка» — макс набор высоты, мин дистанция +- Профиль высот на маршруте +- SRTM DEM 30м данные (Public Domain) + +### ⏳ Фаза 7 — PWA + офлайн +- F-17 Service Worker, офлайн MBTiles, GPS-трекинг в реальном времени +- Интеграция с OsmAnd/Locus (экспорт) + +### ⏳ Фаза 8 — Народные треки +- F-15 Источники: OSM Traces, Wikiloc, Komoot, 4x4travel.ru, Enduroad.ru +- Отдельный слой `community_tracks`, фильтрация по типу активности + +--- + ## Ключевые решения | Решение | Причина | |---------|---------| | 4 uvicorn workers | Устранение узкого места однопоточности | -| Фильтр по length_m на низких зумах | Производительность, читаемость карты | -| Относительные пути в app.js | Работает и через nginx /enduro/, и по прямому IP | -| Dockerfile вместо inline apt+pip | Устранил 452 рестарта контейнера | -| OSRM `weight_name='routability'` | `duration` → OSRM выбирал асфальт как быстрый | -| `forward_rate = penalty` (не /speed) | Penalty/метр — прямой вес пути | -| Два маркера на точку линейки | Кружок anchor:center точно на координатах, плашка offset вверх | -| stopPropagation на крестике линейки | Клик не проваливался на карту и не ставил новую точку | +| Фильтр по length_m на низких зумах | Производительность, читаемость | +| Относительные пути в app.js | Работает через nginx /enduro/ и по прямому IP | +| OSRM `weight_name='routability'` | `duration` → OSRM выбирал асфальт | +| `forward_rate = penalty` | Penalty/метр — прямой вес пути | +| `radiuses=5000` в OSRM запросах | Без этого длинные маршруты не снэппятся | +| Retry TooBig: 5→3→1 | OSRM не даёт 5 альтернатив на длинных маршрутах | +| Retry NoSegment: radiuses=10000 | Точки далеко от дорог — нужен широкий snap | +| Timeout 60s для retry | Длинные маршруты строятся >30с | +| Node.js ssh2 для деплоя | SSH бинарник в контейнере требует glibc 2.38 | +| docker cp вместо compose build | Файлы запечены в образ, cp в running container быстрее | +| Сэмплирование каждые ~500м для stats | Без этого расчёт >30с на длинных маршрутах | +| Grid cache для calc_route_stats | Убирает повторные SQL запросы для близких точек | + +--- + +## Документы + +| Документ | Описание | +|----------|----------| +| `PROJECT.md` | Этот файл — общее состояние проекта | +| `CONCEPT.md` | Концепция и архитектура | +| `TECHNICAL_SPEC.md` | ТЗ прототипа v0.1 | +| `DEV_TASK.md` | Стабилизация v0.1 (архив) | +| `BRD_PHASE3.md` | Бизнес-требования Фазы 3 (согласовано) | +| `BRD_PHASE3.1.md` | Бизнес-требования Фазы 3.1 (на согласовании) | +| `TEST_CASES_PHASE3.md` | 56 тест-кейсов | +| `DEV_TASK_PHASE3.md` | ТЗ для Dev-агента Фаза 3 | +| `reports/` | Отчёты о тестировании | ---