Files
Aislo/resources/tester/test_192_1_moved_pipe_station.py
T
eomsangdonandClaude Opus 5.5 ffa7f9d236 fix(B05·B06): 유령 계획고 편집 근본 막음 — 옮긴 관 편집 따라감 · [저장] 때 자리 없는 편집 버림 · 알림(213-2)
- ① 관 옮김 = 편집 키도 새 자리로: B06 movePipeTo 가 resetStationEdit(옛, 새) · B05 측점 갱신이 사라진 것 하나 · 새것 하나(또는 같은 id · 0.006 m 안)를 짝으로 옮김(followedStation) — 세션 초안도 새 키라 옛 키가 다시 안 나감
- ② [저장](PUT profile-alignment)에서 서버가 측점 · 관 · 구조물 자리 어디에도 없는 편집 키를 버림(drop_unplaced_edits · 저장 차례가 관 · 구조물 뒤라 최신) · 응답 dropped_edit_chainages · 화면 알림 「계획고 편집 N곳을 지웠습니다」 · 자리 못 읽으면 안 버림
- ③ test_192_1 = 고정 사본(fixtures/b05_192_1_moved_pipe_longitudinal.json · 226fc805 460~840 m) · 새 시험 test_213_2

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F3mdb91125mPoC6tpsQx4P
2026-10-10 15:44:28 +09:00

122 lines
5.4 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.
"""192-1 — 종단 계획선 숨은 꺾임(검증_랩탑메인 226fc805 · No.38+9).
까닭: 관을 769.28 → 769.38(0.1m) 옮김 → 「측점 있음」 판정 폭이 0.5m 라 측점이 옛 자리
769.28 에 남음 → B06(측점 769.28)과 B05(관 769.38) 두 자리에 계획고 편집이 남아 0.1m 사이
−465% 계단 · 769.38 은 측점선 없는 꼭짓점.
고침: 판정 폭 0.005m(측점 스냅 폭) · 측점을 다시 뜨면 사라진 측점의 꼭짓점 · 편집을 지움
(반올림 차이 0.006m 안은 옮김). 자료 = 고정 사본(fixtures/b05_192_1_moved_pipe_longitudinal.json ·
226fc805 종단 460~840m · 측점 769.28 인 192 이전 상태 · 213-2) — 사용자 storage 에 기대지 않음.
"""
from __future__ import annotations
import copy
import json
import shutil
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))
import B05_Profile.B05_Profile_Engine_Sections as sections # noqa: E402
from B05_Profile.B05_Profile_Engine_Grade_Profile import rebuild_alignment_profile # noqa: E402
from B05_Profile.B05_Profile_Router_Confirm import _merge_irregular_into_longitudinal # noqa: E402
from B06_Section.B06_Section_Router_Stations import _missing_marks # noqa: E402
SOURCE = PROJECT_ROOT / "resources/tester/fixtures/b05_192_1_moved_pipe_longitudinal.json"
REL = "B06_Section/longitudinal/longitudinal.json"
def _copy(tmp_path: Path) -> Path:
target = tmp_path / REL
target.parent.mkdir(parents=True)
shutil.copyfile(SOURCE, target)
return target
def _load(path: Path) -> dict:
return json.loads(path.read_text(encoding="utf-8"))
def _irregular(data: dict, old: float, new: float) -> list[dict]:
"""다시 뜬 비정규 측점 목록 흉내 — `old` 측점만 `new` 로 옮김."""
result = []
for station in data["stations"]:
if station.get("kind") != "irregular":
continue
item = copy.deepcopy(station)
if abs(item["chainage_m"] - old) < 1e-6:
item["chainage_m"] = new
result.append(item)
return result
def test_원본_자료가_숨은_꼭짓점을_가짐() -> None:
"""까닭 근거 — 769.38 꼭짓점은 측점 목록에 없고 두 편집 사이 −465%."""
data = _load(SOURCE)
alignment, _ = rebuild_alignment_profile(data, data["profile_alignment"]["edits"])
stations = [s["chainage_m"] for s in data["stations"]]
pvis = [p["chainage_m"] for p in alignment["pvi"]]
assert 769.38 in pvis and 769.38 not in stations and 769.28 in stations
assert {"769.280", "769.380"} <= set(alignment["edits"]["station_offsets"])
step = next(s for s in alignment["segments"] if s["from_m"] == 769.28)
assert step["to_m"] == 769.38 and step["grade_percent"] < -400
def test_관_옮긴_측점_다시_뜨면_숨은_꼭짓점_사라짐(tmp_path: Path) -> None:
path = _copy(tmp_path)
data = _load(path)
summary = _merge_irregular_into_longitudinal(tmp_path, REL, _irregular(data, 769.28, 769.38))
after = _load(path)
alignment = after["profile_alignment"]
stations = {round(s["chainage_m"], 3) for s in after["stations"]}
near = [p for p in alignment["pvi"] if 760 < p["chainage_m"] < 780]
assert [p["chainage_m"] for p in near] == [769.38] # 꼭짓점 하나 · 측점선 있음
assert 769.38 in stations and 769.28 not in stations
assert alignment["edits"]["station_offsets"] == {"769.380": pytest.approx(0.051428)}
assert all(abs(b["chainage_m"] - 769.28) > 1e-6 for b in alignment["base_pvi"])
grades = [s["grade_percent"] for s in alignment["segments"] if 760 <= s["from_m"] < 780]
assert max(abs(g) for g in grades) < 20
assert summary is not None and summary["max_grade_pct"] < 20
assert after["design_profiles"][0]["summary"]["max_grade_pct"] == summary["max_grade_pct"]
def test_반올림_차이만_다르면_편집을_옮김(tmp_path: Path) -> None:
path = _copy(tmp_path)
data = _load(path)
data["profile_alignment"]["edits"]["station_offsets"]["484.210"] = 0.3
path.write_text(json.dumps(data), encoding="utf-8")
_merge_irregular_into_longitudinal(tmp_path, REL, _irregular(data, 484.21, 484.213))
offsets = _load(path)["profile_alignment"]["edits"]["station_offsets"]
assert "484.210" not in offsets and offsets["484.213"] == pytest.approx(0.3)
def test_측점이_그대로면_계획선을_건드리지_않음(tmp_path: Path) -> None:
path = _copy(tmp_path)
data = _load(path)
before = data["profile_alignment"]
assert _merge_irregular_into_longitudinal(tmp_path, REL, _irregular(data, -1, -1)) is None
assert _load(path)["profile_alignment"] == before
def test_조금_옮긴_관도_측점_없음으로_셈(tmp_path: Path, monkeypatch) -> None:
"""0.1m 옮긴 관 — 옛 판정(0.5m)은 「측점 있음」으로 놓쳤음."""
target = tmp_path / REL
target.parent.mkdir(parents=True)
target.write_text(
json.dumps({"stations": [{"chainage_m": 760.0}, {"chainage_m": 769.28}]}),
encoding="utf-8",
)
monkeypatch.setattr(sections, "_load_route_polyline", lambda *_: [])
monkeypatch.setattr(sections, "_load_pipe_points", lambda *_: [])
monkeypatch.setattr(
sections, "resolve_extra_stations", lambda *_: [(769.38, "파형강관 D800"), (760.0, "옹벽")]
)
assert _missing_marks(tmp_path, "route.csv") == [
{"chainage_m": 769.38, "label": "파형강관 D800"}
]