- 절토 · 성토측(구조물 트림 선 포함) 고름 = ◀▶ 그 쪽 노견째 · ▲▼ 막음(종단 계획고로 새지 않음) - 도로측(노면 · 노견) 고름 = ◀▶ 막음 · 이동 줄 숨김 · ▲▼ 는 종단도 계획고로 그대로 넘김 - 새 시험 test_193_1_line_axis(갈래 · 바깥만 · 0 에서 멈춤 · 반대측 고정 · 절토 대칭 · 도로 Y 만) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JywHxQuWPk6UYXTebyrBoU
112 lines
4.6 KiB
Python
112 lines
4.6 KiB
Python
"""193-1 B06 횡단 보라 계획선 이동 제약 — 갈래(도로 · 절토 · 성토)마다 축 · 방향.
|
|
|
|
화면 TS(`_Cross_Design_Pick`)를 흉내 DOM 으로 돌린 값(`helper_193_1_line_axis.cjs`) +
|
|
서버 재계산(노견 확장 = 그 쪽만 · 반대측 고정).
|
|
"""
|
|
|
|
import json
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
HELPER = Path(__file__).parent / "helper_193_1_line_axis.cjs"
|
|
if str(ROOT) not in sys.path:
|
|
sys.path.insert(0, str(ROOT))
|
|
|
|
from B06_Section.B06_Section_Engine_Design import compute_cross_design # noqa: E402
|
|
|
|
node_only = pytest.mark.skipif(
|
|
not (ROOT / "config" / "node_modules").is_dir(), reason="프론트엔드 의존성 미설치"
|
|
)
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def out() -> dict:
|
|
done = subprocess.run( # noqa: S603 — 고정 실행 파일
|
|
["node", str(HELPER)], cwd=str(ROOT), capture_output=True, text=True, encoding="utf-8"
|
|
)
|
|
assert done.returncode == 0, done.stderr
|
|
return json.loads(done.stdout)
|
|
|
|
|
|
@node_only
|
|
def test_갈래_판정(out: dict) -> None:
|
|
assert out["axis"] == {"left": "x", "road": "y", "right": "x", "structure": "x"}
|
|
assert out["cutZone"] == "cut" and out["cut"]["axis"] == "x"
|
|
|
|
|
|
@node_only
|
|
def test_성토측_바깥_가로만_중심_못_넘음(out: dict) -> None:
|
|
fill = out["fill"]
|
|
assert fill["upBlocked"] and fill["downBlocked"] # ▲▼ 가 종단 계획고로 새지 않음
|
|
assert fill["afterUpDown"] == {"left": 0, "right": 0}
|
|
assert fill["out2"] == {"left": 0.2, "right": 0} # ← ← = 좌 바깥 0.2 · 우 그대로
|
|
assert fill["inward"] == {"left": 0, "right": 0} # 안쪽 30 걸음 = 0 에서 멈춤
|
|
assert fill["title"] == "사면 이동 (좌)" and fill["rowHidden"] is False
|
|
assert fill["profileUp"] is False # 종단도를 눌렀으면 방향키는 종단도 몫
|
|
assert out["right"]["values"] == {"left": 0.1, "right": 0.1} # 우 사면 = 우 바깥만
|
|
|
|
|
|
@node_only
|
|
def test_구조물_선_반대측_고정_한_벌(out: dict) -> None:
|
|
"""성토측 구조물 트림 선 = 그 쪽 노견째(벽은 노견 끝에 섬) · 반대측 0 그대로."""
|
|
assert out["structure"]["values"] == {"left": 0.1, "right": 0}
|
|
assert out["structure"]["title"] == "사면 이동 (좌)" and out["structure"]["upBlocked"]
|
|
|
|
|
|
@node_only
|
|
def test_절토측_같은_규칙(out: dict) -> None:
|
|
cut = out["cut"]
|
|
assert cut["upBlocked"]
|
|
assert cut["outward"] == {"left": 0.1, "right": 0}
|
|
assert cut["inward"] == {"left": 0, "right": 0}
|
|
|
|
|
|
@node_only
|
|
def test_도로측_높이만_종단_함께(out: dict) -> None:
|
|
road = out["road"]
|
|
assert road["upPassed"] and road["downPassed"] # ▲▼ = 종단도 계획고(지금 길 그대로)
|
|
assert road["leftBlocked"] and road["rightBlocked"] and road["same"]
|
|
assert road["title"] == "노면 높이" and road["rowHidden"] is True
|
|
assert "이동" not in road["label"]
|
|
assert out["released"] == [False, False] # 고름 풀면 막지 않음
|
|
|
|
|
|
def test_종단도는_막힌_방향키를_건너뜀() -> None:
|
|
src = (ROOT / "B05_Profile" / "B05_Profile_UI_Profile_Panel_Tools.ts").read_text(
|
|
encoding="utf-8"
|
|
)
|
|
assert "if (event.defaultPrevented) return;" in src
|
|
assert "ctx.applyEdits(adjustStation(base, ctx.edits(), chainage, delta))" in src
|
|
|
|
|
|
def _ground(level: float) -> list[dict]:
|
|
return [{"offset_m": o / 2, "elevation_m": level, "valid": True} for o in range(-30, 31)]
|
|
|
|
|
|
def test_서버_한쪽_이동_반대측_고정_바깥으로() -> None:
|
|
samples = _ground(97.0)
|
|
base = compute_cross_design(samples, 100.0, ground_type="soil", section_mode="both_fill")
|
|
moved = compute_cross_design(
|
|
samples, 100.0, ground_type="soil", section_mode="both_fill", shoulder_extend_left_m=0.7
|
|
)
|
|
right = lambda d: [p for p in d["design_line"] if p["offset_m"] < 0] # noqa: E731
|
|
assert right(moved) == right(base) # 반대측 고정
|
|
assert moved["road_edges"]["right"] == base["road_edges"]["right"]
|
|
assert moved["road_edges"]["left"]["offset_m"] == pytest.approx(
|
|
base["road_edges"]["left"]["offset_m"] + 0.7
|
|
)
|
|
toe = lambda d: max(p["offset_m"] for p in d["design_line"] if p["elevation_m"] > 97.0) # noqa: E731
|
|
assert toe(moved) > toe(base) # 사면째 바깥으로
|
|
|
|
|
|
def test_구조물은_노견_끝에_섬() -> None:
|
|
"""관 기슭막이 자리 = 설계 노견 끝(`road_edges` · 노견 확장 포함) — 사면과 한 벌로 감."""
|
|
src = (ROOT / "B06_Section" / "B06_Section_UI_Cross_Culvert_Geom.ts").read_text(
|
|
encoding="utf-8"
|
|
)
|
|
assert "const edges = section.design?.road_edges;" in src
|