From 2a2dbe8d1ef57dfbcc48421178697116f88476d4 Mon Sep 17 00:00:00 2001 From: Stream Date: Mon, 4 May 2026 23:30:01 +0300 Subject: [PATCH] auto-sync: 2026-05-04 23:30:01 --- tasks/enduro-trails/prototype/app.py | 90 ++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/tasks/enduro-trails/prototype/app.py b/tasks/enduro-trails/prototype/app.py index f6d70c9..1404154 100644 --- a/tasks/enduro-trails/prototype/app.py +++ b/tasks/enduro-trails/prototype/app.py @@ -484,6 +484,96 @@ async def get_tile(z: int, x: int, y: int): ) +@app.post("/api/recon") +async def post_recon(req: ReconRequest): + """ + Разведка: агрегация trails + POI в радиусе от точки. + """ + lon, lat, radius_km = req.lon, req.lat, req.radius_km + lat_rad = math.radians(lat) + delta_lat = radius_km / 111.0 + delta_lon = radius_km / (111.0 * math.cos(lat_rad)) + + try: + conn = get_db() + cur = conn.cursor() + + # Trails — агрегация по типам + cur.execute(""" + SELECT highway_type, track_type, SUM(length_m) as total_m, COUNT(*) as cnt + FROM trails + WHERE min_lon <= ? AND max_lon >= ? + AND min_lat <= ? AND max_lat >= ? + AND length_m >= 100 + GROUP BY highway_type, track_type + """, (lon + delta_lon, lon - delta_lon, lat + delta_lat, lat - delta_lat)) + trail_rows = cur.fetchall() + + # Агрегация по категориям + lev12_count, lev12_km = 0, 0.0 + lev345_count, lev345_km = 0, 0.0 + path_count, path_km = 0, 0.0 + + for row in trail_rows: + hw = (row["highway_type"] or "").lower() + tt = (row["track_type"] or "").lower() if row["track_type"] else "" + cnt = row["cnt"] + km = (row["total_m"] or 0) / 1000.0 + + if hw == "track": + if tt in ("grade1", "grade2"): + lev12_count += cnt + lev12_km += km + else: + lev345_count += cnt + lev345_km += km + elif hw in ("path", "bridleway"): + path_count += cnt + path_km += km + + total_count = lev12_count + lev345_count + path_count + total_km = lev12_km + lev345_km + path_km + + # POI — подсчёт по типам + cur.execute(""" + SELECT poi_type, COUNT(*) as cnt + FROM poi + WHERE lon >= ? AND lon <= ? AND lat >= ? AND lat <= ? + GROUP BY poi_type + """, (lon - delta_lon, lon + delta_lon, lat - delta_lat, lat + delta_lat)) + poi_rows = cur.fetchall() + + poi_counts = {} + for row in poi_rows: + poi_counts[row["poi_type"]] = row["cnt"] + + conn.close() + + # POI types to report + poi_report = {} + for key in ["natural=water", "tourism=viewpoint", "historic=ruins", + "ford=yes", "natural=peak", "natural=cave_entrance"]: + poi_report[key] = poi_counts.get(key, 0) + + return { + "center": {"lon": lon, "lat": lat}, + "radius_km": radius_km, + "trails": { + "total_count": total_count, + "total_km": round(total_km, 1), + "lev12_count": lev12_count, + "lev12_km": round(lev12_km, 1), + "lev345_count": lev345_count, + "lev345_km": round(lev345_km, 1), + "path_count": path_count, + "path_km": round(path_km, 1), + }, + "poi": poi_report, + } + except Exception as e: + raise HTTPException(500, f"Ошибка БД: {e}") + + @app.post("/api/route") async def post_route(req: RouteRequest): """