"""덤프 운반(산림품셈 10-12 「2. 운반」) — 거리별 호표 · 원문 어긋남은 고른 값·버린 값을 사유에. 2026-09-14 축 C 1장 (브레인 판정 ①②④⑤): ① n 의 Qt = 계산값 T/γt×L (원문 표기 10 버림) ② 발파암 E 0.9 ④ Es = 운반 줄 값 ⑤ 운반거리마다 갈래 · 거리 없으면 0 원 아니라 「운반거리 미입력」 손셈(토사 164.23 m): Qt 10.2632 · n 16.2907 · t1 6.3885 · t2 3.6131 · ㎝t 12.5016 · f 0.77 → Q 34.135 → 34.14(사사오입) """ from __future__ import annotations import sys from decimal import Decimal from pathlib import Path ROOT = Path(__file__).resolve().parents[2] sys.path.insert(0, str(ROOT)) from B09_Estimation.B09_Estimation_MachineProductivity_Dump import ( # noqa: E402 DUMP_MATERIALS, DumpHaul, dump_child_for, dump_distance_from_code, dump_haul_distances, dump_title_code, ) from B09_Estimation.B09_Estimation_UnitPrice import cached_build # noqa: E402 DISTANCE = Decimal("164.23") def test_토사_운반_식_손셈() -> None: haul = DumpHaul(DUMP_MATERIALS["FP-10-12-01"], DISTANCE) assert round(haul.truck_load_m3, 4) == Decimal("10.2632") assert round(haul.loader_cycles, 4) == Decimal("16.2907") assert round(haul.cycle_minutes, 4) == Decimal("12.5016") assert (haul.volume_factor, haul.hourly_output) == (Decimal("0.77"), Decimal("34.14")) def test_암절취는_계산값_Qt_와_운반줄_Es() -> None: haul = DumpHaul(DUMP_MATERIALS["FP-10-12-02"], DISTANCE) assert round(haul.truck_load_m3, 4) == Decimal("8.4375") # 원문 표기 10 이 아님 assert haul.hourly_output == Decimal("12.49") assert any("원문 표기" in note for note in DUMP_MATERIALS["FP-10-12-02"].notes) assert DUMP_MATERIALS["FP-10-12-03"].truck_efficiency == Decimal("0.9") assert any("E 원문 누락" in note for note in DUMP_MATERIALS["FP-10-12-03"].notes) def test_거리마다_호표가_서고_코드에서_거리를_되읽는다() -> None: build = cached_build(dump_haul_m=(str(DISTANCE),)) code = dump_title_code("FP-10-12-01", DISTANCE) assert code == "B-FP-10-12-01#L164.23m" money = build.book.resolve(code) assert money.total > 0 assert dump_distance_from_code(code) == ("164.23",) assert code not in cached_build().book.titles # 거리 없는 조립엔 안 섬 def test_인계_거리와_갈래_잇기() -> None: payload = { "work_items": [ { "work_item_code": "FP-10-12", "haul_equipment": "dump_truck", "haul_distance_m": 164.23, }, {"work_item_code": "FP-10-12", "haul_equipment": "dump_truck", "haul_distance_m": None}, {"work_item_code": "FP-10-11", "haul_equipment": "dozer", "haul_distance_m": 32.09}, ] } assert dump_haul_distances(payload) == ("164.23",) assert dump_child_for("리핑암", "2026-01-01") == "FP-10-12-02" # 범위 별칭 리핑암 → 암절취 assert dump_child_for("토사", "2026-01-01") == "FP-10-12-01" assert dump_child_for("모르는암", "2026-01-01") is None def test_적재는_거리_무관_한_장이고_E0_는_0_60() -> None: from B09_Estimation.B09_Estimation_MachineProductivity_Dump import ( loading_output, loading_title_code, ) # 토사 3600×0.7×0.9×0.77×0.60/22 = 47.628 → 47.63 # 암절취 3600×0.7×0.55×0.74×0.35/22 = 16.317 → 16.32 assert loading_output("FP-10-12-01") == Decimal("47.63") assert loading_output("FP-10-12-02") == Decimal("16.32") build = cached_build() # 거리 없어도 섬 code = loading_title_code("FP-10-12-01") assert build.book.resolve(code).total > 0 basis = build.book.details[f"D-{code[2:]}"][0].note assert "0.75 버림" in basis def test_내역_줄_거리_없으면_운반거리_미입력() -> None: from B09_Estimation.B09_Estimation_BillOfQuantities import build_bill def payload(distance): return { "work_items": [ { "work_item_code": "FP-10-12", "name": "dump_truck 운반", "spec": "토사", "unit": "㎥", "quantity": 40.0, "haul_equipment": "dump_truck", "haul_distance_m": distance, "variant_axis": "ground_class", "variant_value": "토사", "in_bill": True, "origin": "haul", } ], "materials": [], } blank = build_bill(payload(None), build=cached_build()) assert any("운반거리 미입력" in m["reason"] for m in blank.missing) priced = build_bill(payload(164.23), build=cached_build(dump_haul_m=("164.23",))) row = next(r for r in priced.rows if r.name == "dump_truck 운반") assert row.price_code == "B-FP-10-12-01#L164.23m" and row.amount_krw > 0 loading = payload(None) loading["work_items"][0].update(name="덤프 적재", haul_equipment="dump_loading") loaded = build_bill(loading, build=cached_build()) row = next(r for r in loaded.rows if r.name == "덤프 적재") assert row.price_code == "B-FP-10-12-01#적재" and row.amount_krw > 0