"""Match an uploaded roadnet.json to a known city in the dataset by fingerprint.""" from __future__ import annotations import json from pathlib import Path def match_city_by_roadnet(roadnet_data: dict, generated_root: Path) -> str | None: """Return the city_id whose roadnet.json matches the uploaded data, or None.""" uploaded_fp = _fingerprint(roadnet_data) if not uploaded_fp: return None for city_dir in sorted(generated_root.glob("city_*")): roadnet_path = city_dir / "roadnet.json" if not roadnet_path.exists(): continue try: candidate = json.loads(roadnet_path.read_text()) if _fingerprint(candidate) == uploaded_fp: return city_dir.name except Exception: continue return None def list_all_cities(generated_root: Path) -> list[str]: return sorted( d.name for d in generated_root.glob("city_*") if d.is_dir() and (d / "roadnet.json").exists() ) def list_scenarios_for_city(city_id: str, generated_root: Path) -> list[str]: scenario_root = generated_root / city_id / "scenarios" if not scenario_root.exists(): return [] return sorted( d.name for d in scenario_root.iterdir() if d.is_dir() and (d / "config.json").exists() and (d / "flow.json").exists() ) def _fingerprint(roadnet: dict) -> frozenset[str]: """Fingerprint = set of non-virtual intersection IDs.""" return frozenset( item["id"] for item in roadnet.get("intersections", []) if not item.get("virtual", False) and item.get("id") )