fix(494-2 새 교차 관 기본값): 노선 바뀜 길(손 고침 저장 · 추천 적용 · 초기 종단) 새 세류선 교차 관 = B04 새 관 기본값
- followed_pipes 에서 새로 더한 관(짝 -1)만 _apply_new_defaults · 옛 빈 관 · 사용자 관 그대로 - 시험 test_494_2(옛 코드 빨강) · test_283 새 교차 관 옵션 기대 = 기본값 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -176,6 +176,7 @@ def followed_pipes(
|
||||
"""관 따라감 + 새 세류선 교차점 기본 관(저장 안 함) → (짝, 교차 수, 새 노선 정점) — 체인 ·
|
||||
추천 초기 종단(476) 한 벌."""
|
||||
from B04_PreProcess.B04_PreProcess_Engine_Watershed_Analyze import _base_pipes
|
||||
from B04_PreProcess.B04_PreProcess_Router_Basins import _apply_new_defaults
|
||||
from common_util.common_util_drainage_pipes import fill_pipe_coordinates
|
||||
|
||||
vertices = vertices_of([(p["x"], p["y"]) for p in points])
|
||||
@@ -183,6 +184,8 @@ def followed_pipes(
|
||||
pairs = follow_pipes(old_pipes, vertices)
|
||||
total = float(vertices[-1].chainage_m)
|
||||
crossing = add_crossing_pipes(pairs, _base_pipes(vertices, streams), old_xy, total)
|
||||
# 새 교차 관만 B04 와 같은 등록부 기본값(54-39 · 494-2) — 옛 관 빈칸은 미확정 그대로
|
||||
_apply_new_defaults([pipe for index, pipe in pairs if index < 0])
|
||||
return pairs, crossing, vertices
|
||||
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
⑥ 추천 [적용] 실패 — 초기값 사본(`initial_snapshot`)까지 되돌림
|
||||
⑦ 떠 두기 중 뒤 미리 셈이 파일을 지움(`_derived` 원자 쓰기 · 정리) — 건너뜀(옛 = 500
|
||||
FileNotFoundError)
|
||||
492 코드 = ① ④(손 고침) ⑤ 실패 · 옛 떠 두기 = ⑦ 실패.
|
||||
492 코드 = ① ④(손 고침) ⑤ 실패 · 옛 떠 두기 = ⑦ 실패 · 새 교차 관 = B04 새 관 기본값(494-2).
|
||||
|
||||
체인 · API 는 346-3 가짜 세계(`chain_world` · `api_world`)를 빌려 씀 — 파일은 임시 폴더만.
|
||||
|
||||
@@ -43,8 +43,10 @@ import B04_PreProcess.B04_PreProcess_Engine_Watershed_Analyze as analyze # noqa
|
||||
import B05_Profile.B05_Profile_Route_Save as save # noqa: E402
|
||||
import B05_Profile.B05_Profile_Router_Replan as replan # noqa: E402
|
||||
import B06_Section.B06_Section_Repository as b06_repo # noqa: E402
|
||||
from B04_PreProcess.B04_PreProcess_Router_Basins import _apply_new_defaults # noqa: E402
|
||||
from B05_Profile.B05_Profile_Plus_Stations import load_plus_stations, save_plus_stations # noqa: E402
|
||||
from B05_Profile.B05_Profile_Structures_Repository import load_structures # noqa: E402
|
||||
from common_util.common_util_drainage_pipes import PipePoint # noqa: E402
|
||||
from common_util.common_util_json import atomic_write_json # noqa: E402
|
||||
|
||||
FIXTURE = HERE / "fixtures" / "req283_sub8_route.json"
|
||||
@@ -70,6 +72,13 @@ WALL = {
|
||||
CROSSING = SimpleNamespace(chainage_m=158.31, x=150.0, y=30.0)
|
||||
|
||||
|
||||
def _new_pipe_options() -> dict:
|
||||
"""새 교차 관 옵션 = B04 유역 길의 새 관 기본값(494-2 · 54-39)."""
|
||||
pipe = PipePoint(chainage_m=0.0, source="stream")
|
||||
_apply_new_defaults([pipe])
|
||||
return pipe.options
|
||||
|
||||
|
||||
def _side(xy, x: float, y: float) -> float:
|
||||
from shapely.geometry import LineString, Point
|
||||
|
||||
@@ -137,7 +146,7 @@ def _assert_reset(world, result: dict, cross_seen: list) -> None:
|
||||
assert load_plus_stations(world.root) == []
|
||||
points = json.loads(world.pipes_file.read_text("utf-8"))["points"]
|
||||
assert len(points) == 1, points # 옛 사용자 관 버림 · 새 교차 관만
|
||||
assert points[0]["source"] == "stream" and not points[0].get("options")
|
||||
assert points[0]["source"] == "stream" and points[0]["options"] == _new_pipe_options()
|
||||
assert _side(base.NEW, points[0]["x"], points[0]["y"]) < 1e-6
|
||||
assert "profile" not in world.order # 계획고 옮김 없음 = 1차 계획선
|
||||
assert cross_seen == [[]] # 횡단 손 입력 안 넘김
|
||||
@@ -257,7 +266,7 @@ def test_검증_sub8_추천_적용은_교차_하나(sub8, chain_world, cross_see
|
||||
points = json.loads(chain_world.pipes_file.read_text("utf-8"))["points"]
|
||||
assert [round(p["chainage_m"]) for p in points] == [388]
|
||||
assert _side(sub8["new_xy"], points[0]["x"], points[0]["y"]) < 0.01
|
||||
assert not points[0].get("options")
|
||||
assert points[0]["options"] == _new_pipe_options() # 494-2 새 교차 관 = 기본값
|
||||
assert result["route_reset"]["dropped"]["pipes"] == 1
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""494-2 노선 바뀜 길의 새 세류선 교차 관 = B04 와 같은 등록부 기본값(54-39).
|
||||
|
||||
못박는 것
|
||||
- 손 고침 [저장] · 추천 [적용](체인 `_place_pipes`) · 추천 초기 종단(`reset_facilities`) 셋 다
|
||||
`followed_pipes` 를 지나 새 교차 관이 B04 `_apply_new_defaults` 와 같은 옵션을 받음.
|
||||
- 이미 저장된 빈 관 · 사용자가 옵션을 고른 관은 그대로(10-05 「기존 빈칸 = 미확정」).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
if str(ROOT) not in sys.path:
|
||||
sys.path.insert(0, str(ROOT))
|
||||
|
||||
import B04_PreProcess.B04_PreProcess_Engine_Watershed_Analyze as analyze # noqa: E402
|
||||
import B04_PreProcess.B04_PreProcess_Router_Watershed as watershed # noqa: E402
|
||||
import B05_Profile.B05_Profile_Engine_InitialProfile as initial_profile # noqa: E402
|
||||
import B05_Profile.B05_Profile_Route_Save as save # noqa: E402
|
||||
import common_util.common_util_drainage_pipes as drainage_pipes # noqa: E402
|
||||
from B04_PreProcess.B04_PreProcess_Router_Basins import _apply_new_defaults # noqa: E402
|
||||
from common_util.common_util_drainage_pipes import PIPE_SOURCE_STREAM, PipePoint # noqa: E402
|
||||
|
||||
OLD = [(0.0, 0.0), (100.0, 0.0), (200.0, 0.0), (300.0, 0.0), (400.0, 0.0)]
|
||||
NEW = [(0.0, 0.0), (100.0, 0.0), (200.0, 60.0), (300.0, 0.0), (400.0, 0.0)]
|
||||
# 새 노선 북쪽 휨 위(옛 노선에서 먼) 세류선 교차 하나
|
||||
CROSSING = SimpleNamespace(chainage_m=150.4, x=150.0, y=30.0)
|
||||
|
||||
|
||||
def _b04_defaults() -> dict:
|
||||
"""B04 유역 길이 새 관에 주는 옵션 — 비교 기준."""
|
||||
pipe = PipePoint(chainage_m=150.0, source=PIPE_SOURCE_STREAM)
|
||||
_apply_new_defaults([pipe])
|
||||
return pipe.options
|
||||
|
||||
|
||||
def _old_pipes() -> list[PipePoint]:
|
||||
return [
|
||||
PipePoint(chainage_m=50.0, x=50.0, y=0.0), # 저장된 빈 관 — 미확정 그대로
|
||||
PipePoint(chainage_m=350.0, x=350.0, y=0.0, options={"pipe_kind": "흄관"}), # 사용자 고름
|
||||
]
|
||||
|
||||
|
||||
def _points(xy) -> list[dict[str, float]]:
|
||||
return [{"x": x, "y": y} for x, y in xy]
|
||||
|
||||
|
||||
def _fake_crossings(monkeypatch) -> None:
|
||||
monkeypatch.setattr(analyze, "_base_pipes", lambda vertices, streams: [CROSSING])
|
||||
|
||||
|
||||
def _check(pipes: list[PipePoint], kept: bool) -> None:
|
||||
new = [pipe for pipe in pipes if abs(pipe.chainage_m - 150.0) < 1]
|
||||
assert len(new) == 1 and new[0].options == _b04_defaults()
|
||||
assert new[0].options.get("pipe_diameter_mm") # 관경 빈칸 아님(횡단 관 그림 · 54-39)
|
||||
if kept: # 누가거리 순 = 빈 관 · 새 관 · 사용자 관
|
||||
assert [pipe.options for pipe in pipes[::2]] == [None, {"pipe_kind": "흄관"}]
|
||||
|
||||
|
||||
def test_손_고침_저장_followed_pipes(monkeypatch):
|
||||
_fake_crossings(monkeypatch)
|
||||
old = _old_pipes()
|
||||
pairs, crossing, _ = save.followed_pipes(old, [list(p) for p in OLD], _points(NEW), [])
|
||||
assert crossing == 1
|
||||
_check([pipe for _, pipe in pairs], kept=True)
|
||||
assert old[0].options is None # 옛 목록 그대로
|
||||
|
||||
|
||||
def test_추천_적용_체인_관_저장(monkeypatch):
|
||||
"""체인 [적용](492 초기화) — 옛 관 버림 · 새 교차 관 = 기본값으로 정본 저장."""
|
||||
_fake_crossings(monkeypatch)
|
||||
written: list = []
|
||||
|
||||
async def prepare(_project_id):
|
||||
return {"streams": []}
|
||||
|
||||
monkeypatch.setattr(watershed, "_prepare", prepare)
|
||||
monkeypatch.setattr(
|
||||
drainage_pipes, "save_pipe_points", lambda path, sig, pipes, verts: written.extend(pipes)
|
||||
)
|
||||
pairs, counts = asyncio.run(save._place_pipes(None, "unused", [], [], _points(NEW)))
|
||||
assert counts["crossing"] == 1
|
||||
_check(written, kept=False)
|
||||
|
||||
|
||||
def test_추천_초기_종단_reset_facilities(monkeypatch):
|
||||
_fake_crossings(monkeypatch)
|
||||
pipes, structures, plus = initial_profile.reset_facilities(NEW, [])
|
||||
assert structures == [] and plus == []
|
||||
_check(pipes, kept=False)
|
||||
Reference in New Issue
Block a user