- 부품 상자 common_util_structure_parts.json(갈래마다 부품 · 읽는 칸 · 자리꼴 · 정본 · 42종 처음값) · 표 읽기 common_util_structure_catalog.ts / .py 짝(정의 반영 ⊕ 처음값 ⊕ 부품 끔) · 거울 시험 test_322_1_catalog_mirror - 목록: pickGroups 군 차례 = 구조물군 열쇠 · 페이지 거르기 listPick(B05 both · B06 both + b06) · HIDDEN_PICK_GROUPS · HIDDEN_PICK_TYPES · pickable 걷음(옛 대피 셋 asRoad 그대로) - 측점: structureStationMarks · pipeStationMarks · is_station_planting_type · resolve_extra_stations = 표 횡단도(anchor · span3 · none) - 카드 이름: cardTitle / card_title 한 공식(빈칸 = 그 종류 정의 기본값) · 표시 이름이 정의 관종도 앎 - 형상: 벽 = shape wall(형태 = 형상칸.form · 물빼기 = 형상칸.weep) · 포장 = shape pavement(「사용 중」 거르기 없앰) · 맹암거 · 사토 · 관 지점 시설 세트 = shape - 3D 몸체 = 그림 자료 주인 종류의 표 3D 부품 · 알약 띠 = 표 자리꼴 구간(관 지점 시설은 알약만) - ★1 노출형 · 개거 횡단도 none · ★2 쇄석 화면에서도 포장층 · ★3 기슭막이 표 자리꼴 interval(정의 파일 그대로) · ★4 코드 숨김 10종 list hidden · ★5 관 빈칸 D800 → 정의 기본 D1000 - 옛 시험: 도움 파일 로더 27개가 표 모듈 공용 한 벌(helper_322_catalog_module) 씀 · 기대값 고침(272_1 · b05_extra_stations · roundtrip · 314 · 52_7 · walls 거울 · wall_drain_pipe) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ji4nuyLVHcxrXWHTdb5nRD
184 lines
6.1 KiB
JavaScript
184 lines
6.1 KiB
JavaScript
/* 313 [구조물 전체 삭제] 헬퍼 — 진짜 TS(목록 그리기 · 입력 배선)를 Node 로 돌려 표준출력 JSON 한 벌로.
|
|
* 확인창(@ui showConfirmDialog)은 답을 정해 둔 가짜로 막음.
|
|
*/
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript"));
|
|
const CATALOG = require("./helper_322_catalog_module.cjs"); // 구조물 표(322-1)
|
|
|
|
const ROOT = path.join(__dirname, "..", "..");
|
|
const cache = new Map();
|
|
const confirms = [];
|
|
let answer = true;
|
|
const UI = {
|
|
showConfirmDialog: async (message, ok) => {
|
|
confirms.push([message, ok]);
|
|
return answer;
|
|
},
|
|
showToast: () => {},
|
|
};
|
|
const load = (file) => {
|
|
if (cache.has(file)) return cache.get(file);
|
|
const js = ts.transpileModule(fs.readFileSync(file, "utf8"), {
|
|
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 },
|
|
}).outputText;
|
|
const box = { exports: {} };
|
|
cache.set(file, box.exports);
|
|
const near = (m) => {
|
|
if (CATALOG.isCatalogRequest(m)) return CATALOG;
|
|
if (m.startsWith("@ui/")) return UI;
|
|
if (m.startsWith("@config/")) return load(path.join(ROOT, "config", `${m.slice(8)}.ts`));
|
|
if (m.startsWith("@util/")) return load(path.join(ROOT, "common_util", `${m.slice(6)}.ts`));
|
|
if (m.endsWith(".json")) return require(path.join(path.dirname(file), m));
|
|
if (m.startsWith(".")) return load(path.join(path.dirname(file), `${m}.ts`));
|
|
return new Proxy({}, { get: () => () => {} });
|
|
};
|
|
new Function("exports", "module", "require", js)(box.exports, box, near);
|
|
return box.exports;
|
|
};
|
|
|
|
// DOM 흉내 — 목록이 쓰는 것만
|
|
class Node {
|
|
constructor(tag) {
|
|
this.tag = tag;
|
|
this.children = [];
|
|
this.className = "";
|
|
this.textContent = "";
|
|
this.style = { setProperty() {} };
|
|
this.listeners = {};
|
|
this.title = "";
|
|
}
|
|
get classList() {
|
|
const names = () => this.className.split(" ").filter(Boolean);
|
|
return {
|
|
add: (c) => (this.className = [...names(), c].join(" ")),
|
|
toggle: (c, on) => {
|
|
const rest = names().filter((n) => n !== c);
|
|
this.className = (on ? [...rest, c] : rest).join(" ");
|
|
},
|
|
contains: (c) => names().includes(c),
|
|
};
|
|
}
|
|
append(...kids) {
|
|
this.children.push(...kids);
|
|
}
|
|
replaceChildren(...kids) {
|
|
this.children = [...kids];
|
|
}
|
|
addEventListener(type, fn) {
|
|
this.listeners[type] = fn;
|
|
}
|
|
scrollIntoView() {}
|
|
}
|
|
globalThis.document = { createElement: (tag) => new Node(tag), activeElement: null };
|
|
globalThis.requestAnimationFrame = (fn) => fn();
|
|
const memory = new Map();
|
|
globalThis.window = {
|
|
sessionStorage: {
|
|
getItem: (k) => memory.get(k) ?? null,
|
|
setItem: (k, v) => memory.set(k, String(v)),
|
|
removeItem: (k) => memory.delete(k),
|
|
},
|
|
requestAnimationFrame: (fn) => fn(),
|
|
};
|
|
globalThis.sessionStorage = globalThis.window.sessionStorage;
|
|
|
|
const B05 = (f) => load(path.join(ROOT, "B05_Profile", `${f}.ts`));
|
|
const { renderStructureList } = B05("B05_Profile_UI_Structures_List");
|
|
const { bindStructuresEvents } = B05("B05_Profile_UI_Structures_Panel_Events");
|
|
|
|
const typeMap = new Map([
|
|
["sign", { type_id: "sign", name: "표지", group: "E" }],
|
|
["pipe", { type_id: "pipe", name: "배수관", group: "A" }],
|
|
]);
|
|
const sign = { structure_id: "s1", type_id: "sign", placement: "point", chainage_m: 40 };
|
|
const pipe = { chainage_m: 80, facility: "pipe", source: "auto" };
|
|
const draw = (structures, pipes, withClear = true) => {
|
|
const list = new Node("ul");
|
|
let cleared = 0;
|
|
renderStructureList({
|
|
list,
|
|
structures,
|
|
pipeFacilities: pipes,
|
|
typeMap,
|
|
intervalM: 20,
|
|
editingId: null,
|
|
selectedPipeChainage: null,
|
|
onSelectStructure: () => {},
|
|
onSelectPipe: () => {},
|
|
...(withClear ? { onClearAll: () => (cleared += 1) } : {}),
|
|
});
|
|
const last = list.children.at(-1);
|
|
const button = last?.children?.[0];
|
|
const clear = last?.className === "b05-route__irregular-clear";
|
|
if (clear) button.listeners.click();
|
|
return {
|
|
rows: list.children.length,
|
|
lastClass: last?.className ?? null,
|
|
button: clear
|
|
? { text: button.textContent, className: button.className, type: button.type }
|
|
: null,
|
|
cleared,
|
|
};
|
|
};
|
|
const listCases = {
|
|
filled: draw([sign], [pipe]),
|
|
empty: draw([], []),
|
|
noHandler: draw([sign], [pipe], false),
|
|
};
|
|
|
|
// 입력 배선 — 가짜 ctx(누름 듣개는 담기만)
|
|
const el = () => new Node("div");
|
|
const makeCtx = (structures, pipes) => {
|
|
const calls = { reset: 0, release: 0, removed: [], emit: 0 };
|
|
let pipeList = pipes.map((p) => ({ ...p }));
|
|
const ctx = {
|
|
groupSelect: el(),
|
|
typeSelect: el(),
|
|
primary: el(),
|
|
removeButton: el(),
|
|
resetButton: el(),
|
|
positionRow: el(),
|
|
memoField: el(),
|
|
optionRow: el(),
|
|
optionInputs: [],
|
|
anchorFields: { station: el(), remainder: el() },
|
|
startFields: { station: el(), remainder: el() },
|
|
endFields: { station: el(), remainder: el() },
|
|
facilityOptions: { root: el() },
|
|
structures,
|
|
pipeFacilities: () => pipeList,
|
|
projectId: "p",
|
|
callbacks: {
|
|
onListRelease: () => (calls.release += 1),
|
|
onPipeRemove: (at) => {
|
|
calls.removed.push(at);
|
|
pipeList = pipeList.filter((p) => p.chainage_m !== at); // 하나씩 빼기 길이 목록을 갈아 끼움
|
|
},
|
|
},
|
|
resetForm: () => (calls.reset += 1),
|
|
emit: () => (calls.emit += 1),
|
|
};
|
|
return { ctx, calls, left: () => structures.length + pipeList.length };
|
|
};
|
|
const runClear = async (structures, pipes, ok) => {
|
|
answer = ok;
|
|
confirms.length = 0;
|
|
const { ctx, calls, left } = makeCtx(structures, pipes);
|
|
const { clearAll } = bindStructuresEvents(ctx);
|
|
await clearAll();
|
|
return { confirms: [...confirms], calls, left: left() };
|
|
};
|
|
|
|
(async () => {
|
|
const pipes = [pipe, { chainage_m: 160.37, facility: "ford_pavement", source: "user" }];
|
|
const result = {
|
|
listCases,
|
|
confirmed: await runClear([{ ...sign }, { ...sign, structure_id: "s2" }], pipes, true),
|
|
cancelled: await runClear([{ ...sign }], pipes, false),
|
|
pipesOnly: await runClear([], [pipe], true),
|
|
nothing: await runClear([], [], true),
|
|
};
|
|
process.stdout.write(JSON.stringify(result));
|
|
})();
|