fix(b06): 횡단 카드 고름 뒤 종단 측점 세로선 유지 · 종단 누름 반대 길도 (177-3)
- setSelectedStructure keepStation — B06 카드가 선 주인 · 선 없는 구조물 · 풂도 카드 선 지킴 - 새 시험 test_177_3_station_line_keep Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015sDZSjFvoiDjdGpgj3muc3
This commit is contained in:
@@ -622,12 +622,12 @@ export function createDesignProfile(ctx: DesignProfileContext) {
|
||||
syncDrainageSpans();
|
||||
draw();
|
||||
},
|
||||
/** 사이드 목록에서 고른 구조물을 그래프 알약·측점 세로선 선택에 함께 맞춘다. */
|
||||
setSelectedStructure(structureId: string | null) {
|
||||
// 지금 측점(B06 카드)이 그 구조물 자리면 측점선도 그대로(53-2)
|
||||
/** 고른 구조물에 알약 · 측점선을 맞춤 — 그 자리면 선 그대로(53-2) · keepStation(B06 카드 = 선 주인) = 선 없는 구조물 · 풂도 카드 선 지킴(177-3). */
|
||||
setSelectedStructure(structureId: string | null, keepStation = false) {
|
||||
selectedStructureId = structureId;
|
||||
const own = stationIdAtStructure(structureId) ?? (keepStation ? selectedStationId : null);
|
||||
const keep = structureId !== null && structureIdAtStation(selectedStationId) === structureId;
|
||||
selectedStationId = keep ? selectedStationId : stationIdAtStructure(structureId);
|
||||
selectedStationId = keep ? selectedStationId : own;
|
||||
draw();
|
||||
},
|
||||
/** 이어 공사 시작 기준(측점번호·누가거리 오프셋)을 반영해 측점 라벨·누가거리 표시를 옮긴다. */
|
||||
|
||||
@@ -265,7 +265,7 @@ export function createSectionProfile(
|
||||
},
|
||||
selectMark(structureId) {
|
||||
markedId = structureId;
|
||||
profile?.setSelectedStructure(structureId);
|
||||
profile?.setSelectedStructure(structureId, true); // 카드가 측점선 주인 — 선 없는 구조물 · 풂은 카드 선 지킴(177-3)
|
||||
},
|
||||
showCard(section) {
|
||||
if (!profile) return;
|
||||
@@ -280,7 +280,7 @@ export function createSectionProfile(
|
||||
// 일반 측점은 측점선 짝 알약이 없어 꺼짐 — 고른 구조물이 이 측점을 덮으면 그 알약을 지킴(53-1)
|
||||
const marked = markedId ? marks.find((entry) => entry.structure_id === markedId) : undefined;
|
||||
if (!pipe && marked && coversChainage(marked, section.chainage_m))
|
||||
profile.setSelectedStructure(markedId);
|
||||
profile.setSelectedStructure(markedId, true);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/* 177-3 횡단 카드 ↔ 종단 측점선 헬퍼 — 진짜 design_profile.ts 의 `setSelectedStation` · `setSelectedStructure`
|
||||
* 본문을 떼어(TS 는 그 자리 트랜스파일) 측점 · 구조물 짝 흉내에 붙이고, B06 카드 고름 차례
|
||||
* (showCard → setSelectedStation · 리스너 → selectMark → setSelectedStructure(mark, true))와 B05 기본 길을 돌려
|
||||
* 남은 측점선 id 를 표준출력 JSON 한 벌로.
|
||||
*/
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript"));
|
||||
|
||||
const ROOT = path.join(__dirname, "..", "..");
|
||||
const src = fs.readFileSync(path.join(ROOT, "A00_Common", "design", "design_profile.ts"), "utf8");
|
||||
const method = (name) => {
|
||||
const pattern = String.raw`\r?\n ${name}\([^\r\n]*\) \{\r?\n[\s\S]*?\r?\n \},`;
|
||||
const match = src.match(new RegExp(pattern));
|
||||
if (!match) throw new Error(`본문 없음: ${name}`);
|
||||
return match[0];
|
||||
};
|
||||
const body = `
|
||||
let selectedStationId = null;
|
||||
let selectedStructureId = null;
|
||||
// 관(pipe-80.17)만 측점선(irr-80)이 있음 — 벽 · 노면공은 선 없음(PST stationIdAtStructure)
|
||||
const structureIdAtStation = (stationId) => (stationId === "irr-80" ? "pipe-80.17" : null);
|
||||
const stationIdAtStructure = (structureId) => (structureId === "pipe-80.17" ? "irr-80" : null);
|
||||
const draw = () => {};
|
||||
module.exports = {
|
||||
line: () => selectedStationId,
|
||||
${method("setSelectedStation")}
|
||||
${method("setSelectedStructure")}
|
||||
};`;
|
||||
const js = ts.transpileModule(body, {
|
||||
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 },
|
||||
}).outputText;
|
||||
const box = { exports: {} };
|
||||
new Function("exports", "module", js)(box.exports, box);
|
||||
const dp = box.exports;
|
||||
|
||||
/** B06 카드 고름 — showCard(카드 · 관 측점이면 관 선) 뒤 리스너가 selectMark(mark) = keepStation true. */
|
||||
const b06Card = (lineId, mark) => {
|
||||
dp.setSelectedStation(lineId);
|
||||
dp.setSelectedStructure(mark, true);
|
||||
return dp.line();
|
||||
};
|
||||
/** B05 목록 고름 — 기본값(keepStation 없음). */
|
||||
const b05Pick = (lineId, structureId) => {
|
||||
dp.setSelectedStation(lineId);
|
||||
dp.setSelectedStructure(structureId);
|
||||
return dp.line();
|
||||
};
|
||||
|
||||
const out = {
|
||||
plainCard: b06Card("s40", null), // 일반 카드 — 덮는 것 없음
|
||||
wallCard: b06Card("s100", "wall"), // 벽(선 없는 구조물) 카드
|
||||
paveCard: b06Card("s140", "pave"), // 노면공 범위 안 카드
|
||||
pipeCard: b06Card("irr-80", "pipe-80.17"), // 관 카드 = 관 선
|
||||
pipeFromPlain: b06Card("s60", "pipe-80.17"), // 관 알약 = 관 선으로 옮김
|
||||
// 반대 길 — 종단 측점선 누름 → 카드 고름 → 같은 리스너(selectMark null)
|
||||
profileClick: b06Card("s200", null),
|
||||
// 카드 풂 = showCard(null) → 선 끔
|
||||
release: (dp.setSelectedStation(null), dp.line()),
|
||||
b05Wall: b05Pick("s100", "wall"), // B05 = 지금 그대로(선 없는 구조물 → 선 끔)
|
||||
b05Pipe: b05Pick("s40", "pipe-80.17"),
|
||||
b05Keep: b05Pick("irr-80", "pipe-80.17"),
|
||||
};
|
||||
process.stdout.write(JSON.stringify(out));
|
||||
@@ -0,0 +1,72 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""177-3 B06 횡단 카드 고름 → 종단 측점 세로선 유지(반대 방향도).
|
||||
|
||||
못박는 것
|
||||
- 카드 고름 뒤 리스너의 selectMark(mark) 가 측점선을 끄지 않음 — 일반 · 벽 · 노면공 카드 = 그 카드 선.
|
||||
- 관 카드 · 관 알약 = 관 측점선 · 카드 풂 = 선 끔.
|
||||
- 종단 측점선 누름(반대 길)도 같은 리스너 — 누른 선 그대로.
|
||||
- B05(keepStation 기본값) = 지금 그대로(선 없는 구조물 → 선 끔).
|
||||
|
||||
Node 헬퍼 `helper_177_3_station_line_keep.cjs` 가 진짜 design_profile.ts 본문을 돌림. 화면은 사용자 확인.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
import pytest
|
||||
|
||||
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||
ROOT = os.path.abspath(os.path.join(HERE, "..", ".."))
|
||||
|
||||
|
||||
def _read(*parts: str) -> str:
|
||||
with open(os.path.join(ROOT, *parts), encoding="utf-8") as handle:
|
||||
return handle.read()
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def out():
|
||||
proc = subprocess.run(
|
||||
["node", os.path.join(HERE, "helper_177_3_station_line_keep.cjs")],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
encoding="utf-8",
|
||||
timeout=60,
|
||||
)
|
||||
assert proc.returncode == 0, proc.stderr
|
||||
return json.loads(proc.stdout)
|
||||
|
||||
|
||||
def test_카드_고름은_그_카드_측점선_유지(out):
|
||||
assert out["plainCard"] == "s40"
|
||||
assert out["wallCard"] == "s100"
|
||||
assert out["paveCard"] == "s140"
|
||||
|
||||
|
||||
def test_관은_관_측점선(out):
|
||||
assert out["pipeCard"] == "irr-80"
|
||||
assert out["pipeFromPlain"] == "irr-80"
|
||||
|
||||
|
||||
def test_반대_길_종단_측점선_누름도_유지(out):
|
||||
assert out["profileClick"] == "s200"
|
||||
assert out["release"] is None
|
||||
|
||||
|
||||
def test_B05_기본_길은_그대로(out):
|
||||
assert out["b05Wall"] is None
|
||||
assert out["b05Pipe"] == "irr-80"
|
||||
assert out["b05Keep"] == "irr-80"
|
||||
|
||||
|
||||
def test_배선():
|
||||
svp = _read("B06_Section", "B06_Section_UI_Section_View_Profile.ts")
|
||||
assert "profile?.setSelectedStructure(structureId, true);" in svp
|
||||
assert "profile.setSelectedStructure(markedId, true);" in svp
|
||||
cross = _read("A00_Common", "design", "design_view_cross.ts")
|
||||
assert "sectionView.selectMark(mark, false);" in cross
|
||||
b05 = _read("A00_Common", "design", "design_view_profile.ts")
|
||||
assert ", true)" not in "".join(
|
||||
line for line in b05.splitlines() if "setSelectedStructure(" in line
|
||||
)
|
||||
Reference in New Issue
Block a user