fix(B08): 토적표가 설계 측구 가름값을 그대로 읽도록 하고 표기 자리수를 품셈에 맞춤

- 측구 토사·암을 절토 면적비로 다시 안분하지 않고 B06 이 낸
  ditch_soil_area_m2·ditch_rock_area_m2 를 그대로 씀. 근거 ditch_split_basis 도 줄에 실음.
- 설계값이 없는 저장분만 옛 안분으로 떨어지고 사유를 줄 주기에 남김.
- 표기 자리수 — 단면적 ㎡ 1자리 · 체적 계열 ㎥ 2자리 · 합계 정수 (계산은 전정밀 그대로).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GrXDD23Dvt2sR7q3X6oekp
This commit is contained in:
2026-09-12 13:14:13 +09:00
co-authored by Claude Opus 5
parent d6e45bb431
commit 1bfe1aa6e7
4 changed files with 153 additions and 29 deletions
+66 -5
View File
@@ -115,8 +115,55 @@ def test_암은_토사와_다른_계수() -> None:
)
def test_측구_안분은_절토_토사암_비율() -> None:
"""측구 지반이 따로 안 오므로 그 측점 절토 비율로 가른다(엔진 주석의 TODO 자리)."""
def test_설계가_가른_값을_그대로_읽음() -> None:
"""측구 가름의 주인은 횡단 설계다 — 토적표가 절토 비율로 다시 나누면 안 된다.
절토 비율(3:1)로 안분하면 0.30/0.10 이 되지만, 설계는 암반 경계선으로 0.05/0.35 를
냈다. 그 값이 그대로 서야 횡단도와 토적표의 숫자가 같아진다.
"""
stations = [
StationArea(chainage_m=0.0),
StationArea(
chainage_m=10.0,
cut_soil_area_m2=3.0,
cut_rock_area_m2=1.0,
ditch_area_m2=0.4,
ditch_soil_area_m2=0.05,
ditch_rock_area_m2=0.35,
ditch_split_basis="rock_boundary",
cut_rock_kind="ripping_rock",
),
]
row = build_rows(stations)[1]
assert row.ditch_soil_area_m2 == pytest.approx(0.05)
assert row.ditch_rock_area_m2 == pytest.approx(0.35)
assert row.ditch_split_basis == "rock_boundary"
assert row.notes == [] # 설계값을 읽었으므로 폴백 사유가 없다.
def test_못_가른_측점은_사유와_함께_전량_암() -> None:
"""암 지반인데 암반 경계선이 없으면 설계가 전량 암으로 낸다 — 여기서 손보지 않는다."""
stations = [
StationArea(chainage_m=0.0),
StationArea(
chainage_m=10.0,
cut_soil_area_m2=2.0,
cut_rock_area_m2=2.0,
ditch_area_m2=0.18,
ditch_soil_area_m2=0.0,
ditch_rock_area_m2=0.18,
ditch_split_basis="rock_ground_no_boundary",
cut_rock_kind="blasting_rock",
),
]
row = build_rows(stations)[1]
assert row.ditch_soil_area_m2 == 0.0 # 절반씩 임의로 나누지 않는다.
assert row.ditch_rock_area_m2 == pytest.approx(0.18)
assert row.ditch_split_basis == "rock_ground_no_boundary"
def test_설계값이_없을_때만_절토_비율로_안분() -> None:
"""가름이 붙기 전 저장분 — 폴백으로 안분하되 사유를 남겨 설계값과 구분한다."""
stations = [
StationArea(chainage_m=0.0),
StationArea(
@@ -130,6 +177,8 @@ def test_측구_안분은_절토_토사암_비율() -> None:
row = build_rows(stations)[1]
assert row.ditch_soil_area_m2 == pytest.approx(0.3)
assert row.ditch_rock_area_m2 == pytest.approx(0.1)
assert row.ditch_split_basis == "cut_area_ratio_fallback"
assert row.notes and "안분" in row.notes[0]
def test_값을_자르지_않을것() -> None:
@@ -145,9 +194,7 @@ def test_합계행() -> None:
rows = build_rows(거창_앞_네_측점())
total = totals(rows)
assert total["distance_m"] == pytest.approx(30.0)
assert total["cut_soil_volume_m3"] == pytest.approx(
sum(r.cut_soil_volume_m3 for r in rows)
)
assert total["cut_soil_volume_m3"] == pytest.approx(sum(r.cut_soil_volume_m3 for r in rows))
def test_표_모양() -> None:
@@ -166,12 +213,26 @@ def test_설계결과에서_담기() -> None:
"cut_rock_area_m2": 0.5,
"fill_area_m2": 2.0,
"ditch_area_m2": 0.18,
"ditch_soil_area_m2": 0.12,
"ditch_rock_area_m2": 0.06,
"ditch_split_basis": "rock_boundary",
"cut_rock_kind": "blasting_rock",
}
area = StationArea.from_design(20.0, design)
assert area.chainage_m == 20.0
assert area.cut_soil_area_m2 == 1.5
assert area.cut_rock_kind == "blasting_rock"
assert area.ditch_soil_area_m2 == 0.12
assert area.ditch_rock_area_m2 == 0.06
assert area.ditch_split_basis == "rock_boundary"
def test_가름이_없는_저장분은_None으로_받음() -> None:
"""0.0 과 「설계가 안 냄」은 다르다 — None 이라야 폴백이 선다."""
area = StationArea.from_design(20.0, {"cut_soil_area_m2": 1.5, "ditch_area_m2": 0.18})
assert area.ditch_soil_area_m2 is None
assert area.ditch_rock_area_m2 is None
assert area.ditch_split_basis is None
def test_측점_순서가_뒤죽박죽이어도_이정순으로() -> None: