"""Pipeline: calcula matriz de tiempo/distancia y isócronas para centros de servicio.""" from __future__ import annotations import asyncio import sys import os _FUNCTIONS_DIR = os.path.join(os.path.dirname(__file__), "..") if _FUNCTIONS_DIR not in sys.path: sys.path.insert(0, _FUNCTIONS_DIR) from geo.valhalla_matrix_1_to_n import valhalla_matrix_1_to_n from geo.valhalla_isochrones_async import valhalla_isochrones_async async def compute_centers_reachability_pipeline( origins: list[tuple[float, float]], centers: list[tuple[float, float]], isochrone_minutes: int = 15, base_url: str = "http://localhost:8002", concurrency: int = 6, ) -> dict: """Calcula la accesibilidad de centros de servicio desde orígenes clientes. Compone valhalla_matrix_1_to_n para obtener tiempos/distancias de todos los pares (origin, center) y valhalla_isochrones_async para generar una isócrona por cada centro. Args: origins: Lista de (lat, lon) de los clientes o puntos de origen. centers: Lista de (lat, lon) de los centros de servicio. isochrone_minutes: Minutos de isócrona a calcular para cada centro. base_url: URL base del servidor Valhalla. concurrency: Número máximo de requests async simultáneos para isócronas. Returns: Dict con claves: "matrix" (list[dict]): Un dict por par (origin_i, center_j) con {i, j, meters, seconds, error}. Orden: todos los centros para origin[0], luego origin[1], etc. "isochrones" (list[dict|None]): Una isócrona GeoJSON por cada center, en el mismo orden. None si Valhalla falló para ese centro. """ n_origins = len(origins) n_centers = len(centers) # Build all pairs: (origin_idx, center_idx) pairs = [(i, j) for i in range(n_origins) for j in range(n_centers)] # 1. Matrix: origins as sources, centers as destinations raw_matrix = valhalla_matrix_1_to_n( origins=origins, destinations=centers, pairs=pairs, base_url=base_url, concurrency=concurrency, ) matrix = [ { "i": pairs[k][0], "j": pairs[k][1], "meters": raw_matrix[k]["meters"], "seconds": raw_matrix[k]["seconds"], "error": raw_matrix[k]["error"], } for k in range(len(pairs)) ] # 2. Isochrones: one per center iso_requests = [ {"lat": lat, "lon": lon, "minutes": isochrone_minutes, "id": str(idx)} for idx, (lat, lon) in enumerate(centers) ] isochrones = await valhalla_isochrones_async( requests=iso_requests, base_url=base_url, concurrency=concurrency, ) return {"matrix": matrix, "isochrones": list(isochrones)}