fix(472-2 덧 횡단 차례): 횡단 파일 = 측점(누가거리) 차례로 읽음 — 이름 차례면 cross_01080.16m 이 cross_01080m 앞
- cross_files_in_order 한 벌(Engine_Sections) — B06 상세 GET(_read_section_detail) · B07 측점 파일(_cross_files) 둘 다 이것으로 - B07 측점 도면 장 나눔의 이름 차례 sorted 걷음 - 시험 test_472_2_cross_order(옛 코드 빨강 셋 → 초록) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -163,6 +163,18 @@ def valid_cross_names(cross_dir: Path, stations: list[Any]) -> set[str]:
|
||||
}
|
||||
|
||||
|
||||
def cross_files_in_order(cross_dir: Path, stations: list[Any]) -> list[Path]:
|
||||
"""잔재를 걸러 읽을 cross_*.json — **측점 차례**(이름 차례면 `01080.16` 이 `01080` 앞)."""
|
||||
valid = valid_cross_names(cross_dir, stations)
|
||||
|
||||
def chainage(path: Path) -> tuple[float, str]:
|
||||
match = re.fullmatch(rf"cross_{CROSS_KEY_PATTERN}m", path.stem)
|
||||
return (float(match.group(1)) if match else float("inf"), path.name)
|
||||
|
||||
files = [path for path in cross_dir.glob("cross_*.json") if not valid or path.name in valid]
|
||||
return sorted(files, key=chainage)
|
||||
|
||||
|
||||
def prune_stale_cross_files(cross_dir: Path, stations: list[Any]) -> set[str]:
|
||||
"""stations에 없는 잔재 cross_*.json을 삭제하고 유효 파일명 집합을 반환한다.
|
||||
|
||||
|
||||
@@ -16,9 +16,9 @@ from fastapi.responses import JSONResponse, Response
|
||||
from B03_FileInput.B03_FileInput_Repository import get_project_storage_relative_path
|
||||
from B05_Profile.B05_Profile_Engine_Grade_Profile import rebuild_alignment_profile
|
||||
from B05_Profile.B05_Profile_Engine_Sections import (
|
||||
cross_files_in_order,
|
||||
relabel_pipe_stations,
|
||||
run_section_generation,
|
||||
valid_cross_names,
|
||||
)
|
||||
from B05_Profile.B05_Profile_Engine_Sections_Core import SectionGenerationOptions
|
||||
from B06_Section.B06_Section_Engine_Attach import attach_saved_shapes
|
||||
@@ -248,12 +248,10 @@ def _read_section_detail(project_root: Path, longitudinal_file_path: str) -> dic
|
||||
|
||||
longitudinal = json.loads(longitudinal_path.read_text(encoding="utf-8"))
|
||||
stations = longitudinal.get("stations") if isinstance(longitudinal, dict) else None
|
||||
# 조회는 지우지 않음 — 잔재는 걸러 읽기만(지우기는 측점을 쓰는 쪽 몫)
|
||||
valid_names = valid_cross_names(cross_dir, stations if isinstance(stations, list) else [])
|
||||
# 조회는 지우지 않음 — 잔재는 걸러 읽기만(지우기는 측점을 쓰는 쪽 몫) · 측점 차례(472-2)
|
||||
cross_sections = [
|
||||
json.loads(path.read_text(encoding="utf-8"))
|
||||
for path in sorted(cross_dir.glob("cross_*.json"))
|
||||
if not valid_names or path.name in valid_names
|
||||
for path in cross_files_in_order(cross_dir, stations if isinstance(stations, list) else [])
|
||||
]
|
||||
if not isinstance(longitudinal, dict) or not all(
|
||||
isinstance(section, dict) for section in cross_sections
|
||||
|
||||
@@ -286,7 +286,7 @@ def _cross_sheet_plan(project_root: Path, longitudinal_path: Path) -> list[dict[
|
||||
"""
|
||||
longitudinal = _read_json(longitudinal_path)
|
||||
chainages: list[int | float] = []
|
||||
for path in sorted(_cross_files(longitudinal_path, longitudinal)):
|
||||
for path in _cross_files(longitudinal_path, longitudinal):
|
||||
match = _CROSS_ID.fullmatch(path.stem)
|
||||
if not match:
|
||||
continue
|
||||
|
||||
@@ -9,7 +9,7 @@ import re
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from B05_Profile.B05_Profile_Engine_Sections import cross_station, valid_cross_names
|
||||
from B05_Profile.B05_Profile_Engine_Sections import cross_files_in_order, cross_station
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -39,12 +39,8 @@ def _cross_files(longitudinal_path: Path, longitudinal: dict[str, Any]) -> list[
|
||||
if not cross_dir.is_dir():
|
||||
raise FileNotFoundError("B06 횡단면 파일을 찾을 수 없습니다.")
|
||||
stations = longitudinal.get("stations")
|
||||
# 읽기는 지우지 않음 — 잔재는 걸러 읽기만(지우기는 측점을 쓰는 쪽 몫 · R26)
|
||||
valid_names = valid_cross_names(cross_dir, stations if isinstance(stations, list) else [])
|
||||
files = sorted(cross_dir.glob("cross_*.json"))
|
||||
if valid_names:
|
||||
files = [path for path in files if path.name in valid_names]
|
||||
return files
|
||||
# 읽기는 지우지 않음 — 잔재는 걸러 읽기만(지우기는 측점을 쓰는 쪽 몫 · R26) · 측점 차례(472-2)
|
||||
return cross_files_in_order(cross_dir, stations if isinstance(stations, list) else [])
|
||||
|
||||
|
||||
def _station_map(longitudinal: dict[str, Any]) -> dict[int | float, dict[str, Any]]:
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""472-2 덧 — 횡단 파일을 측점(누가거리) 차례로 읽는지.
|
||||
|
||||
이름 차례면 `cross_01080.16m` 이 `cross_01080m` 앞(「.」 < 「m」) → GET 상세의 측점 차례가
|
||||
어긋나 화면 차례 짝(detailCross)이 갈리고, B07 측점 도면 장 나눔도 차례가 뒤집힘.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
if str(ROOT) not in sys.path:
|
||||
sys.path.insert(0, str(ROOT))
|
||||
|
||||
from B06_Section.B06_Section_Router import _read_section_detail # noqa: E402
|
||||
from B07_DesignDetail.B07_DesignDetail_Router_Support_Io import _cross_files # noqa: E402
|
||||
|
||||
CHAINAGES = [1060.0, 1080.0, 1080.16, 1100.0, 999.5]
|
||||
NAMES = {
|
||||
1060.0: "cross_01060m.json",
|
||||
1080.0: "cross_01080m.json",
|
||||
1080.16: "cross_01080.16m.json",
|
||||
1100.0: "cross_01100m.json",
|
||||
999.5: "cross_00999.50m.json",
|
||||
}
|
||||
|
||||
|
||||
def _stage(tmp_path: Path) -> Path:
|
||||
stage = tmp_path / "B05_Profile"
|
||||
(stage / "cross_sections").mkdir(parents=True)
|
||||
(stage / "longitudinal").mkdir()
|
||||
longitudinal = stage / "longitudinal" / "longitudinal.json"
|
||||
longitudinal.write_text(
|
||||
json.dumps({"stations": [{"chainage_m": m} for m in CHAINAGES]}), encoding="utf-8"
|
||||
)
|
||||
for chainage, name in NAMES.items():
|
||||
(stage / "cross_sections" / name).write_text(
|
||||
json.dumps({"chainage_m": chainage, "samples": []}), encoding="utf-8"
|
||||
)
|
||||
return longitudinal
|
||||
|
||||
|
||||
def test_상세_GET_은_측점_차례(tmp_path: Path) -> None:
|
||||
longitudinal = _stage(tmp_path)
|
||||
detail = _read_section_detail(tmp_path, str(longitudinal.relative_to(tmp_path)))
|
||||
got = [section["chainage_m"] for section in detail["cross_sections"]]
|
||||
assert got == sorted(CHAINAGES)
|
||||
|
||||
|
||||
def test_B07_측점_파일도_측점_차례(tmp_path: Path) -> None:
|
||||
longitudinal = _stage(tmp_path)
|
||||
files = _cross_files(longitudinal, json.loads(longitudinal.read_text(encoding="utf-8")))
|
||||
assert [path.name for path in files] == [NAMES[m] for m in sorted(CHAINAGES)]
|
||||
|
||||
|
||||
def test_B07_장_나눔도_측점_차례() -> None:
|
||||
"""장 나눔 쪽이 이름으로 다시 줄 세우지 않음(`sorted(_cross_files(…))` = 이름 차례)."""
|
||||
source = (ROOT / "B07_DesignDetail" / "B07_DesignDetail_Router_Support.py").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
assert "sorted(_cross_files(" not in source
|
||||
Reference in New Issue
Block a user