- 한 벽을 두고 값이 셋(등록부·표 H2.5 · 구조물도 H2.5 · 횡단도 관경 기준)이던 결함 — 근거 있는 관경 기준으로 맞춤 - 관 벽 높이 안 적으면 관경 + 여유 0.5 를 0.1m 로 올리고 근입 0.5 더함(Ø800 1.8 · Ø1000 2.0 · Ø1500 2.5) - 파이썬(B06 엔진)·TS(세트 스펙·횡단 상수) 거울 시험 · 등록부 기본 2.5 걷고 empty_means - 최소값이라 미확정·금액 밖은 그대로 - B05 벽 칸(관 유입·유출 · 독립 기슭막이)은 비워 두고 회색 제안값 · [제안값 넣기] 누른 때만 값 — 저장 한 번에 미확정이 확정으로 바뀌던 길을 막음 - 전체 시험: 받은 덤프 적재 커밋 몫 2개만 빨강(보고함) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016VBGFXB9AbJBwXP19z75Qq
128 lines
5.2 KiB
Python
128 lines
5.2 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
|
||
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_fall_back_to_registry_defaults():
|
||
"""옵션이 빈 저장분은 레지스트리 기본값(Ø1000·L10)으로 채운다.
|
||
|
||
높이는 2026-09-14 브레인 판정으로 **관경 기준 최소 높이**(Ø1000 → 1.5 + 근입 0.5 = 2.0) —
|
||
횡단도가 그리는 그 높이. 옛 기본 2.5 는 횡단도가 안 쓰던 값이라 걷음.
|
||
"""
|
||
spec = _culvert_set(None)
|
||
assert spec["type"] == "pipe"
|
||
assert spec["diameter_m"] == 1.0
|
||
assert spec["min_cover_m"] == MIN_PIPE_COVER_M
|
||
for side in ("inlet", "outlet"):
|
||
part = spec[side]
|
||
assert part["structure"] == "기슭막이"
|
||
assert part["revet_height_m"] == 2.0
|
||
assert part["revet_length_m"] == 10
|
||
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
|
||
# 레지스트리 기본 형태: 유입 찰 / 유출 메.
|
||
assert spec["inlet"]["revet_form"] == "돌쌓기(찰)"
|
||
assert spec["outlet"]["revet_form"] == "돌쌓기(메)"
|
||
|
||
|
||
def test_basin_inlet_skips_revet_and_apron():
|
||
"""유입구 = 집수정이면 그쪽 기슭막이·보호공을 만들지 않는다(라벨만)."""
|
||
spec = _culvert_set({"inlet_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_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]
|