120 lines
4.2 KiB
JavaScript
120 lines
4.2 KiB
JavaScript
/* 514-1 알약 · 평면 마커 우클릭 「구조물 삭제」(요구 328-1) — `design_pipe_ids.removeMarkOwner` ·
|
|
* `_RouteEdit_StructureMenu` 를 Node 로 돌려 JSON 한 줄(`test_514_1_mark_remove.py` 가 판정).
|
|
* 관 장부 · 메뉴 판 · 마커 집기는 가짜 · 주인 가르기 · 평면 항목 짓기는 진짜.
|
|
* node helper_514_1_mark_remove.cjs
|
|
*/
|
|
const path = require("path");
|
|
const { makeLoader } = require("./helper_ts_stub_loader.cjs");
|
|
|
|
const ROOT = path.join(__dirname, "..", "..");
|
|
const B05 = path.join(ROOT, "B05_Profile");
|
|
const opens = [];
|
|
const calls = [];
|
|
const ui = () => ({
|
|
createMapContextMenu: () => ({
|
|
element: { parentElement: null },
|
|
open: (x, y, items) => opens.push({ x, y, items }),
|
|
close() {},
|
|
contains: () => false,
|
|
}),
|
|
});
|
|
// 평면 마커 = 측점선 없는 대피로 20 m(화면 40 px)
|
|
const MARK = { id: "evac-1", chainageM: 20 };
|
|
const STUBS = {
|
|
"../b_page_state": {
|
|
readState: () => ({ next: 4, ids: [{ id: "pipe-s3", at: 55 }] }),
|
|
writeState() {},
|
|
},
|
|
"./design_selection": {
|
|
PIPE_MATCH_M: 0.51,
|
|
isNear: () => false,
|
|
nearestWithin: () => null,
|
|
readSelection: () => null,
|
|
selectDesign() {},
|
|
},
|
|
common_util_pick_tag: { setPipeTagSource() {} },
|
|
"../A00_Common/touch_bridge": { pickPx: (v) => v },
|
|
"./B05_Profile_UI_IrregularStations": { irregularStationId: (id) => `irr:${id}` },
|
|
"./B05_Profile_Api_Structures": { structureAnchorM: (s) => s.chainage_m ?? 0 },
|
|
"../A00_Common/design/design_selection": { PIPE_MATCH_M: 0.51 },
|
|
"./B05_Profile_UI_RouteEdit_StructureMarks": {
|
|
planMarkAt: (_c, _l, toScreen, px, py) => {
|
|
const [x, y] = toScreen([MARK.chainageM, 0]);
|
|
const distance = Math.hypot(x - px, y - py);
|
|
return distance <= 10 ? { mark: MARK, distance } : null;
|
|
},
|
|
},
|
|
};
|
|
const { loadTs } = makeLoader({ root: ROOT, stubs: STUBS, ui });
|
|
const ids = loadTs(path.join(ROOT, "A00_Common", "design", "design_pipe_ids.ts"));
|
|
ids.usePipeIds("p1");
|
|
const shared = loadTs(path.join(B05, "B05_Profile_UI_Profile_Structures.ts"));
|
|
const plan = loadTs(path.join(B05, "B05_Profile_UI_RouteEdit_StructureMenu.ts"));
|
|
|
|
const out = {};
|
|
// 알약 주인 가르기 — 관 세션 id · 옛 자리 이름 관 = 관 지점 · 그 밖 = 구조물 id
|
|
const remove = {
|
|
pipe: (m) => calls.push(["pipe", m]),
|
|
structure: (id) => calls.push(["structure", id]),
|
|
};
|
|
["pipe-s3", "pipe-12.50", "evac-1", "cross-2"].forEach((id) => ids.removeMarkOwner(id, remove));
|
|
out.owners = calls.splice(0);
|
|
|
|
function fakeElement() {
|
|
const listeners = {};
|
|
return {
|
|
isConnected: true,
|
|
addEventListener: (type, fn) => (listeners[type] = listeners[type] || []).push(fn),
|
|
getBoundingClientRect: () => ({ left: 0, top: 0 }),
|
|
append(child) {
|
|
child.parentElement = this;
|
|
},
|
|
parentElement: null,
|
|
fire(type, clientX, clientY) {
|
|
(listeners[type] || []).forEach((fn) =>
|
|
fn({ clientX, clientY, target: null, preventDefault() {} }),
|
|
);
|
|
},
|
|
};
|
|
}
|
|
// 종단 그래프 = 재료(관 측점 40 m 하나)
|
|
const host = fakeElement();
|
|
shared.mountStructureMenu(host, {
|
|
stations: [{ id: "pipe-1", chainage_m: 40, origin: "pipe" }],
|
|
x: (m) => m * 2,
|
|
chainageAt: (px) => px / 2,
|
|
maxChainageM: 100,
|
|
onRemove: (station) => calls.push(["remove", station.id]),
|
|
onRemoveMark: (id) => calls.push(["removeMark", id]),
|
|
onAddPipe: () => {},
|
|
structureGroups: () => [{ label: "A군", types: [{ type: { name: "배수관", type_id: "pipe" } }] }],
|
|
onAddStructureType: () => {},
|
|
});
|
|
const canvas = fakeElement();
|
|
canvas.parentElement = fakeElement();
|
|
const line = [
|
|
[0, 0],
|
|
[100, 0],
|
|
];
|
|
plan.bindPlanStructureMenu(
|
|
{
|
|
canvas,
|
|
toScreen: (v) => [v[0] * 2, v[1] * 2],
|
|
unrotate: (x, y) => [x, y],
|
|
state: () => ({ plannedLine: line, planned: line }),
|
|
},
|
|
() => -1,
|
|
);
|
|
const planAt = (x, y) => {
|
|
canvas.fire("contextmenu", x, y);
|
|
const items = opens.at(-1).items;
|
|
return items.map((item) => (Array.isArray(item) ? item[0] : item.label));
|
|
};
|
|
out.planMark = planAt(41, 3); // 대피로 마커
|
|
opens.at(-1).items[0][1]();
|
|
out.planPipe = planAt(81, 2); // 관 측점선 = 측점 먼저
|
|
opens.at(-1).items[0][1]();
|
|
out.planEmpty = planAt(140, 2); // 빈 자리 = 추가 메뉴
|
|
out.calls = calls;
|
|
process.stdout.write(JSON.stringify(out));
|