From 45d55de93f4e486c23aa6c2808961209ca688b6c Mon Sep 17 00:00:00 2001 From: umsangdon Date: Wed, 9 Sep 2026 06:51:01 +0900 Subject: [PATCH] =?UTF-8?q?feat(B08):=20=EC=82=AC=ED=86=A0=20=EC=9A=B4?= =?UTF-8?q?=EB=B0=98=20=E2=80=94=20=EC=83=81=ED=83=9C(=EC=9E=90=EC=97=B0/?= =?UTF-8?q?=EB=8B=A4=EC=A7=90)=EB=A5=BC=20=EA=B0=92=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=82=B4=EA=B3=A0,=20=EB=B2=94=EC=9C=84=EB=A5=BC=20=EC=82=AC?= =?UTF-8?q?=EC=9C=A0=EC=97=90=20=EC=A0=81=EC=9D=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 유토곡선 잔량이 되돌린 값(natural_m3_by_ground)을 들고 오면 **그것을 씀**. 없으면 다짐값으로 서되 「품셈 운반 밑수는 자연상태」라는 사실을 근거에 적음 (조용히 쓰면 상태가 어긋난 물량이 단가에 물림). 우리가 환산하지 않음 — 계수는 저쪽에 있음 - 갈래를 못 붙인 몫은 상태도 못 되돌리므로 그 사실을 함께 적음 - `haul.spoil.volume_basis` 신설 — 받는 쪽이 단가와 맞는지 스스로 보게 - 범위를 줄 사유에 적음: 「사토장 정지」는 실무가 사토 운반 단가 안 조각(1/3)으로 넣으므로 수량 줄을 따로 안 세움 · 사토장 사면 보호공은 실무 집계표에 행이 없어 안 셈 (교본 6장 3절은 요구 — 뒤집으면 그때) Co-Authored-By: Claude Opus 5 (1M context) --- B08_Quantity/B08_Quantity_Router_Earthwork.py | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/B08_Quantity/B08_Quantity_Router_Earthwork.py b/B08_Quantity/B08_Quantity_Router_Earthwork.py index 0251e050..a1aff6f9 100644 --- a/B08_Quantity/B08_Quantity_Router_Earthwork.py +++ b/B08_Quantity/B08_Quantity_Router_Earthwork.py @@ -160,6 +160,10 @@ def _spoil_of(plan: dict[str, Any] | None, settings: dict[str, Any]) -> dict[str ⚠ `spoil_m3` 는 **공제·가산이 끝난 값**이다(채집석 공제는 빼고 구조물 잔토는 더한 뒤). 여기서 또 만지면 두 번 셈이 된다. ⚠ 자연방토(`natural_spoil_m3`)는 실어 내지 않는 몫이라 **뺀다**. + ⚠⚠ **상태가 갈린다.** 유토곡선 잔량은 **다짐상태**이고 품셈 운반(10-11·10-12)의 밑수는 + **자연상태**다(식이 `f = 1/L` 을 스스로 곱한다). 잔량이 되돌린 값 + (`natural_m3_by_ground`)을 들고 오면 **그것을 쓰고**, 없으면 다짐값으로 서되 그 사실을 + 근거에 적는다 — 조용히 쓰면 상태가 어긋난 물량이 단가에 물린다(2026-09-09 두 창 확인). """ haul_plan = (plan or {}).get("haul_plan") if isinstance(plan, dict) else None source = haul_plan if isinstance(haul_plan, dict) else (plan or {}) @@ -171,11 +175,17 @@ def _spoil_of(plan: dict[str, Any] | None, settings: dict[str, Any]) -> dict[str # 토사로 눅이면 덤프 단가가 임의로 정해진다. grounds: dict[str, float] = {} unknown = 0.0 + natural_basis = True for residual in source.get("residuals") or []: if str(residual.get("kind") or "") != "spoil": continue + # 되돌린 값이 오면 그것이 이긴다 — 우리가 다시 환산하지 않는다(계수가 저쪽에 있다). + returned = residual.get("natural_m3_by_ground") + source_map = returned if isinstance(returned, dict) else residual + if not isinstance(returned, dict): + natural_basis = False for key in ("ea_m3", "rr_m3", "br_m3"): - value = float(residual.get(key) or 0.0) + value = float(source_map.get(key) or source_map.get(key[:2]) or 0.0) if value > 0: grounds[key] = grounds.get(key, 0.0) + value unknown += float(residual.get("ground_unknown_m3") or 0.0) @@ -188,12 +198,20 @@ def _spoil_of(plan: dict[str, Any] | None, settings: dict[str, Any]) -> dict[str deducted = source.get("collected_stone_deducted_m3") if deducted: note_parts.append(f"채집석 {float(deducted):,.2f}㎥ 빠진 뒤") + if grounds and not natural_basis: + note_parts.append( + "⚠ 다짐상태 물량 — 품셈 운반 밑수는 자연상태라 유토곡선이 되돌린 값이 오면 그것을 씀" + ) + if unknown > 0: + note_parts.append(f"⚠ 갈래를 못 붙인 {unknown:,.2f}㎥ 는 상태도 못 되돌림") return { "volume_m3": round(volume, 3), "distance_m": settings.get("spoil_site_distance_m"), "note": " · ".join(note_parts), "by_ground_m3": {key: round(value, 3) for key, value in grounds.items()}, "ground_unknown_m3": round(unknown, 3), + # 어느 상태의 물량인가 — 받는 쪽이 단가와 맞는지 스스로 볼 수 있게 값으로 적는다. + "volume_basis": "natural" if natural_basis else "compacted", }