- 평면 고름 이름 PLAN_PICK_FROM 을 design_pick_escape 로 옮김(Cross · 마커가 같이 씀) - 종단 고름 구독 = Esc 처럼 b05-plan 풂(값 없음)이면 폼 닫음 · 패널 접힘 · 펼침 그대로 · 오른쪽 판 그대로 - 시험 409 에 409-2 더함(새 helper_409_2) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XWh5wNNycMkbwMpACz1rte
161 lines
6.2 KiB
JavaScript
161 lines
6.2 KiB
JavaScript
/* 411-A B05 평면 오른쪽 횡단 판 — 구조물 · 관을 골라도 그 측점 횡단 · 옮긴 뒤에도 열쇠로 따라감.
|
|
* `_RouteEdit_Cross` 를 Node 로 돌려 JSON 한 줄(`test_411_a_cross_structure.py` 가 판정). 묶음 · 그림 · 가게는 가짜 ·
|
|
* 고름 구독 · 측점 짚기 · 판 채우기는 진짜.
|
|
* node helper_411_a_cross_structure.cjs
|
|
*/
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript"));
|
|
|
|
const B05 = path.join(__dirname, "..", "..", "B05_Profile");
|
|
const out = {};
|
|
|
|
/* 가짜 DOM — 판(제목 · 상자 · 발) 글만 봄 */
|
|
function fakeElement() {
|
|
const parts = new Map();
|
|
const element = {
|
|
textContent: "",
|
|
children: [],
|
|
isConnected: true,
|
|
clientHeight: 150,
|
|
setAttribute() {},
|
|
append: (...items) => element.children.push(...items),
|
|
replaceChildren: (...items) => (element.children = items),
|
|
getBoundingClientRect: () => ({ width: 240, height: 150 }),
|
|
querySelector: (selector) => {
|
|
if (!parts.has(selector)) parts.set(selector, fakeElement());
|
|
return parts.get(selector);
|
|
},
|
|
};
|
|
return element;
|
|
}
|
|
global.document = { createElement: fakeElement };
|
|
global.ResizeObserver = class {
|
|
observe() {}
|
|
disconnect() {}
|
|
};
|
|
|
|
let listener = null;
|
|
let stations = [];
|
|
const route = { id: 1 };
|
|
const subscribers = [];
|
|
const pipe = {
|
|
output: (stage) => (stage === "ground" ? { stations } : {}),
|
|
input: () => route,
|
|
subscribe: (fn) => (subscribers.push(fn), () => {}),
|
|
};
|
|
const crossStage = () => subscribers.forEach((fn) => fn({ kind: "stage", stage: "cross" }));
|
|
|
|
const STUBS = {
|
|
"../A00_Common/b_svg_zoom_pan": { attachSvgZoomPan() {} },
|
|
"../A00_Common/design/design_pipeline_page": { pagePipeline: () => pipe },
|
|
"../A00_Common/design/design_selection": {
|
|
nearestWithin: (items, at, of) => {
|
|
let best;
|
|
let gap = 0.51;
|
|
for (const item of items)
|
|
if (Math.abs(of(item) - at) < gap) [best, gap] = [item, Math.abs(of(item) - at)];
|
|
return best;
|
|
},
|
|
selectDesign() {},
|
|
subscribeSelection: (_projectId, fn) => ((listener = fn), () => {}),
|
|
},
|
|
"../A00_Common/design/design_pick_escape": { PLAN_PICK_FROM: "b05-plan" },
|
|
"../A00_Common/design/design_store": {
|
|
useDesignStore: () => ({ subscribe: () => () => {}, get: () => null }),
|
|
},
|
|
"./logic/B05_Profile_Pipeline_Detail": {
|
|
stationSection: (station) => ({ chainage_m: station.chainageM, samples: [] }),
|
|
},
|
|
"./B05_Profile_UI_RouteEdit_Cross_Draw": {
|
|
buildCrossSvg: () => ({ svg: fakeElement(), layer: null, width: 240, height: 150 }),
|
|
CROSS_PLOT_PAD: 0,
|
|
summarizeCross: (preview) => `횡단 ${preview.chainage_m}`,
|
|
},
|
|
"../A00_Common/b_page_state": { readStateRaw: () => null },
|
|
"../A00_Common/design/design_page_route": { pageRouteId: () => null },
|
|
"../common_util/common_util_station": { stationLabel: (chainageM) => String(chainageM) },
|
|
"./B05_Profile_UI_RouteEdit_Chrome": { sidePanelsOf: new Map() },
|
|
"./B05_Profile_UI_RouteEdit_Cross_Card": {
|
|
routeCrossCard: () => fakeElement(),
|
|
routeCrossSource: () => null,
|
|
},
|
|
};
|
|
const cache = new Map();
|
|
function loadTs(full) {
|
|
if (cache.has(full)) return cache.get(full);
|
|
const js = ts.transpileModule(fs.readFileSync(full, "utf8"), {
|
|
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 },
|
|
}).outputText;
|
|
const box = { exports: {} };
|
|
cache.set(full, box.exports);
|
|
const localRequire = (request) => {
|
|
if (STUBS[request]) return STUBS[request];
|
|
if (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`));
|
|
return require(request);
|
|
};
|
|
new Function("exports", "module", "require", js)(box.exports, box, localRequire);
|
|
cache.set(full, box.exports);
|
|
return box.exports;
|
|
}
|
|
|
|
const cross = loadTs(path.join(B05, "B05_Profile_UI_RouteEdit_Cross.ts"));
|
|
const station = (key, chainageM, kind, id = null) => ({ key, chainageM, kind, id });
|
|
const grid = [
|
|
station("end:BP", 0, "end"),
|
|
station("grid:1", 20, "grid"),
|
|
station("grid:2", 40, "grid"),
|
|
];
|
|
const side = fakeElement();
|
|
const preview = cross.createCrossPreview({
|
|
projectId: "p1",
|
|
side,
|
|
request: () => ({ vertices: [], min_radius_m: 15, station_interval_m: 20 }),
|
|
});
|
|
const [current] = side.children;
|
|
const shownNow = () => ({
|
|
station: current.querySelector(".b05-routeedit__cross-station").textContent,
|
|
foot: current.querySelector(".b05-routeedit__cross-foot").textContent,
|
|
});
|
|
const pick = (chainageM, structureId, from) => listener({ chainageM, structureId }, from);
|
|
|
|
// ① 구조물 고름(id) = 그 측점 횡단 · 법선은 마커 몫(structure)
|
|
stations = [
|
|
...grid,
|
|
station("structure:A", 45, "structure", "A"),
|
|
station("pipe:p1", 80.17, "pipe", "p1"),
|
|
];
|
|
pick(45, "A", "b05");
|
|
out.structurePick = { ...shownNow(), structure: preview.watched()?.structure ?? null };
|
|
// ② 옮김 — 묶음이 새 자리로(같은 열쇠) · cross 차례 = 새 자리 횡단(고름은 옛 45 그대로)
|
|
stations = [
|
|
...grid,
|
|
station("structure:A", 52, "structure", "A"),
|
|
station("pipe:p1", 80.17, "pipe", "p1"),
|
|
];
|
|
crossStage();
|
|
out.structureMoved = { ...shownNow(), at: preview.watched()?.chainageM ?? null };
|
|
// ③ 관 고름(누가거리만) = 그 측점 횡단
|
|
pick(80.17, null, "b05");
|
|
out.pipePick = { ...shownNow(), structure: preview.watched()?.structure ?? null };
|
|
// ④ 평면 마커 고름 풂(b05-plan) = 판 그대로
|
|
pick(null, null, "b05-plan");
|
|
out.planRelease = shownNow();
|
|
// ⑤ 일반측점 고름 = 그 측점 횡단 · 법선(structure 없음)
|
|
pick(20, null, "b05");
|
|
out.gridPick = { ...shownNow(), structure: preview.watched()?.structure ?? null };
|
|
// ⑥ 묶음 전 구조물 고름 — 열쇠 없이 기다렸다 묶음 뒤 열쇠로 붙듦 · 그 뒤 옮김도 따라감
|
|
stations = [];
|
|
pick(60, "B", "b05");
|
|
out.beforePipeline = shownNow();
|
|
stations = [...grid, station("structure:B", 60, "structure", "B")];
|
|
crossStage();
|
|
out.afterPipeline = shownNow();
|
|
stations = [...grid, station("structure:B", 66, "structure", "B")];
|
|
crossStage();
|
|
out.latchedMoved = shownNow();
|
|
// ⑦ 다른 보기가 풂(null · b05) = 판 비움(382-2 그대로)
|
|
pick(null, null, "b05");
|
|
out.otherRelease = { ...shownNow(), watched: preview.watched() };
|
|
console.log(JSON.stringify(out));
|