"""Build src/static/flood-marks-2024.json from CMU Water Center's flood marks. After the October 2024 flood (P.1 peaked at 5.30 m on 5 October), CMU Water Center marked the high-water line at about 5,000 places in Chiang Mai and Lamphun (CMFlood, "Flood marks 2024"): the depth above the road surface, in cm. This keeps position and depth only, in a compact array form: uv run python scripts/build_flood_marks.py # fetch from CMU uv run python scripts/build_flood_marks.py --geojson F # or a saved copy """ import argparse import json import urllib.request from pathlib import Path REPO = Path(__file__).resolve().parents[1] OUT = REPO / "src" / "static" / "flood-marks-2024.json" URL = "https://watercenter.cmu.ac.th/data/New_floodMark_2025_fixed_like_pole.geojson" SOURCE = ( "CMU Water Center (ศูนย์วิชาการสนับสนุนการบริหารจัดการน้ำ มหาวิทยาลัยเชียงใหม่), " "flood marks of October 2024, " "https://watercenter.cmu.ac.th/chiangmai/cmflood/warning/floodmark" ) def load(path: Path | None) -> dict: if path: return json.loads(path.read_text(encoding="utf-8")) req = urllib.request.Request(URL, headers={"User-Agent": "Mozilla/5.0"}) with urllib.request.urlopen(req, timeout=120) as r: return json.loads(r.read().decode("utf-8")) def main() -> None: ap = argparse.ArgumentParser(description=__doc__.splitlines()[0]) ap.add_argument("--geojson", type=Path, help="read CMU's GeoJSON from here") args = ap.parse_args() marks, skipped = [], 0 for f in load(args.geojson)["features"]: p = f.get("properties") or {} lon, lat, depth = p.get("longitude"), p.get("latitude"), p.get("water_level") if lon is None or lat is None or depth is None: skipped += 1 continue # 18-19.5 N, 98.5-99.5 E: a swapped or empty coordinate is skipped if not (18.0 < lat < 19.5 and 98.5 < lon < 99.5) or depth <= 0: skipped += 1 continue marks.append([round(lon, 5), round(lat, 5), round(depth)]) marks.sort(key=lambda m: (m[1], m[0])) doc = { "source": SOURCE, "p1_level": 5.30, "date": "2024-10-05", "fields": ["lon", "lat", "depth_cm_above_road"], "marks": marks, } OUT.write_text( json.dumps(doc, ensure_ascii=False, separators=(",", ":")) + "\n", encoding="utf-8", ) print( f"wrote {OUT.relative_to(REPO)}: {len(marks)} marks, {skipped} skipped, " f"{OUT.stat().st_size / 1024:.0f} KB" ) if __name__ == "__main__": main()