MEGAINFRA-WEBAPP/scripts/site-model/test_cedar_gate_services.py
DEls 5141f7783a feat(site-map): Cedar Gate stormwater and sewer pipes and manholes from the long sections
Extract 23 stormwater structures / 22 pipes and 18 sewer manholes / 17 pipes with sizes, inverts, ground levels and positions from the C3277 long-section tables (superseded sewer copies dropped by matching the issued PDFs). New model folder 2026-10-21. Map 3 draws them as round pipes and manholes, adds status popups for pipes and manholes, and reuses Map 2's services panel; water stays plan routes.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-21 05:04:42 +02:00

51 lines
2.3 KiB
Python

import json
import math
import unittest
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2] / "reports/site-models/cedar-gate/2026-10-21"
def seg_dist(p, a, b):
dx, dy = b[0] - a[0], b[1] - a[1]
l2 = dx * dx + dy * dy
t = 0 if not l2 else max(0, min(1, ((p[0] - a[0]) * dx + (p[1] - a[1]) * dy) / l2))
return math.hypot(p[0] - a[0] - t * dx, p[1] - a[1] - t * dy)
class CedarGateServices(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.s = json.loads((ROOT / "services.json").read_text())
cls.report = json.loads((ROOT / "services-extraction.json").read_text())
def test_pipes_join_known_structures_and_fall_downhill(self):
sw = {x["name"] for x in self.s["stormwater"]["structures"]}
for p in self.s["stormwater"]["pipes"]:
self.assertIn(p["from"], sw); self.assertIn(p["to"], sw)
self.assertGreaterEqual(p["ilFrom"], p["ilTo"]); self.assertGreater(p["length"], 0); self.assertGreater(p["dia"], 0)
sr = {x["id"] for x in self.s["sewer"]["manholes"]}
for p in self.s["sewer"]["pipes"]:
self.assertIn(p["from"], sr); self.assertIn(p["to"], sr)
self.assertGreaterEqual(p["ilFrom"], p["ilTo"])
def test_sizes_match_the_plan_labels(self):
dia = sorted(p["dia"] for p in self.s["stormwater"]["pipes"] if p["run"] == 1)
self.assertEqual(dia, [675, 750, 750, 825, 1350, 1350, 1500, 1500, 1500]) # the eight SW-M1 plan labels plus the short outlet pipe
self.assertTrue(all(p["dia"] in (160, 250) for p in self.s["sewer"]["pipes"]))
def test_structures_sit_on_their_plan_routes(self):
routes = [r for r in self.s["planRoutes"] if r["service"] == "stormwater"]
for q in self.s["stormwater"]["structures"]:
d = min(seg_dist((q["e"], q["n"]), r["pts"][i], r["pts"][i + 1]) for r in routes for i in range(len(r["pts"]) - 1))
self.assertLess(d, 3.5, q["name"])
def test_superseded_sewer_copies_are_dropped(self):
titles = [r["title"] for r in self.report["runs"] if r["kind"] == "sewer"]
self.assertEqual(sorted(titles), ["SE-2", "SE-3", "SE-M1"])
self.assertTrue(all(r["verifiedOnIssuedSheets"] for r in self.report["runs"] if r["kind"] == "sewer"))
self.assertEqual(len(self.report["discarded"]), 3)
if __name__ == "__main__":
unittest.main()