# Heatmap API - Тепловые карты с кэшированием ## Endpoint ### GET /api/v1/stats/heatmap Получить данные для тепловой карты находок с 4 типами визуализации и кэшированием на 1 час. ## Типы карт (map_type) ### 1. `all` - Все точки Все точки с одинаковой интенсивностью (1.0). **Использование:** Общий обзор всех находок. **Пример:** ```bash curl "http://localhost:8000/api/v1/stats/heatmap?map_type=all" ``` **Response:** ```json { "points": [ { "lat": 53.92, "lon": 27.58, "intensity": 1.0, "case_id": "uuid", "metadata": { "age": 10, "season": "лето", "outcome": "alive" } } ], "total": 1, "filters_applied": {"map_type": "all"} } ``` ### 2. `age` - По возрасту Интенсивность зависит от возраста: младше = выше интенсивность (более критично). **Формула:** `intensity = max(0.3, 1.0 - (age / 18.0))` **Использование:** Приоритизация поиска младших детей. **Пример:** ```bash curl "http://localhost:8000/api/v1/stats/heatmap?map_type=age&age_group=8-11" ``` **Response:** ```json { "points": [ { "lat": 53.92, "lon": 27.58, "intensity": 0.44, "case_id": "uuid", "metadata": { "age": 10, "age_group": "8-11" } } ], "total": 1, "filters_applied": { "map_type": "age", "age_group": "8-11" } } ``` ### 3. `season` - По сезону Интенсивность зависит от сезона (зима = критичнее). **Интенсивности:** - Зима: 1.0 (красный) - Осень: 0.8 (оранжевый) - Весна: 0.6 (желтый) - Лето: 0.4 (зеленый) **Использование:** Анализ сезонных паттернов. **Пример:** ```bash curl "http://localhost:8000/api/v1/stats/heatmap?map_type=season&season=зима" ``` ### 4. `outcome` - По исходу Интенсивность зависит от исхода поиска. **Интенсивности:** - Погиб: 1.0 (красный) - Выжил: 0.5 (зеленый) - Неизвестно: 0.3 (серый) **Использование:** Анализ опасных зон. **Пример:** ```bash curl "http://localhost:8000/api/v1/stats/heatmap?map_type=outcome&outcome=alive" ``` **Response:** ```json { "points": [ { "lat": 53.92, "lon": 27.58, "intensity": 0.5, "case_id": "uuid", "metadata": { "outcome": "alive", "distance_km": 2.5 } } ], "total": 1, "filters_applied": { "map_type": "outcome", "outcome": "alive" } } ``` ## Query Parameters (фильтры) | Параметр | Тип | Описание | Пример | |----------|-----|----------|--------| | `map_type` | string | Тип карты: all, age, season, outcome | `map_type=age` | | `age_group` | string | Возрастная группа: 0-3, 4-7, 8-11, 12-14, 15-17, 18+ | `age_group=8-11` | | `season` | string | Сезон: зима, весна, лето, осень | `season=лето` | | `year_from` | int | Год начала периода | `year_from=2020` | | `year_to` | int | Год окончания периода | `year_to=2026` | | `outcome` | string | Исход: alive, deceased | `outcome=alive` | ## Кэширование **Механизм:** `functools.lru_cache` с автоматической инвалидацией каждый час. **Параметры кэша:** - Размер: 128 комбинаций параметров - TTL: 1 час (автоматически через timestamp_hour) - Ключ: `{map_type}_{age_group}_{season}_{year_from}_{year_to}_{outcome}_{hour}` **Преимущества:** - Быстрый отклик для повторных запросов - Снижение нагрузки на БД - Автоматическая очистка устаревших данных ## Примеры использования ### 1. Все находки за 2025 год ```bash curl "http://localhost:8000/api/v1/stats/heatmap?map_type=all&year_from=2025&year_to=2025" ``` ### 2. Младшие дети (0-7 лет) зимой ```bash curl "http://localhost:8000/api/v1/stats/heatmap?map_type=age&age_group=0-3&season=зима" ``` ### 3. Опасные зоны (погибшие) ```bash curl "http://localhost:8000/api/v1/stats/heatmap?map_type=outcome&outcome=deceased" ``` ### 4. Подростки летом (последние 3 года) ```bash curl "http://localhost:8000/api/v1/stats/heatmap?map_type=age&age_group=12-14&season=лето&year_from=2023&year_to=2026" ``` ## Интеграция с фронтендом ### Leaflet.js пример ```javascript // Получить данные const response = await fetch('/api/v1/stats/heatmap?map_type=age'); const data = await response.json(); // Создать heatmap слой const heatPoints = data.points.map(p => [p.lat, p.lon, p.intensity]); const heat = L.heatLayer(heatPoints, { radius: 25, blur: 15, maxZoom: 17, gradient: { 0.0: 'green', 0.5: 'yellow', 1.0: 'red' } }).addTo(map); ``` ## Протестировано (2026-05-05) ✅ `map_type=all` - работает (intensity: 1.0) ✅ `map_type=age` - работает (intensity: 0.44 для 10 лет) ✅ `map_type=season` - работает ✅ `map_type=outcome` - работает (intensity: 0.5 для alive) ✅ Фильтры: age_group, season, outcome - работают ✅ Кэширование: lru_cache с TTL 1 час ## Технические детали **Файлы:** - `backend/services/stats_service.py` - функции `get_heatmap_with_cache()`, `get_heatmap_data_cached()` - `backend/api/v1/stats.py` - endpoint `/heatmap` **Зависимости:** - `functools.lru_cache` - встроенный кэш Python - SQLAlchemy - фильтрация по БД - Pydantic - валидация типов ## Дата создания 2026-05-05