Files
Aislo/resources/tester/test_b08_earthwork_table.py
T
eomsangdonandClaude Opus 5 d7cb14f416 test(B08): tmp/tests 중 tester 에 없던 47 개를 resources/tester 로 옮김
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>
2026-09-09 17:15:57 +09:00

185 lines
6.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""토적표 엔진 검사 — PLAN 8-4b·8-16.
정답지는 거창 실무 토적표(오솔길 `1.BOM` 과 1:1)다. 평균단면적법이 실물과 같은 값을
내는지, 첫 측점에 체적이 없는지, 값을 자르지 않는지를 못 박는다.
"""
from __future__ import annotations
import sys
from pathlib import Path
import pytest
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT))
from B08_Quantity.B08_Quantity_Engine_EarthworkTable import ( # noqa: E402
StationArea,
build_rows,
build_table,
totals,
)
from config.config_system_design import EARTHWORK_CONVERSION_FACTORS # noqa: E402
SOIL_C = EARTHWORK_CONVERSION_FACTORS["soil"]["compacted"]
def 거창_앞_네_측점() -> list[StationArea]:
"""거창 `1.BOM` 앞부분 — 절토 토사만 있고 측구는 단면 0.18㎡ 고정인 구간.
BOM 값: 0(0.00) · 0+10(1.89) · 1(1.73) · 1+10(1.45), 거리 10m 등간.
"""
return [
StationArea(chainage_m=0.0, cut_soil_area_m2=0.00, ditch_area_m2=0.0),
StationArea(chainage_m=10.0, cut_soil_area_m2=1.89, ditch_area_m2=0.18),
StationArea(chainage_m=20.0, cut_soil_area_m2=1.73, ditch_area_m2=0.18),
StationArea(chainage_m=30.0, cut_soil_area_m2=1.45, ditch_area_m2=0.18),
]
def test_첫_측점은_체적이_없음() -> None:
"""앞 측점이 없으면 평균을 낼 수 없다 — 실무 토적표도 첫 행 체적이 비어 있다."""
rows = build_rows(거창_앞_네_측점())
assert rows[0].distance_m == 0.0
assert rows[0].cut_soil_volume_m3 == 0.0
assert rows[0].adjusted_total_m3 == 0.0
def test_평균단면적법_실무값_재현() -> None:
"""BOM 0+10 행: 단면적 1.89 → 체적 9.45 → 보정 8.50 (거리 10m)."""
rows = build_rows(거창_앞_네_측점())
row = rows[1]
assert row.distance_m == pytest.approx(10.0)
assert row.cut_soil_volume_m3 == pytest.approx(9.45) # (0.00+1.89)/2 × 10
assert row.cut_soil_adjusted_m3 == pytest.approx(9.45 * SOIL_C)
assert row.cut_soil_adjusted_m3 == pytest.approx(8.505) # BOM 표기 8.50
def test_평균단면적법_다음_측점() -> None:
"""BOM 1 행: (1.89+1.73)/2 × 10 = 18.10 → 보정 16.29."""
row = build_rows(거창_앞_네_측점())[2]
assert row.cut_soil_volume_m3 == pytest.approx(18.10)
assert row.cut_soil_adjusted_m3 == pytest.approx(16.29)
def test_측구_단면_0_18이_체적으로() -> None:
"""측구 0.18㎡ 가 이어지면 10m 당 1.80㎥ — BOM 10열과 같다."""
rows = build_rows(거창_앞_네_측점())
assert rows[2].ditch_soil_volume_m3 == pytest.approx(1.80)
assert rows[2].ditch_soil_adjusted_m3 == pytest.approx(1.62)
def test_보정량계는_네_갈래_합() -> None:
row = build_rows(거창_앞_네_측점())[2]
assert row.adjusted_total_m3 == pytest.approx(
row.cut_soil_adjusted_m3
+ row.cut_rock_adjusted_m3
+ row.ditch_soil_adjusted_m3
+ row.ditch_rock_adjusted_m3
)
assert row.adjusted_total_m3 == pytest.approx(16.29 + 1.62) # BOM 15열 17.91
def test_누가토량은_차인토량의_누계() -> None:
"""유토곡선의 원본이 이 열이다 — 누계가 어긋나면 곡선이 통째로 틀린다."""
rows = build_rows(거창_앞_네_측점())
running = 0.0
for row in rows:
running += row.balance_m3
assert row.cumulative_m3 == pytest.approx(running)
def test_성토가_있으면_유용토는_작은_쪽() -> None:
stations = [
StationArea(chainage_m=0.0),
StationArea(chainage_m=10.0, cut_soil_area_m2=2.0, fill_area_m2=8.0),
]
row = build_rows(stations)[1]
assert row.adjusted_total_m3 == pytest.approx(10.0 * SOIL_C) # 절취 10㎥ → 보정 9㎥
assert row.fill_volume_m3 == pytest.approx(40.0)
assert row.diverted_m3 == pytest.approx(9.0) # 둘 중 작은 쪽
assert row.balance_m3 == pytest.approx(9.0 - 40.0)
def test_암은_토사와_다른_계수() -> None:
"""토사 0.90 · 리핑암 1.15 — 한 계수로 뭉치면 암 물량이 틀린다."""
stations = [
StationArea(chainage_m=0.0),
StationArea(chainage_m=10.0, cut_rock_area_m2=2.0, cut_rock_kind="ripping_rock"),
]
row = build_rows(stations)[1]
assert row.cut_rock_volume_m3 == pytest.approx(10.0)
assert row.cut_rock_adjusted_m3 == pytest.approx(
10.0 * EARTHWORK_CONVERSION_FACTORS["ripping_rock"]["compacted"]
)
def test_측구_안분은_절토_토사암_비율() -> None:
"""측구 지반이 따로 안 오므로 그 측점 절토 비율로 가른다(엔진 주석의 TODO 자리)."""
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,
cut_rock_kind="ripping_rock",
),
]
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)
def test_값을_자르지_않을것() -> None:
"""품셈 1-2-2 는 표기 규칙이다 — 엔진은 전정밀로 둔다(PLAN 8-16)."""
stations = [StationArea(chainage_m=0.0), StationArea(chainage_m=7.0, cut_soil_area_m2=1.0)]
row = build_rows(stations)[1]
assert row.cut_soil_volume_m3 == pytest.approx(3.5)
assert row.cut_soil_adjusted_m3 == pytest.approx(3.15)
assert repr(row.cut_soil_adjusted_m3) != "3.2"
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)
)
def test_표_모양() -> None:
table = build_table(거창_앞_네_측점())
assert table["method"] == "average_end_area"
assert table["station_count"] == 4
assert table["conversion_factors"] is EARTHWORK_CONVERSION_FACTORS
assert len(table["rows"]) == 4
assert "cut_soil_adjusted_m3" in table["rows"][1]
def test_설계결과에서_담기() -> None:
"""B06 설계 결과의 키 이름을 그대로 받는다 — 이름이 어긋나면 0 이 조용히 들어간다."""
design = {
"cut_soil_area_m2": 1.5,
"cut_rock_area_m2": 0.5,
"fill_area_m2": 2.0,
"ditch_area_m2": 0.18,
"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"
def test_측점_순서가_뒤죽박죽이어도_이정순으로() -> None:
stations = [
StationArea(chainage_m=20.0, cut_soil_area_m2=1.0),
StationArea(chainage_m=0.0),
StationArea(chainage_m=10.0, cut_soil_area_m2=2.0),
]
rows = build_rows(stations)
assert [r.chainage_m for r in rows] == [0.0, 10.0, 20.0]