"""구조물도 그림 — 기슭막이·골막이·떼흙막이·바닥막이·개거 (2026-09-14 · 표 = 그림). 표를 세운 그 전개(`build_table`)로 장을 만들고 그림 글자가 **표 근거와 같은 수**를 보이는지 대조. """ from __future__ import annotations import re import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[2] if str(ROOT) not in sys.path: sys.path.insert(0, str(ROOT)) from B08_Quantity.B08_Quantity_Engine_StructureFigure import attach_figures # noqa: E402 from B08_Quantity.B08_Quantity_Engine_StructureSheet import build_standard_sheets # noqa: E402 from B08_Quantity.B08_Quantity_Engine_UnitQuantity import build_table # noqa: E402 from B08_Quantity.B08_Quantity_Engine_UnitQuantity_Revetment import ( # noqa: E402 BED_SILL_TRENCH_NOTE, SOIL_GUARD_SOD, ) def _sheet(type_id: str, rubble=None, **options) -> dict: structure = { "structure_id": type_id, "type_id": type_id, "start_m": 0.0, "end_m": float(options.get("length_m") or 0.0), "options": options, } table = build_table([structure], None, rubble_base_thickness_m=rubble) payload = build_standard_sheets(table) attach_figures(payload, rubble) return payload["sheets"][0] def _texts(sheet: dict) -> list[str]: return [shape["text"] for shape in sheet["figure"] or [] if shape["kind"] == "text"] def _basis(sheet: dict, name: str) -> str: return next(row["basis"] for row in sheet["rows"] if row["name"] == name) def test_기슭막이_돌쌓기형은_돌쌓기_그림이고_기울기_두께가_표와_같다() -> None: sheet = _sheet("revetment", form="돌쌓기(메)", height_m=2.0, back_len_cm=35, length_m=10) texts = _texts(sheet) assert sheet["figure_reason"] is None slope = re.search(r"1:([\d.]+)", _basis(sheet, "돌쌓기")).group(1) # 메쌓기 표준경사 assert f"1 : {slope}" in texts top = re.search(r"상부 ([\d.]+)", _basis(sheet, "입적")).group(1) assert f"상부 {top} m" in texts concrete = _sheet("revetment", form="콘크리트", height_m=2.0, length_m=10) assert concrete["figure"] is None and "콘크리트 기슭막이" in concrete["figure_reason"] def test_골막이_그림_치수는_표_두께식과_같다() -> None: sheet = _sheet( "erosion_check", form="돌", height_m=1.5, top_length_m=4, bottom_length_m=2, back_len_cm=45 ) texts = _texts(sheet) thickness = re.search(r"평균두께 ([\d.]+)m", _basis(sheet, "입적")).group(1) label = next(t for t in texts if t.startswith("상부")) assert f"평균 {float(thickness):.2f}" in label trench = next(t for t in texts if t.startswith("바닥파기")) width = re.search(r"× ([\d.]+) \)", _basis(sheet, "터파기").replace(")", " )")).group(1) assert f"폭 {float(width):.2f}" in trench band = [s for s in sheet["figure"] if s["kind"] == "path" and s["dash"]][0] assert min(y for _x, y in band["points"]) < 0 # 바닥파기 띠가 밑변 바깥(아래)에 섬 def test_떼흙막이_붙박이_치수로_표_두_줄이_다시_나온다() -> None: d = SOIL_GUARD_SOD["dims"] sod = ( d["top_m"] * d["sod_m"] + d["bottom_m"] * d["sod_m"] + (d["top_m"] + d["bottom_m"]) / 2 * d["height_m"] + d["slant_m"] * d["sod_m"] * 2 ) trench = (d["slant_m"] * d["trench_width_m"] * d["trench_depth_m"] * 2) + ( d["bottom_m"] * d["trench_width_m"] * d["trench_depth_m"] ) rows = {row[0]: row[2] for row in SOIL_GUARD_SOD["rows"]} assert round(sod, 2) == rows["떼"] and round(trench, 2) == rows["터파기"] assert ( abs(((d["top_m"] - d["bottom_m"]) / 2) ** 2 + d["height_m"] ** 2 - d["slant_m"] ** 2) < 0.01 ) sheet = _sheet("soil_guard", form="떼", height_m=0.5, length_m=10) assert sheet["figure"] and sheet["unit_label"] == "개소당" other = _sheet("soil_guard", form="돌(찰)", height_m=0.5, length_m=10) assert other["figure"] is None and "떼흙막이" in other["figure_reason"] def test_바닥막이_그림_사유는_표와_같은_말이고_기초잡석은_산출_조건() -> None: sheet = _sheet("bed_sill", rubble=0.3, form="돌붙임(찰)", area_m2=12, height_m=0.3) texts = _texts(sheet) assert BED_SILL_TRENCH_NOTE in sheet["notes"] and BED_SILL_TRENCH_NOTE in texts assert "기초잡석 T=0.3 m — 산출 조건" in texts dry = _sheet("bed_sill", form="돌붙임(메)", area_m2=12, height_m=0.3) assert ( not any("기초잡석" in t for t in _texts(dry)) and BED_SILL_TRENCH_NOTE not in dry["notes"] ) def test_개거는_표가_서도_치수를_못_정한_까닭() -> None: sheet = _sheet("open_ditch", ditch_spec="콘크리트 개거 150×200", length_m=5) assert sheet["rows"] and sheet["figure"] is None and "확인 대기" in sheet["figure_reason"] l_type = _sheet("open_ditch", ditch_spec="L형수로 H=0.2", length_m=5) assert l_type["rows"] and "단면 그림이 없어" in l_type["figure_reason"]