feat(b08): 임목폐기물 뿌리 산정법 고르개 · 지침 π 3.14 · 분리발주 대상 아님 안내

- 환경친화적인 도로건설 지침 부록1 확인: 뿌리분 체적 V = 0.3927D³ × 1,300㎏/㎥ — 고르개로 넣음(기본은 분배비 15/85)
- 뿌리분 직경 D 는 지침 표기 「뿌리분의 직경(DBH, m)」이 모호해 흉고직경과 따로 받음
- 지상부 식을 지침 원문대로 π 3.14 로 셈 — 실정보고 예 130.40㎥ 와 바로 맞음
- 분리발주 칸 밑·사유에 「임목폐기물은 분리발주 대상 아님(환경부 회신)」

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BW6Jdsh18WPtYUR6THZJqn
This commit is contained in:
2026-09-14 01:09:23 +09:00
co-authored by Claude Opus 5
parent ae9578a6dc
commit 35ba45f572
9 changed files with 143 additions and 35 deletions
+18 -5
View File
@@ -7,7 +7,6 @@
from __future__ import annotations
import math
import sys
from pathlib import Path
@@ -28,8 +27,8 @@ FIELD = {"stems_per_1000m2": 134, "dbh_cm": 16, "height_m": 10.0, "unit_weight_k
def test_지상부는_실정보고_부피와_같다() -> None:
"""W1 = 1,000㎏/㎥ 로 두면 지상부 톤 = 지상부 부피(㎥) — 실정보고 130.40㎥."""
above, root = tree_waste_tons(7450.0, FIELD)
# 실정보고는 π 를 3.14 로 셈 — 같은 π 로 되돌리면 130.40 과 같다.
assert above * 3.14 / math.pi == pytest.approx(130.40, abs=0.01)
# 지침 부록1 식·실정보고 모두 π 를 3.14 로 적음 — 그대로 셈해 130.40 과 같다.
assert above == pytest.approx(130.40, abs=0.01)
assert root == pytest.approx(above * 15 / 85)
@@ -48,9 +47,9 @@ def test_단가가_없으면_금액이_안_서고_있으면_미확정() -> None:
assert priced["amount_krw"] == int(priced["amount"] * 60000)
def test_톤_경계를_알린다() -> None:
def test_톤_경계를_알리고_분리발주_대상_아님을_적는다() -> None:
big = tree_waste_rows(SLOPE, FIELD)[0] # 약 153톤
assert big["amount"] >= 100 and "100톤 이상" in big["reason"]
assert "분리발주 대상 아님" in big["reason"] and "환경부" in big["reason"]
small = tree_waste_rows({"tree_removal_fill": 500.0}, FIELD)[0] # 약 10톤
assert 5 <= small["amount"] < 100 and "5톤 이상" in small["reason"]
@@ -64,3 +63,17 @@ def test_경비라_내역에_안_서고_제외_사유가_간다() -> None:
row = handed["임목폐기물 처리"]
assert row["in_bill"] is False and row["blocked_kind"] is None
assert "경비" in row["in_bill_reason"]
def test_뿌리분_체적법은_D_세제곱_곱하기_1300() -> None:
"""지침 부록1 — V = 0.3927 D³ · 뿌리분 중량 = V × 1,300㎏/㎥ (본수만큼)."""
field = {**FIELD, "root_ball_diameter_m": 0.5}
above, root = tree_waste_tons(7450.0, field, "root_ball")
stems = 134 / 1000 * 7450
assert root == pytest.approx(0.3927 * 0.5**3 * 1300 * stems / 1000)
assert above == pytest.approx(tree_waste_tons(7450.0, FIELD)[0])
def test_체적법인데_뿌리분_직경이_비면_안_선다() -> None:
row = tree_waste_rows(SLOPE, FIELD, root_method="root_ball")[0]
assert row["amount"] is None and "뿌리분 직경" in row["reason"]