From d9109dda1d2b990a7982fceaac2a40c278048034 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=8F=84=EC=96=B8?= Date: Tue, 27 Oct 2026 17:51:39 +0900 Subject: [PATCH] fix: apply numeric tolerance to nested coordinates (#3) --- tools/validate_network.py | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/tools/validate_network.py b/tools/validate_network.py index 5601f0a..d14450a 100644 --- a/tools/validate_network.py +++ b/tools/validate_network.py @@ -12,6 +12,23 @@ SECTIONS = {'JUNCTIONS':'junction', 'OUTFALLS':'outfall', 'STORAGE':'storage', 'CONDUITS':'conduit', 'PUMPS':'pump', 'WEIRS':'weir'} +def values_match(actual, expected, tolerance): + """Apply the same numeric contract at every nesting level.""" + if isinstance(expected, bool): + return isinstance(actual, bool) and actual == expected + if isinstance(expected, (float, int)): + return (isinstance(actual, (float, int)) and not isinstance(actual, bool) + and math.isfinite(actual) and math.isfinite(expected) + and abs(actual - expected) <= tolerance) + if isinstance(expected, list): + return (isinstance(actual, list) and len(actual) == len(expected) + and all(values_match(a, e, tolerance) for a, e in zip(actual, expected))) + if isinstance(expected, dict): + return (isinstance(actual, dict) and actual.keys() == expected.keys() + and all(values_match(actual[k], v, tolerance) for k, v in expected.items())) + return type(actual) is type(expected) and actual == expected + + def parse_inp(path): raw = Path(path).read_bytes() for encoding in ('utf-8-sig', 'cp949'): @@ -44,12 +61,7 @@ def validate(inp, network, tolerance=1e-6): def compare(entity, field, actual, expected): nonlocal checks checks += 1 - if isinstance(expected, (float, int)) and not isinstance(expected, bool): - ok = (isinstance(actual, (float, int)) and not isinstance(actual, bool) - and math.isfinite(actual) and abs(actual - expected) <= tolerance) - else: - ok = actual == expected - if not ok: + if not values_match(actual, expected, tolerance): errors.append({'id': entity, 'field': field, 'actual': actual, 'expected': expected}) def number(tokens, index, default=None):