tmp/ 가 창끼리 안 건너가는 것이 확정돼(랩탑이 시간 두고 두 번 확인) 시험·예외가 저절로 건너가도록 git 안으로 옮김. 사용자 확정. - 내용은 하나도 안 고침 — 자리만 옮김. tmp/tests 는 남겨 둠. - 같은 이름이 이미 있던 64 개는 랩탑 것을 그대로 두고 건너뜀. - helper_b05_*.js 둘은 랩탑이 .cjs 로 이미 올린 것과 **줄바꿈만 다른 같은 내용**이라 복사본을 도로 뺌(시험이 .cjs 를 부름). - resources/tester/ 에서 전체 1176 통과 · 29 건너뜀 · 실패 0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
101 lines
4.3 KiB
Python
101 lines
4.3 KiB
Python
"""콘크리트를 자재 축에 세움 · 할증 이름 잇기 (2026-09-09 확정 3차 ⑥).
|
|
|
|
⚠⚠ **재료비가 통째로 빠져 있던 자리다.** 타설 줄(품셈 12-1)은 **품만** 주고 재료를 안 준다
|
|
(서브 일위대가도 재료 0원). 콘크리트를 자재 축에 안 보내면 레미콘 값이 어디에도 없다.
|
|
|
|
⚠ 겨누는 것 여섯
|
|
① 콘크리트 셋이 자재총괄에 선다
|
|
② 배합은 여전히 분해 안 함(㉢) — 「콘크리트 ㎥」에서 멈춘다
|
|
③ ⚠ 타설 줄과 **겹치지 않는다** — 그쪽은 품, 이쪽은 재료
|
|
④ 할증은 **레미콘일 때만** 붙는다 — 비빔은 시멘트·골재가 각각 할증됨
|
|
⑤ 이형철근 D13·D16 은 할증표 「이형철근」 줄로 이어진다(품셈 1-3-1, 규격 안 가림)
|
|
⑥ ⚠ 이름을 **바꾸지 않는다** — 이름만 잇는다(리핑암↔파쇄암과 같은 처방)
|
|
"""
|
|
|
|
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_MaterialSummary import ( # noqa: E402
|
|
build_table as build_material,
|
|
)
|
|
from B08_Quantity.B08_Quantity_Engine_MaterialSummary import surcharge_lookup_name # noqa: E402
|
|
from B08_Quantity.B08_Quantity_Engine_UnitQuantity import build_table # noqa: E402
|
|
|
|
|
|
def 단위표() -> dict:
|
|
return 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,
|
|
"foundation": "기초유",
|
|
},
|
|
}
|
|
]
|
|
)
|
|
|
|
|
|
def 자재(method: str | None = None) -> dict:
|
|
return {
|
|
row["name"]: row for row in build_material(단위표(), concrete_placing_method=method)["rows"]
|
|
}
|
|
|
|
|
|
def test_콘크리트가_자재총괄에_선다() -> None:
|
|
rows = 자재()
|
|
assert rows["채움콘크리트"]["net_amount"] > 0
|
|
assert rows["버림콘크리트"]["net_amount"] > 0
|
|
|
|
|
|
def test_배합은_분해하지_않는다() -> None:
|
|
"""⚠ 시멘트·모래·자갈로 쪼개면 B09 일위대가와 두 배가 된다(㉢)."""
|
|
rows = 자재()
|
|
assert not ({"시멘트", "모래", "자갈"} & set(rows))
|
|
|
|
|
|
def test_타설_줄과_겹치지_않는다() -> None:
|
|
"""타설은 품, 자재는 재료 — 둘 다 서되 같은 것을 두 번 세지 않는다."""
|
|
rows = build_handoff(unit_quantity_table=단위표())["work_items"]
|
|
placing = [row for row in rows if row["name"] == "콘크리트 타설"]
|
|
assert len(placing) == 1
|
|
assert all(row["name"] != "채움콘크리트" for row in rows)
|
|
|
|
|
|
def test_할증은_레미콘일_때만_붙는다() -> None:
|
|
"""⚠ 비빔은 시멘트·골재가 각각 할증되는 자리라 레미콘 할증을 붙이면 틀린다."""
|
|
레미콘 = 자재("ready_mixed")["채움콘크리트"]
|
|
비빔 = 자재("machine_mixed")["채움콘크리트"]
|
|
# ⚠ 「안 정함」은 비빔이 아니다 — 타설 줄이 기본값(레디믹스트)으로 도는데 할증만
|
|
# 미확보로 두면 같은 프로젝트에서 두 값이 어긋난다(실화면에서 걸린 자리).
|
|
안정함 = 자재(None)["채움콘크리트"]
|
|
assert 안정함["surcharge_pct"] is not None
|
|
assert "기본값" in 안정함["note"]
|
|
assert 레미콘["surcharge_pct"] is not None
|
|
assert 비빔["surcharge_pct"] is None
|
|
assert "레미콘이 아니라" in 비빔["note"] or "레미콘이 아니라" in str(비빔)
|
|
|
|
|
|
def test_이형철근은_규격을_안_가린다() -> None:
|
|
"""품셈 1-3-1 「이형철근」 줄 하나가 D13·D16 을 다 받는다."""
|
|
assert surcharge_lookup_name("이형철근 D13", None)[0] == "이형철근"
|
|
assert surcharge_lookup_name("이형철근 D16", None)[0] == "이형철근"
|
|
|
|
|
|
def test_이름을_바꾸지_않는다() -> None:
|
|
"""⚠ 줄 이름이 바뀌면 타설 줄·묶음 조각이 성분을 못 찾는다 — 찾을 때만 다른 이름을 쓴다."""
|
|
rows = 자재("ready_mixed")
|
|
assert "레미콘" not in rows
|
|
assert rows["채움콘크리트"]["name"] == "채움콘크리트"
|