Files
wiki/tasks/enduro-trails/TECHNICAL_SPEC.md
2026-05-04 09:40:01 +03:00

274 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Техническое задание: Прототип Enduro Trails v0.1
**Проект:** Enduro Trails 🏍️
**Документ:** TECHNICAL_SPEC.md
**Версия:** 0.1
**Дата:** 02.05.2026
**Автор:** Стрим 🌊
**Исполнитель:** Dev-агент
**Статус:** на согласовании
---
## 1. Цель
Создать прототип на mva154, который визуализирует грунтовые дороги ЦФО+Чувашия на карте с «перевёрнутой логикой»: грунтовки яркие и заметные, асфальт — тусклый фон. Без роутинга — только данные + визуализация.
---
## 2. Область (Scope)
### ✅ Включено в v0.1
- Скачивание PBF дампа с Geofabrik (ЦФО)
- Парсинг дорог (highway=track, highway=path) с тегами
- Импорт в Spatialite (.sqlite файл)
- Слой POI (водоёмы, видовые точки, заброчки)
- Генерация Mapbox GL совместимых тайлов (z10z16)
- Кастомный стиль: грунтовки яркие, асфальт серый
- Веб-карта (MapLibre GL JS) с контролами слоёв
- Клик по дороге → popup с информацией
### ❌ НЕ включено в v0.1
- OSRM роутинг (фаза 2)
- SRTM рельеф + уклоны (фаза 3)
- PWA / оффлайн работа (фаза 5)
- GPS трекинг
- Мобильное приложение
- «Красивый маршрут», «Горка», «Связка» и прочие алгоритмы
---
## 3. Технические требования
### 3.1 Хост
- **Сервер:** mva154 (localhost, Docker)
- **Порт:** 5558 (или первый свободный 555X)
- **Доступ:** Docker контейнеры + docker-compose
- **Ресурсы:** без ограничений (это прототип)
### 3.2 Источник данных
| Параметр | Значение |
|----------|----------|
| **Формат** | OSM PBF |
| **Источник** | `https://download.geofabrik.de/russia/centralfederal.ru-latest.osm.pbf` + `https://download.geofabrik.de/russia/volga.osm.pbf` |
| **Регион** | Центральный ФО + Чувашия (Приволжский ФО) |
| **Чувашия** | ⚠️ Чувашия входит в Приволжский ФО, не в ЦФО. Скачать `volga.osm.pbf`, объединить с `centralfederal.osm.pbf` через `osmium merge`, затем отфильтровать по BBOX |
| **BBOX фильтрация** | west=30.0, east=48.0, south=51.0, north=59.0 (east расширен до 48.0 чтобы захватить Чувашию) |
### 3.3 Парсинг
**Инструмент:** Pyrosm (Python) + osmium
**Фильтр дорог (выбираем):**
```
highway: track, path, bridleway, cycleway, footway (для связки)
```
**Теги для каждого сегмента:**
| Тег | Описание |
|-----|----------|
| `surface` | paved, unpaved, gravel, sand, mud, earth, grass, asphalt, concrete |
| `tracktype` | grade1grade5 |
| `mtb:scale` | 06 |
| `trail_visibility` | yes, no, negative |
| `smoothness` | excellent, good, intermediate, bad, very_bad, horrible |
| `access` | private, no, permissive, destination |
| `vehicle` | yes, no, agricultural, forestry |
| `name` | название (если есть) |
| `osm_id` | ID из OSM |
| `geometry` | LINESTRING |
| `length_m` | длина в метрах (рассчитать) |
**POI точки:**
```
natural=water + name (озёра, реки — крупные)
tourism=viewpoint (видовые точки)
historic=ruins / abandoned=yes (заброшки)
natural=peak (вершины)
natural=cave_entrance (пещеры)
ford=yes (броды)
```
### 3.4 Хранение — Spatialite
**Файл:** `tasks/enduro-trails/data/centralfederal.sqlite`
**Таблица `trails`:**
```sql
CREATE TABLE trails (
id INTEGER PRIMARY KEY AUTOINCREMENT,
osm_id INTEGER NOT NULL,
highway_type TEXT,
track_type TEXT,
surface TEXT,
name TEXT,
length_m REAL,
mtb_scale TEXT,
visibility TEXT,
smoothness TEXT,
access TEXT,
tags TEXT, -- JSON с остальными тегами
geom GEOMETRY -- LINESTRING, SRID 4326
);
-- ⚠️ Spatialite синтаксис (НЕ PostGIS!)
SELECT CreateSpatialIndex('trails', 'geom');
CREATE INDEX idx_trails_highway ON trails(highway_type);
CREATE INDEX idx_trails_surface ON trails(surface);
```
**Таблица `poi`:**
```sql
CREATE TABLE poi (
id INTEGER PRIMARY KEY AUTOINCREMENT,
osm_id INTEGER NOT NULL,
poi_type TEXT, -- lake, viewpoint, ruins, peak, cave, ford
name TEXT,
geom GEOMETRY -- POINT, SRID 4326
);
-- ⚠️ Spatialite синтаксис (НЕ PostGIS!)
SELECT CreateSpatialIndex('poi', 'geom');
CREATE INDEX idx_poi_type ON poi(poi_type);
```
### 3.5 Генерация тайлов
**Формат:** Mapbox GL совместимые векторные тайлы (PBF + JSON)
**Уровни:** z10, z11, z12, z13, z14, z15, z16
**Варианты реализации:**
1. **Spatialite → MBTiles → TileServer GL** — конвертация через `tippecanoe` или `ogr2ogr`, затем TileServer GL отдаёт MBTiles
2. **Martin** (Rust) — быстрый тайл-сервер, поддерживает SQLite/MBTiles напрямую, проще цепочка
3. **Python self-hosted** — FastAPI отдаёт тайлы на лету из Spatialite
**Рекомендация:** Martin через Docker — поддерживает SQLite напрямую, минимум шагов.
⚠️ **Важно:** TileServer GL не работает с Spatialite напрямую — нужна конвертация в MBTiles (tippecanoe или ogr2ogr) перед использованием.
**Слои тайлов:**
| Слой | Источник | Описание |
|------|----------|----------|
| `trails` | trails table | Все грунтовые дороги |
| `poi` | poi table | Точки интереса |
### 3.6 Стиль карты (Mapbox GL Style JSON)
**Принцип «перевёрнутой логики»:**
| Элемент | Стиль |
|---------|-------|
| Грунтовки (grade35, unpaved) | Яркие оранжевые/жёлтые линии, толщина 34px |
| Грунтовки (grade12, paved) | Средние оранжевые, толщина 2px |
| Path/bridleway | Пунктирные жёлтые, толщина 1.5px |
| Асфальт primary+ | Тонкие серые, 1px |
| Асфальт secondary/tertiary | Серые, 1.5px |
| Fon | Очень тёмный/приглушённый |
| POI озёра | 💙 голубые точки |
| POI viewpoints | 📷 фиолетовые |
| POI ruins | 🏚️ коричневые |
| POI peaks | 🔺 красные треугольники |
### 3.7 Веб-карта (Frontend)
**Технологии:**
- HTML + CSS + JavaScript (Vanilla или React по выбору Dev-агента)
- MapLibre GL JS (CDN, без сборки)
**Структура:**
```
tasks/enduro-trails/prototype/
├── app.py # FastAPI сервер (раздаёт статику + API)
├── static/
│ ├── index.html
│ ├── style.json # MapLibre GL Style
│ ├── app.js # Логика карты
│ └── app.css
└── data/
└── centralfederal.sqlite
```
**Функции (всё выполнено ✅):**
- [x] Отображение карты с кастомным стилем
- [x] Контролы слоёв (вкл/выкл: грунтовки, POI)
- [x] Клик по дороге → popup (name, surface, tracktype, length)
- [x] Клик по POI → popup (name, type)
- [x] Поиск по bbox (кнопка «показать всё»)
- [x] Зум/пан — стандартные
---
## 4. Структура проекта
```
tasks/enduro-trails/
├── PROJECT.md
├── CONCEPT.md
├── TECHNICAL_SPEC.md
├── DEV_TASK.md
├── TASKS/
│ └── active/
│ └── prototype-setup/
│ └── TASK.md
├── prototype/
│ ├── app.py # FastAPI: /api/tiles, /api/route, /api/health, /api/cache/clear
│ ├── requirements.txt
│ ├── Dockerfile
│ ├── docker-compose.yml
│ ├── README.md
│ └── static/
│ ├── index.html
│ ├── app.js
│ ├── app.css
│ └── style.json
├── scripts/
│ ├── parse.py # Парсинг PBF → SQLite (Spatialite)
│ ├── requirements-parse.txt
│ └── smoke_check.py
└── osrm/
└── enduro.lua # Профиль OSRM (кастомный по грунтовкам)
```
---
## 5. Критерии приёмки (Acceptance Criteria)
Прототип считается готовым когда:
1. ✅ Скачан PBF дамп ЦФО с Geofabrik
2.`parse.py` парсит PBF → `centralfederal.sqlite` (trails + POI)
3. ✅ Тайлы генерируются (FastAPI on-the-fly из SQLite)
4.Веб-карта на `localhost:5558` показывает:
- Грунтовки яркие (жёлтые/красно-оранжевые)
- Асфальт тусклый (серый)
- POI отображаются иконками
5. ✅ Клик по дороге → popup с name, surface, tracktype, length
6. ✅ Базовые контролы слоёв (toggle trails, POI)
7.`docker-compose up` запускает всё одной командой
---
## 6. Ограничения и заметки
- **Без роутинга** — OSRM ставится в фазе 2
- **Без рельефа** — SRTM слой в фазе 3
- **Без PWA** — только веб, вёрстка для десктопа
- **Один регион** — ЦФО, масштабирование потом
- **Данные статичные** — обновление PBF = перезапуск parse.py
- **Без авторизации** — локальный хост, только для Славы пока
- **Pyrosm** может потребовать GDAL — если сложно, использовать Osmium
---
## 7. Следующие шаги (после v0.1)
| Фаза | Что | Приоритет |
|------|-----|-----------|
| Фаза 2 | OSRM роутинг + «Дикий путь» | High |
| Фаза 3 | SRTM рельеф + уклоны | Medium |
| Фаза 4 | «Красивый маршрут», «Горка» | Medium |
| Фаза 5 | PWA + оффлайн | Low |
---
*Документ создан автоматически. Для правок — связаться со Стрим.*