Spaces:
Sleeping
Sleeping
| """ | |
| Refresh the shipped OSRM road-distance matrix for Jatim kabupaten. | |
| Usage: | |
| python tools/fetch_osrm_distance.py | |
| Output: | |
| sample_data/road_distance_jatim.csv | |
| Calls the public OSRM demo endpoint (router.project-osrm.org) once with a | |
| single /table batch — N coordinates produce an N×N matrix. The endpoint is | |
| rate-limited and labeled "for evaluation only"; a single batch of <100 | |
| coordinates is well within tolerance. For higher cadence, self-host OSRM | |
| via Docker with the Indonesia OSM extract. | |
| The matrix is precomputed and committed; engine runtime does NOT call this | |
| endpoint. Re-run only when: | |
| - sample_data/kabupaten_jatim.csv adds/removes/relocates a kabupaten | |
| - You want to refresh against newer OSM road graph (post-toll opening, etc.) | |
| Source: OpenStreetMap (ODbL license) via Project OSRM. | |
| """ | |
| from __future__ import annotations | |
| import csv | |
| import json | |
| import sys | |
| import time | |
| import urllib.parse | |
| import urllib.request | |
| from pathlib import Path | |
| ROOT = Path(__file__).resolve().parents[1] | |
| sys.path.insert(0, str(ROOT)) | |
| KAB_CSV = ROOT / "sample_data" / "kabupaten_jatim.csv" | |
| OUT_CSV = ROOT / "sample_data" / "road_distance_jatim.csv" | |
| def load_kabupaten(): | |
| rows = [] | |
| with open(KAB_CSV, newline="", encoding="utf-8") as f: | |
| r = csv.DictReader(f) | |
| for row in r: | |
| rows.append({ | |
| "id": row["kab_id"], | |
| "nama": row["nama"], | |
| "lat": float(row["latitude"]), | |
| "lon": float(row["longitude"]), | |
| }) | |
| return rows | |
| def fetch_table(kabs, profile: str = "driving"): | |
| # OSRM expects lon,lat (NOT lat,lon) | |
| coord_str = ";".join(f"{k['lon']},{k['lat']}" for k in kabs) | |
| url = ( | |
| f"http://router.project-osrm.org/table/v1/{profile}/" | |
| f"{urllib.parse.quote(coord_str, safe=',;')}" | |
| f"?annotations=distance,duration" | |
| ) | |
| print(f"[osrm] requesting {len(kabs)} x {len(kabs)} table ({len(url)} char URL)") | |
| t = time.time() | |
| with urllib.request.urlopen(url, timeout=120) as resp: | |
| body = resp.read().decode("utf-8") | |
| elapsed = time.time() - t | |
| print(f"[osrm] response {len(body)} bytes in {elapsed:.1f}s") | |
| data = json.loads(body) | |
| if data.get("code") != "Ok": | |
| print("[osrm] non-Ok response:", data) | |
| sys.exit(1) | |
| return data | |
| def main(): | |
| kabs = load_kabupaten() | |
| print(f"[osrm] loaded {len(kabs)} kabupaten") | |
| data = fetch_table(kabs) | |
| distances = data["distances"] # meters | |
| durations = data["durations"] # seconds | |
| n = len(kabs) | |
| assert len(distances) == n and len(durations) == n | |
| n_missing = 0 | |
| with open(OUT_CSV, "w", newline="", encoding="utf-8") as f: | |
| w = csv.writer(f) | |
| w.writerow(["from_id", "from_nama", "to_id", "to_nama", "road_km", "duration_hr"]) | |
| for i in range(n): | |
| for j in range(n): | |
| dist_m = distances[i][j] | |
| dur_s = durations[i][j] | |
| if dist_m is None or dur_s is None: | |
| n_missing += 1 | |
| continue | |
| w.writerow([ | |
| kabs[i]["id"], kabs[i]["nama"], | |
| kabs[j]["id"], kabs[j]["nama"], | |
| f"{dist_m / 1000:.3f}", | |
| f"{dur_s / 3600:.4f}", | |
| ]) | |
| print(f"[osrm] wrote {n*n - n_missing} pairs -> {OUT_CSV.relative_to(ROOT)}") | |
| if n_missing: | |
| print(f"[osrm] WARNING: {n_missing} pairs returned None (no route found)") | |
| if __name__ == "__main__": | |
| main() | |