- 기슭막이(돌쌓기형) — 돌쌓기 그림 그대로 · 기울기 판정 대상에 넣고 찰/메는 형태에서(표와 한 벌) - 골막이 — 정면 사다리꼴 · 방수로 관 · 바닥파기 띠 + 옆 단면 · 치수는 표와 같이 쓰는 erosion_check_section 한 벌로 뽑음(값 불변) - 떼흙막이 — 정본 평균 붙박이 치수(dims)로 · 그 치수로 표 두 줄(떼 1.39 · 바닥파기 0.17)이 다시 나오는지 시험 - 바닥막이 — 돌 켜 · 버림 · 기초잡석(산출 조건) · 터파기 · 표 사유에 새 한 줄 「터파기는 돌 두께만 — 버림·기초잡석은 판 깊이에 안 들어감」을 그림도 같이 씀 - 표가 안 선 장은 표 사유를 그대로 까닭으로 · 개거 둘은 원문끼리 치수가 달라서/단면 그림이 없어서 까닭 - 화면 확인: 검증 프로젝트 936be972 에 넷을 잠깐 놓았다 되돌림(구조물 5개 원본과 같음 · 단계 상태 그대로 · 내역 124,424,547 그대로) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016VBGFXB9AbJBwXP19z75Qq
112 lines
4.9 KiB
Python
112 lines
4.9 KiB
Python
"""구조물도 그림 — 기슭막이·골막이·떼흙막이·바닥막이·개거 (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"]
|