- 부품 처음값 spoil_bank 형상 · 3D = none · 형상 부품 「사토(성토 채움)」 지움 - 사토 단면 셈 파이썬 · TS 짝 지움(Engine_SpoilFill · common_util_spoil_fill · spoil_fill 옵션 · fill_area_beyond) - 카드 그림 · 면적표 줄 · 모달 띠 · 고름 선 · B07 표 「사토장」 칸 지움(빈 줄로 되돌림) - B08 수량 · 유토 배분(haul-plan) 미사용 확인 · 남은 사토 값 = [저장] 서버 재계산 · 브라우저 단계 다시 셈으로 정리 - 시험 고쳐 씀: 322_1 · 349_0n · b06_spoil_fill_allocation(남은 값 정리) · spoil_fill_mirror(죽은 길) · 52_9 · cross_design_mirror · 150 · 164 · 179_4 · 316 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VmC34fsxxbweEG3RUjs3Mn
110 lines
4.0 KiB
Python
110 lines
4.0 KiB
Python
"""사토장 — 횡단 단면 셈 지움 · 남은 사토 값 정리 (PLAN 380-1 · 요구 241-8).
|
|
|
|
⚠ 잠그는 것
|
|
① 사토장이 놓여도 [저장]·[확정] 서버 재계산(`enforce_design_lines` → `_enforce_stored_designs`)이
|
|
사토 단면을 세우지 않는다 — 횡단도에 그림 없음 · 상세 CAD 글만.
|
|
② 옛 저장분에 남은 `spoil_fill_*` 값(노선 성토를 뺀 꼴)은 [저장] 한 번에 지워지고
|
|
노선 성토(`fill_area_m2`)가 사토장 없는 값으로 돌아온다.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
PROJECT_ROOT = Path(__file__).resolve().parents[2]
|
|
if str(PROJECT_ROOT) not in sys.path:
|
|
sys.path.insert(0, str(PROJECT_ROOT))
|
|
|
|
from B06_Section.B06_Section_Engine_Design import compute_cross_design # noqa: E402
|
|
from B06_Section.B06_Section_Router_Design import enforce_design_lines # noqa: E402
|
|
from B06_Section.B06_Section_Server_Calc_Prebuild import _enforce_stored_designs # noqa: E402
|
|
|
|
|
|
def _samples() -> list[dict]:
|
|
"""우측(-offset)이 높고 좌측(+offset)이 낮은 지반 — 좌가 성토 쪽."""
|
|
return [
|
|
{"offset_m": round(offset, 3), "elevation_m": round(100.0 - 0.5 * offset, 4), "valid": True}
|
|
for offset in [x * 0.5 for x in range(-30, 31)]
|
|
]
|
|
|
|
|
|
def _plain() -> dict:
|
|
return compute_cross_design(
|
|
_samples(), 99.8, ground_type="soil", section_mode="right_cut", ditch_side="right"
|
|
)
|
|
|
|
|
|
_LONGITUDINAL = {
|
|
"design_profiles": [
|
|
{"samples": [{"chainage_m": float(c), "elevation_m": 99.8} for c in range(0, 201, 20)]}
|
|
]
|
|
}
|
|
|
|
|
|
def _write_site(root: Path) -> None:
|
|
(root / "B05_Profile" / "route").mkdir(parents=True, exist_ok=True)
|
|
(root / "B05_Profile" / "route" / "structures.json").write_text(
|
|
json.dumps(
|
|
{
|
|
"revision": 1,
|
|
"structures": [
|
|
{
|
|
"structure_id": "sp-1",
|
|
"type_id": "spoil_bank",
|
|
"placement": "site",
|
|
"chainage_m": 120.0,
|
|
"options": {"capacity_m3": 400.0, "side": "좌"},
|
|
}
|
|
],
|
|
},
|
|
ensure_ascii=False,
|
|
),
|
|
encoding="utf-8",
|
|
)
|
|
|
|
|
|
def _leftover() -> dict:
|
|
"""옛 저장분 꼴 — 사토장 몫 1 ㎡ 를 노선 성토에서 뺀 채 `spoil_fill_*` 가 남음."""
|
|
design = _plain()
|
|
return {
|
|
**design,
|
|
"fill_area_m2": round(design["fill_area_m2"] - 1.0, 4),
|
|
"spoil_fill_area_m2": 7.0,
|
|
"spoil_fill_side": "left",
|
|
"spoil_fill_width_m": 3.0,
|
|
"spoil_fill_line": [{"offset_m": 3.0, "elevation_m": 99.0}],
|
|
"spoil_fill_replaced_fill_m2": 1.0,
|
|
"spoil_fill_capacity_m3": 400.0,
|
|
"spoil_fill_structure_id": "sp-1",
|
|
}
|
|
|
|
|
|
def test_설계_결과에_사토_칸_없음() -> None:
|
|
assert not [key for key in _plain() if key.startswith("spoil_fill")]
|
|
|
|
|
|
def test_사토장이_놓여도_저장_재계산이_사토_단면을_안_세움(tmp_path: Path) -> None:
|
|
_write_site(tmp_path)
|
|
sections = [
|
|
{"chainage_m": c, "samples": _samples(), "design": _plain()} for c in (100.0, 120.0, 140.0)
|
|
]
|
|
enforce_design_lines(_LONGITUDINAL, sections, tmp_path)
|
|
_enforce_stored_designs(_LONGITUDINAL, sections, tmp_path, None)
|
|
for section in sections:
|
|
assert not [key for key in section["design"] if key.startswith("spoil_fill")]
|
|
|
|
|
|
def test_옛_사토_값은_저장_한_번에_지워지고_성토_돌아옴(tmp_path: Path) -> None:
|
|
_write_site(tmp_path)
|
|
plain_fill = _plain()["fill_area_m2"]
|
|
assert plain_fill > 1.0 # 성토가 실제로 서는 지반이라야 「돌아옴」이 뜻을 가짐
|
|
sections = [{"chainage_m": 120.0, "samples": _samples(), "design": _leftover()}]
|
|
assert enforce_design_lines(_LONGITUDINAL, sections, tmp_path) == 1
|
|
design = sections[0]["design"]
|
|
assert not [key for key in design if key.startswith("spoil_fill")]
|
|
assert design["fill_area_m2"] == pytest.approx(plain_fill, abs=1e-6)
|