#!/usr/bin/env python3 """Patch traffic lane connection probabilities toward highway routing.""" from __future__ import annotations import argparse import json from pathlib import Path from typing import Any FLAGS = { "Road": 16, "Pavement": 8, "TrafficDisabled": 128, "CrossWalk": 256, "GPSOnly": 512, "Blockade": 2048, "Highway": 16384, } def load_json(path: Path) -> Any: return json.loads(path.read_text(encoding="utf-8")) def flag_value(flags: Any) -> int: return int(flags or 0) def has(flags: int, name: str) -> bool: return bool(flags & FLAGS[name]) def category(flags: int) -> str: if has(flags, "Highway"): return "highway" if has(flags, "GPSOnly"): return "gpsonly" if has(flags, "Road"): return "road" if has(flags, "Pavement"): return "pavement" return "other" def write_json(path: Path, data: Any) -> None: path.parent.mkdir(parents=True, exist_ok=True) path.write_text(json.dumps(data, indent=2) + "\n", encoding="utf-8") def main() -> int: parser = argparse.ArgumentParser() parser.add_argument("traffic_persistent_json", type=Path) parser.add_argument("lane_connections_json", type=Path) parser.add_argument("out_json", type=Path) parser.add_argument("--high", type=int, default=255) parser.add_argument("--low", type=int, default=1) args = parser.parse_args() traffic = load_json(args.traffic_persistent_json) lanes = traffic["Data"]["RootChunk"]["data"]["lanes"] lane_categories = [category(flag_value(lane.get("flags", 0))) for lane in lanes] connections = load_json(args.lane_connections_json) rows = connections["Data"]["RootChunk"]["data"] changed = 0 high_set = 0 low_set = 0 touched_rows = 0 for row in rows: source_index = row["index"] source_category = lane_categories[source_index] outlanes = row["value"]["outlanes"] if not outlanes: continue target_categories = [ lane_categories[out["laneIndex"]] for out in outlanes if 0 <= out["laneIndex"] < len(lane_categories) ] has_highway_target = "highway" in target_categories has_non_highway_target = any(cat != "highway" for cat in target_categories) row_changed = False for out in outlanes: target_category = lane_categories[out["laneIndex"]] old = out["exitProbabilityCompressed"] new = old if target_category == "highway" and source_category in {"road", "gpsonly", "highway"}: new = args.high elif ( source_category == "highway" and has_highway_target and target_category != "highway" ): new = args.low elif ( source_category in {"road", "gpsonly"} and has_highway_target and has_non_highway_target and target_category != "highway" ): new = args.low if new != old: out["exitProbabilityCompressed"] = new changed += 1 row_changed = True if new == args.high: high_set += 1 elif new == args.low: low_set += 1 if row_changed: touched_rows += 1 write_json(args.out_json, connections) print(f"rows seen: {len(rows)}") print(f"rows touched: {touched_rows}") print(f"edges changed: {changed}") print(f"edges set high: {high_set}") print(f"edges set low: {low_set}") return 0 if __name__ == "__main__": raise SystemExit(main())