Files
Aislo/resources/tester/test_b06_culvert_set.py
T

132 lines
5.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""B06 배수관 세트(배관·기슭막이·보호공) 엔진 검증.
정본(`pipe_points.json`) + 레지스트리 기본값 조합이 계획서(3-0 근거 표)대로
나오는지, 배관 외 시설(BOX암거 등)이 이번 범위에서 빠지는지 확인한다.
"""
import json
import sys
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parents[2]
if str(PROJECT_ROOT) not in sys.path:
sys.path.insert(0, str(PROJECT_ROOT))
from B06_Section.B06_Section_Engine_Culvert import ( # noqa: E402
APRON_LENGTH_FACTOR,
APRON_THICKNESS_M,
MIN_PIPE_COVER_M,
REVET_FACE_SLOPE,
_culvert_set,
attach_culvert_sets,
pipe_points_file,
)
def test_cross_reference_constants_match_plan():
"""계획서 3-0 표 값 — 토피 0.5m·보호공 길이 2배·두께 0.45m(사용자 확정)·전면 1:0.3."""
assert MIN_PIPE_COVER_M == 0.5
assert APRON_LENGTH_FACTOR == 2.0
assert APRON_THICKNESS_M == 0.45
assert REVET_FACE_SLOPE == 0.3
# 배관은 수평도 가능 — 세트에 경사 강제값을 싣지 않는다(2026-08-20 사용자 확정).
assert "min_slope" not in _culvert_set(None)
def test_empty_options_have_no_members():
"""빈 고르기 칸 = 그 부재 없음(54-39) — 구조 · 형태 · 관종 · 기초 빈 값."""
spec = _culvert_set(None)
assert spec["type"] == "pipe"
assert spec["min_cover_m"] == MIN_PIPE_COVER_M
assert spec["pipe_kind"] is None
assert spec["foundation"] is None
assert spec["inlet"] == {"role": "inlet", "structure": ""}
assert spec["outlet"] == {"role": "outlet", "structure": ""}
def test_saved_values_drive_members():
"""고른 값만 부재 — 빈 높이 = 관경 기준 최소(Ø1000 → 2.0) · 빈 형태 = 없음."""
spec = _culvert_set({"inlet_type": "집수정", "inlet_structure": "L", "outlet_type": "기슭막이"})
assert spec["inlet"]["basin_form"] == "L"
assert spec["inlet"]["basin_height_m"] is None
part = spec["outlet"]
assert part["structure"] == "기슭막이"
assert part["revet_form"] is None
assert part["revet_height_m"] == 2.0
assert part["face_slope"] == REVET_FACE_SLOPE
# 보호공 = 낙차고(2.0) × 2 = 4.0m, 두께 0.45m(사용자 확정).
assert part["apron_length_m"] == 4.0
assert part["apron_thickness_m"] == 0.45
def test_basin_inlet_skips_revet_and_apron():
"""유입구 = 집수정이면 그쪽 기슭막이·보호공을 만들지 않는다(라벨만)."""
spec = _culvert_set({"inlet_type": "집수정", "outlet_type": "기슭막이"})
assert spec["inlet"]["structure"] == "집수정"
assert "revet_height_m" not in spec["inlet"]
assert "apron_length_m" not in spec["inlet"]
# 유출측은 그대로 세트를 갖춘다.
assert spec["outlet"]["structure"] == "기슭막이"
assert spec["outlet"]["apron_length_m"] == 4.0 # 빈 높이 = 관경 기준 최소 2.0 × 2
def test_string_diameter_and_custom_height():
"""관경 문자열 저장분("800")과 사용자 높이 변경이 그대로 반영된다."""
spec = _culvert_set(
{"pipe_diameter_mm": "800", "outlet_type": "기슭막이", "outlet_revet_height_m": 1.5}
)
assert spec["diameter_m"] == 0.8
assert spec["outlet"]["revet_height_m"] == 1.5
assert spec["outlet"]["apron_length_m"] == 3.0 # 1.5 × 2
def test_attach_only_pipe_facilities(tmp_path):
"""배관은 `culvert`, 세월교는 `ford`, BOX암거는 `box` 키로 얹는다.
배관 매칭은 chainage ±0.02m 그대로다. 세월교·BOX암거는 구체 폭만큼 이어져
기준 측점 전후 절반까지 붙는다(2026-08-25 사용자 확정) — 아래 100.0m은
어느 쪽 범위에도 들지 않는다.
"""
target = pipe_points_file(tmp_path)
target.parent.mkdir(parents=True)
target.write_text(
json.dumps(
{
"route_signature": "x",
"points": [
{
"chainage_m": 84.3,
"source": "spacing",
"options": {"pipe_diameter_mm": 1000},
},
{"chainage_m": 149.73, "source": "stream", "facility": "ford_bridge"},
{"chainage_m": 200.92, "source": "spacing", "facility": "box_culvert"},
],
},
ensure_ascii=False,
),
encoding="utf-8",
)
cross_sections = [
{"chainage_m": 84.3, "samples": []},
{"chainage_m": 149.73, "samples": []},
{"chainage_m": 200.92, "samples": []},
{"chainage_m": 100.0, "samples": []},
]
attached = attach_culvert_sets(tmp_path, cross_sections)
assert attached == 3
assert "culvert" in cross_sections[0]
assert cross_sections[0]["culvert"]["diameter_m"] == 1.0
# 세월교·BOX암거는 그림이 달라 키를 나눈다 — 배수관 소비처가 집어가면 안 된다.
assert cross_sections[1]["ford"]["type"] == "ford"
assert cross_sections[2]["box"]["type"] == "box"
assert all("culvert" not in section for section in cross_sections[1:])
assert all("ford" not in section for section in (cross_sections[0], *cross_sections[2:]))
def test_attach_without_file_is_noop(tmp_path):
"""정본 파일이 없으면 아무 것도 얹지 않고 0을 돌려준다."""
sections = [{"chainage_m": 10.0}]
assert attach_culvert_sets(tmp_path, sections) == 0
assert "culvert" not in sections[0]