Files
Aislo/resources/tester/test_b05_station_roundtrip.py
T
eomsangdonandClaude Opus 5.5 867c4650c7 fix(B05): 관 · 구조물 자체 측점이 종단 측점에서 정수 m 격자로 붙던 것 — 파일 이름에만 정수 m
PLAN 19장 남은 차이(sub8 왕복 시험): 관 440.24 · 619.71 · 720.44 · 899.91 이 저장 뒤 종단 측점에서
440 · 620 · 720 · 900 으로 붙음(generate_sections 의 정수 m 격자 붙이기). 판정 (다) 유지 — 횡단 파일
이름(cross_{정수m}m)은 그대로 한 정수 m 에 한 장, 측점 값은 관 · 구조물 자체 측점 그대로:
- 같은 정수 m 에 격자 측점이 있으면 격자 대신 관 · 구조물 측점을 씀(kind irregular · 라벨 그대로)
- 시 · 종점 격자는 그대로 두고 라벨만 얹음(노선 끝 측점이 사라지지 않게)
- 비정규끼리 같은 정수 m 면 앞선 것만(종전과 같음 · 파일 한 장)
시험 — test_b05_b06_save_roundtrip[B05] 통과(관 측점 차이 0 · 사본 storage · 읽기 전용 DB) ·
test_b05_extra_stations_supplier(옛 「격자 우선」 기대를 새 규칙으로 · 시 · 종점 하나 더함) ·
test_b05_station_roundtrip · test_regeneration_extra_stations 통과. [B06] 경우의 「횡단 patch 263.47 —
받을 행이 없어 DB 가 버림」은 고치기 전 코드에서도 같게 실패(이번 변경과 무관 · 보고함).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VVM3xZ1aUPcUTuW2WZSnwg
2026-09-29 10:12:59 +09:00

104 lines
3.9 KiB
Python

# -*- coding: utf-8 -*-
"""구조물 측점 왕복 — 옵션 · 메모만 고쳐 저장해도 측점이 그대로(PLAN 19장 sub6).
측점 칸은 잔여거리를 소수 1자리로 보인다. 칸을 안 고쳤으면 실어 둔 누가거리를 그대로
읽어야 한다(123.37 → 123.4 로 뭉개져 옮겨 저장되던 흠). 서버가 관 측점을 0.01m 로
반올림해 돌려주면 계획고 편집(station_offsets)은 지우지 않고 새 측점으로 옮긴다.
Node 헬퍼(`helper_b05_station_roundtrip.cjs`)가 TS 를 트랜스파일해 돌리고 여기서 판정한다.
"""
import json
import os
import subprocess
import pytest
HERE = os.path.dirname(os.path.abspath(__file__))
@pytest.fixture(scope="module")
def results():
proc = subprocess.run(
["node", os.path.join(HERE, "helper_b05_station_roundtrip.cjs")],
capture_output=True,
text=True,
timeout=60,
)
assert proc.returncode == 0, proc.stderr
return json.loads(proc.stdout)
def test_칸을_안_고치면_실어_둔_측점_그대로(results):
assert results["shown"] == ["6", "3.4"]
assert results["untouched"] == 123.37
assert results["untouchedRaw"] == 123.3721
assert results["retypedSame"] == 123.37
assert results["r119"] == ["5", "19.8", 119.8]
def test_칸을_고치면_친_값(results):
assert results["edited"] == pytest.approx(125.2)
assert results["normalized"] == ["2", "10.0", 50]
assert results["cleared"] is None
def test_계획고_편집은_가까운_새_측점으로_옮김(results):
assert results["moved"] == {
"station_offsets": {"200.000": 0.3, "123.370": 0.5},
"curve_radii": {"123.370": 40},
}
# 옮길 곳이 없으면 종전대로 지움
assert "200.000" not in results["deleted"]["station_offsets"]
# ── 서버 — 관 · 구조물 자체 측점은 소수 그대로(정수 m 는 횡단 파일 이름에만) ─────────
# 브레인 판정(다) · 19장 남은 차이: 파일 이름은 한 정수 m 에 한 장 그대로, 측점 값은 사용자가 놓은
# 소수 그대로 저장 · 다시 읽기 · 종단 측점. 임시 storage 에서만 씀(공유 storage 안 건드림).
def _flat_sampler():
import numpy as np
class _Flat:
def sample_xy(self, xy):
count = len(np.asarray(xy, dtype=np.float64))
return np.full(count, 100.0), np.ones(count, dtype=bool)
return _Flat()
def test_사용자_구조물_119_8_저장_다시_읽기_그대로(tmp_path):
from B05_Profile.B05_Profile_Engine_Sections import cross_filename, resolve_extra_stations
from B05_Profile.B05_Profile_Engine_Sections_Core import (
SectionGenerationOptions,
generate_sections,
)
from B05_Profile.B05_Profile_Structures_Repository import load_structures, save_structures
from B05_Profile.B05_Profile_Structures_Schema import StructureInstance
item = StructureInstance(
type_id="cross_drain_exposed",
placement="point",
chainage_m=119.8,
memo="메모만",
placement_source="manual",
)
save_structures(str(tmp_path), [item], base_revision=0)
_, loaded = load_structures(str(tmp_path))
assert [s.chainage_m for s in loaded] == [119.8]
extras = resolve_extra_stations(tmp_path, [])
assert [chainage for chainage, _ in extras] == [119.8]
sections = generate_sections(
[[0.0, 0.0, 100.0], [300.0, 0.0, 100.0]],
_flat_sampler(),
SectionGenerationOptions(extra_stations=extras),
)
chainages = [round(s["chainage_m"], 3) for s in sections["longitudinal"]["stations"]]
# 횡단 측점도 자체 측점 119.8(같은 정수 미터 격자 120 대신 · 파일 이름 cross_00120m 한 장)
assert 119.8 in chainages and 120.0 not in chainages
assert cross_filename(119.8) == cross_filename(120.0)
_, again = load_structures(str(tmp_path))
assert [s.chainage_m for s in again] == [119.8] and again[0].memo == "메모만"