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>
121 lines
4.5 KiB
Python
121 lines
4.5 KiB
Python
"""거푸집 사용횟수 검사 — 품셈 1-7-1 · 2026-09-07 ⑩.
|
||
|
||
⚠ 사용횟수는 **관측값이 아니라 법**이다 — 품셈 1-7-1 이 구조물 종류별로 정해 둔다.
|
||
⚠⚠ **횟수별 재료 환산은 여기서 하지 않는다.** 품셈 12-4 의 비율(%)은 일위대가 재료비에
|
||
걸리는 값이라, B08 이 곱해 넘기면 B09 가 또 곱해 두 번 준다.
|
||
"""
|
||
|
||
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_Formwork import ( # noqa: E402
|
||
FORMWORK_NAMES,
|
||
NOTE_REUSE_MISSING,
|
||
FormworkTable,
|
||
annotate,
|
||
load_formwork_table,
|
||
shoring_status,
|
||
)
|
||
from B08_Quantity.B08_Quantity_Engine_UnitQuantity import build_table # noqa: E402
|
||
|
||
|
||
def 옹벽() -> dict:
|
||
return {
|
||
"structure_id": "w1",
|
||
"type_id": "retaining_wall",
|
||
"start_m": 100.0,
|
||
"end_m": 110.0,
|
||
"options": {"form": "반중력식", "height_m": 2.0, "length_m": 10.0},
|
||
}
|
||
|
||
|
||
def test_원문에_이름이_있는_구조물은_횟수가_붙음() -> None:
|
||
"""품셈 1-7-1 의 3회 줄에 「옹벽」이 그대로 있다."""
|
||
table = build_table([옹벽()], {"retaining_wall": "옹벽"})
|
||
forms = [c for s in table["structures"] for c in s["components"] if c["name"] in FORMWORK_NAMES]
|
||
assert forms
|
||
assert all(c["reuse_count"] == 3 for c in forms)
|
||
assert all("1-7-1" in c["reuse_note"] for c in forms)
|
||
assert table["formwork_reuse_missing"] == []
|
||
|
||
|
||
def test_횟수별_비율을_여기서_곱하지_않을것() -> None:
|
||
"""⚠ 이 시험이 이 파일의 핵심 — 합판 3회 46.1 % 를 여기서 곱하면 B09 와 겹쳐 두 번 준다.
|
||
B08 이 내는 것은 **접촉 면적 그대로**이고 횟수는 옆에 적기만 한다."""
|
||
table = build_table([옹벽()], {"retaining_wall": "옹벽"})
|
||
euroform = next(
|
||
c for s in table["structures"] for c in s["components"] if c["name"] == "유로폼"
|
||
)
|
||
assert euroform["amount"] == 32.0 # 3.20 ㎡/m × 10m — 46.1 % 를 곱하지 않았다
|
||
# 비율표는 데이터에 있되 값에 안 걸린다.
|
||
assert load_formwork_table().reuse_ratio_pct["plywood"]["3"] == 46.1
|
||
|
||
|
||
def test_모르는_종류는_지어내지_않고_미확보() -> None:
|
||
structures = [
|
||
{
|
||
"type_id": "듣도보도못한구조물",
|
||
"name": "무엇",
|
||
"components": [{"name": "합판거푸집", "unit": "㎡", "amount": 5.0}],
|
||
}
|
||
]
|
||
notes, missing = annotate(structures)
|
||
assert missing == ["듣도보도못한구조물"]
|
||
assert structures[0]["components"][0]["reuse_count"] is None
|
||
assert structures[0]["components"][0]["reuse_note"] == NOTE_REUSE_MISSING
|
||
|
||
|
||
def test_거푸집이_없는_구조물은_건드리지_않음() -> None:
|
||
structures = [
|
||
{
|
||
"type_id": "retaining_wall",
|
||
"components": [{"name": "콘크리트", "unit": "㎥", "amount": 1.0}],
|
||
}
|
||
]
|
||
notes, missing = annotate(structures)
|
||
assert notes == [] and missing == []
|
||
assert "reuse_count" not in structures[0]["components"][0]
|
||
|
||
|
||
def test_이름은_정확히_일치로만_본다() -> None:
|
||
"""부분일치면 「거푸집씻기」(공사용수 항목)가 거푸집으로 잡힌다."""
|
||
structures = [
|
||
{
|
||
"type_id": "retaining_wall",
|
||
"components": [{"name": "거푸집씻기", "unit": "㎥", "amount": 1.0}],
|
||
}
|
||
]
|
||
annotate(structures)
|
||
assert "reuse_count" not in structures[0]["components"][0]
|
||
|
||
|
||
def test_파일이_없으면_전부_미확보() -> None:
|
||
structures = [
|
||
{
|
||
"type_id": "retaining_wall",
|
||
"components": [{"name": "유로폼", "unit": "㎡", "amount": 1.0}],
|
||
}
|
||
]
|
||
notes, missing = annotate(structures, FormworkTable())
|
||
assert missing == ["retaining_wall"]
|
||
|
||
|
||
# ── 동바리 ──────────────────────────────────────────────────────────
|
||
|
||
|
||
def test_동바리는_대상이_없으면_없다고_말할것() -> None:
|
||
"""0 으로 적으면 「대상이 없음」과 「값이 0」이 구별되지 않는다."""
|
||
status = shoring_status()
|
||
assert status["applicable"] is False
|
||
assert status["reason"]
|
||
assert set(status["pending_types"]) == {"box_culvert", "ford_bridge"}
|
||
|
||
|
||
def test_표에도_동바리_상태가_실림() -> None:
|
||
assert build_table([옹벽()])["shoring"]["applicable"] is False
|