Files
Aislo/resources/tester/test_b08_blinding.py
T
eomsangdonandClaude Opus 5 1375d8c290 feat(b08): 구조물도 탭에 양식 식을 실음 — 산출 기초·식·갈 곳·안 섬
- 양식이 있는 종류(찰쌓기)는 장마다 양식으로 줄을 다시 세움(L=1 m당) — 식·설명·반올림·
  갈 곳·출처·안 섬 까닭을 줄에 실음. 양식 없는 종류는 지금 전개 그대로(고정형 모양)
- 화면 표: 산출 근거 밑에 식 한 줄 · 갈 곳 칸 · 안 선 줄은 「안 섬」과 까닭
- 전개 결함 둘 고침(브레인 판정): 「실무 관행」 계수가 돌종류를 지우던 것 ·
  기초잡석이 서는데 「두께가 없어 안 섬」 사유가 함께 뜨던 것
- 검증 프로젝트 찰쌓기 15줄 — 양식 m당×10 = 원단위 탭 합계 전부 일치

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016VBGFXB9AbJBwXP19z75Qq
2026-09-13 17:23:12 +09:00

126 lines
5.1 KiB
Python

"""버림 콘크리트 — 빠뜨리고 있던 줄 (2026-09-09 사용자 확정 ⑭).
⚠ 겨누는 것 다섯
① 기본은 **넣는다** — 정한 적 없는 프로젝트에서 줄이 사라지지 않아야 한다
② 「안 넣음」으로 두면 **빠진다**
③ 두께는 **0.10m**(KDS 44 90 00) — 임의 값이 아니다
④ 근거 문구에 **잠정임이 드러난다**(폭이 잡석다짐 폭이라야 하나 그 값이 아직 없다)
⑤ ⚠ 채움 콘크리트와 **섞이지 않는다** — 타설 줄은 버림 몫만 세운다
"""
from __future__ import annotations
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT))
from B08_Quantity.B08_Quantity_Engine_Handoff import build_handoff # noqa: E402
from B08_Quantity.B08_Quantity_Engine_UnitQuantity import ( # noqa: E402
BLINDING_THICKNESS_M,
boulder_masonry,
stone_masonry,
wants_blinding,
)
def 성분(**options: object) -> dict:
components, _ = stone_masonry(
2.5, 10.0, {"height_m": 2.5, "length_m": 10.0, "back_len_cm": 45, **options}, wet=True
)
return {c.name: c for c in components}
def test_기본은_넣는다() -> None:
"""⚠ 빈 칸을 「빼기」로 읽으면 저장해 둔 적 없는 프로젝트에서 줄이 통째로 사라진다."""
assert wants_blinding({}) is True
assert "버림콘크리트" in 성분()
def test_안_넣음으로_두면_빠진다() -> None:
for value in ("안 넣음", "제외", "false", "no"):
assert wants_blinding({"blinding_concrete": value}) is False, value
assert "버림콘크리트" not in 성분(blinding_concrete="안 넣음")
def test_두께는_원문값이다() -> None:
"""KDS 44 90 00 「구조물 시공이 원활하도록 **100 mm 두께**의 버림콘크리트를 타설」."""
assert BLINDING_THICKNESS_M == 0.10
got = 성분()["버림콘크리트"]
# 기초 폭(터파기 폭) × 연장 × 두께 — 폭이 근거 문구에 적혀 있으므로 그 값으로 검산한다.
assert got.unit == "㎥"
assert got.amount > 0
def test_폭은_하단_길이에서_온다() -> None:
"""⚠ 「폭은 잡석다짐 폭」(KCS 34 50 05)이고 그 폭이 확정 ⑪ 로 **하단 길이**가 됐다.
옛 잠정(터파기 폭 = 평균두께 + 0.2)을 지운 자리다 — 근거 문구에 어디서 온 폭인지 적힌다.
"""
got = 성분()["버림콘크리트"]
하부두께 = 0.45 + 0.30 + 0.30 * (2.5 - 1.0) # 1.20
assert abs(got.amount - 하부두께 * 10.0 * BLINDING_THICKNESS_M) < 1e-9
assert "KDS" in got.basis and "하단 길이" in got.basis
assert "잠정" not in got.basis
def test_기초잡석은_계상하고_안_선다는_사유를_안_남긴다() -> None:
"""ⓘ 2026-09-13 바뀜 — 옛 시험은 「두께가 원문에 없어 안 선다」를 굳혔음.
확정 3차 ② 로 두께 0.2 가 서고 `build_table` 이 기초잡석 줄을 세우는데, 전개는 여전히
「안 섬」 사유를 붙여 **구조물도에 줄과 사유가 함께 떠 서로 어긋났음**(화면 실측).
브레인 판정(PLAN 10장 「기초잡석 계상함」)대로 사유를 걷고 줄이 서는지 봄.
"""
from B08_Quantity.B08_Quantity_Engine_UnitQuantity import build_table
_, notes = stone_masonry(
2.5, 10.0, {"height_m": 2.5, "length_m": 10.0, "back_len_cm": 45}, wet=True
)
assert not any("기초잡석(12-25)" in n and "안 섬" in n for n in notes)
table = build_table(
[
{
"structure_id": "s1",
"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},
}
]
)
names = [c["name"] for c in table["structures"][0]["components"]]
assert "기초잡석" in names
def test_큰돌쌓기에도_선다() -> None:
components, _ = boulder_masonry(
2.5, 10.0, {"height_m": 2.5, "length_m": 10.0, "stone_cm": "60~80"}
)
assert any(c.name == "버림콘크리트" for c in components)
def test_타설_줄은_버림_몫만_센다() -> None:
"""⚠ 채움 콘크리트가 섞이면 이중계상 — 그 공종 품에 이미 들어 있을 수 있다."""
item = 성분()
structure = {
"structure_id": "s1",
"type_id": "masonry_wet",
"name": "돌쌓기(찰)",
"length_m": 10.0,
"height_m": 2.5,
"start_m": 0.0,
"end_m": 10.0,
"options": {"height_m": 2.5, "length_m": 10.0, "back_len_cm": 45},
"notes": [],
"components": [
{"name": c.name, "unit": c.unit, "amount": c.amount, "basis": c.basis}
for c in item.values()
],
}
rows = build_handoff(unit_quantity_table={"structures": [structure]})["work_items"]
placing = [row for row in rows if row["name"] == "콘크리트 타설"]
assert len(placing) == 1
assert abs(placing[0]["quantity"] - item["버림콘크리트"].amount) < 1e-6
assert abs(placing[0]["quantity"] - item["채움콘크리트"].amount) > 1e-6