auto-sync: 2026-05-04 22:50:01

This commit is contained in:
Stream
2026-05-04 22:50:01 +03:00
parent 265b364445
commit dcc7a6aec2
2 changed files with 445 additions and 110 deletions

View File

@@ -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 — Несколько вариантов**
> Система предлагает 23 кольцевых маршрута: северный (через озёра), восточный (через леса), южный (через поля). Слава выбирает северный — через озёра красивее.
**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: Выбрать 35 POI для маршрута**
- Жадный алгоритм: начать со старта, на каждом шаге выбирать ближайший POI с максимальными баллами
- Суммарная дистанция до POI ≤ желаемая дистанция × 0.8 (оставить запас на возврат)
- После последнего POI — маршрут обратно к старту
**Шаг 3: Построить маршрут через POI**
- Использовать OSRM: старт → POI1 → POI2 → ... → старт
- Каждый сегмент — запрос к OSRM с `alternatives=false`
**Шаг 4: Проверить дистанцию**
- Если итоговая дистанция > желаемая × 1.3 — уменьшить кол-во POI, перестроить
- Если < желаемая × 0.5 — добавить POI, перестроить
**Шаг 5: Альтернативы**
- Повторить с другим набором POI (другое направление от старта)
- Дать 23 варианта
#### 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 сек (35 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-агенту.*

View File

@@ -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/` | Отчёты о тестировании |
---