Files
Aislo/resources/tester/test_b08_dry_height_face_role.py

77 lines
3.2 KiB
Python

# -*- coding: utf-8 -*-
"""메쌓기 높이 사유(B2) · 성토/절토 칸(B3) — 2026-09-14 브레인 판정 ㉰·㉲.
㉰ 두 기준 공존 — 임도기술교본 7-3:27 「메쌓기 2.0m 이하」 ↔ 품셈 13-4-4 [주]⑪ 원문 L7192
「3m 이상이면 전부 또는 하부를 찰쌓기」. 막지 않고 사유(B08 줄) · 칸 경고(B05, `warn_above`).
㉲ `face_role` — 비우면 단면유형 + 설치 측 자동 판정(계산이지 기본값이 아님) · 고르면 그 값이 이김.
"""
from __future__ import annotations
import json
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_UnitQuantity import expand, stone_masonry # noqa: E402
from common_util.common_util_structure_face_role import structure_face_role_of # noqa: E402
REGISTRY = json.loads(
(ROOT / "B05_Profile" / "B05_Profile_Structure_Types.json").read_text(encoding="utf-8")
)
FIELDS = (ROOT / "B05_Profile" / "B05_Profile_UI_Structures_Fields.ts").read_text(encoding="utf-8")
def _options(type_id: str) -> dict[str, dict]:
item = next(t for t in REGISTRY["types"] if t["type_id"] == type_id)
return {o["key"]: o for o in item["options"]}
def _height_notes(height: float, wet: bool) -> list[str]:
_rows, notes = stone_masonry(height, 10.0, {"back_len_cm": 45}, wet)
return [n for n in notes if "메쌓기 높이" in n]
def test_메쌓기_높이_두_기준_사유() -> None:
assert _height_notes(2.0, False) == []
over_guide = _height_notes(2.5, False)
assert len(over_guide) == 1 and "7-3:27" in over_guide[0] and "L7192" in over_guide[0]
over_limit = _height_notes(3.0, False)
assert len(over_limit) == 1 and "3m 이상이면" in over_limit[0]
assert _height_notes(3.5, True) == [] # 찰쌓기는 이 사유 대상 아님
def test_등록부_메쌓기_높이_칸은_경고만() -> None:
height = _options("masonry_dry")["height_m"]
assert height["warn_above"] == 2.0 and "L7192" in height["warn_message"]
assert "is-outside-standard" in FIELDS and "warn_above" in FIELDS
def test_성토절토_칸이_이긴다() -> None:
assert structure_face_role_of("both_fill", {"face_role": "절토"}) == (
"절토",
"사용자 지정 절토면(성토/절토 칸)",
)
# 비우면 지금 판정 그대로
assert structure_face_role_of("both_fill", {})[0] == "성토"
for type_id in ("masonry_wet", "masonry_dry", "revetment"):
role = _options(type_id)["face_role"]
assert role["choices"] == ["성토", "절토"] and role["default"] is None, type_id
def test_전개가_칸_값으로_기울기를_고른다() -> None:
structure = {
"structure_id": "w",
"type_id": "masonry_wet",
"start_m": 0.0,
"end_m": 10.0,
"options": {"height_m": 2.5, "length_m": 10.0, "back_len_cm": 45, "face_role": "절토"},
}
result = expand(structure, None, None, "both_fill")
wall = next(c for c in result.components if c.name == "돌쌓기")
# 찰쌓기 · 절토 · 직고 ≤3m → 1:0.25 (성토였으면 1:0.30)
assert "절토" in wall.basis and "1:0.25" in wall.basis