Files
Aislo/resources/tester/test_b06_culvert_set.py
T

159 lines
6.6 KiB
Python

"""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
CHUTE_THICKNESS_CM,
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·전면 1:0.3 · 도수로/돌붙임 빈 두께 30 cm(90-2 사용자 확정)."""
assert MIN_PIPE_COVER_M == 0.5
assert CHUTE_THICKNESS_CM == 30.0
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 → 1.5 · 139-1) · 빈 형태 = 없음."""
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"] == 1.5
assert part["face_slope"] == REVET_FACE_SLOPE
# 옛 보호공(apron) 칸은 걷음 — 유출 보호는 도수로/돌붙임 띠(90-2)
assert "apron_length_m" not in part
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 spec["outlet"]["structure"] == "기슭막이"
assert spec["outlet"]["revet_height_m"] == 1.5 # 빈 높이 = 관경 기준(139-1)
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
def test_old_default_moves_for_large_pipe():
"""옛 기본 1.5 · 관경 > 1.0 = 관경 + 0.5 로 읽음(139-1) · 관경 ≤ 1.0 · 다른 값은 그대로."""
big = _culvert_set(
{
"pipe_diameter_mm": 1200,
"inlet_type": "집수정",
"inlet_basin_height_m": 1.5,
"outlet_type": "기슭막이",
"outlet_revet_height_m": 1.5,
}
)
assert big["outlet"]["revet_height_m"] == 1.7
assert big["inlet"]["basin_height_m"] == 1.7
small = _culvert_set(
{"pipe_diameter_mm": 800, "outlet_type": "기슭막이", "outlet_revet_height_m": 1.5}
)
assert small["outlet"]["revet_height_m"] == 1.5
hand = _culvert_set(
{"pipe_diameter_mm": 1500, "outlet_type": "기슭막이", "outlet_revet_height_m": 1.6}
)
assert hand["outlet"]["revet_height_m"] == 1.6
def test_chute_thickness_cm_to_m():
"""도수로/돌붙임(90-2) — 구조를 고르면 `chute` · 두께 cm → m · 빈 두께 30 cm · 안 고르면 없음."""
assert "chute" not in _culvert_set({"chute_add_1_thickness": 40})
spec = _culvert_set({"chute_add_1_structure": "돌붙임", "chute_add_1_thickness": "45"})
assert spec["chute"] == {"structure": "돌붙임", "thickness_m": 0.45}
blank = _culvert_set({"chute_add_1_structure": "도수로", "chute_add_1_thickness": ""})
assert blank["chute"] == {"structure": "도수로", "thickness_m": 0.3}
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]