- 서버 POST drainage/pipe-proposals(아무것도 안 씀) · propose_pipes(common_util_stream_crossing) · claim_crossings = {교차점: 라벨} 짝
- 라벨 왕복 — 계산 carry 가 화면 라벨 실음 · 관 속성 보관소가 응답 · 초안 · 요청에 라벨 실어 나름 · 옵션 고침에도 남김
- 지운 관을 다시 넣으면 지움 표지 걷음(keep_labels)
- 계산 등록부 D2 runner = propose_pipes · 시험 test_510 · 349 낡은 두 방식 기대 고침
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
99 lines
3.2 KiB
JavaScript
99 lines
3.2 KiB
JavaScript
/* 510-1 [자동 제안] 후보 목록 — 진짜 `B05_Profile_UI_Drainage_Propose.ts` · 관 속성 보관소를 가짜 DOM · fetch 로.
|
|
* node helper_510_propose.cjs (짝 = `test_510_auto_pipe_propose.py`) */
|
|
const path = require("path");
|
|
const { makeLoader } = require("./helper_ts_stub_loader.cjs");
|
|
|
|
const ROOT = path.join(__dirname, "..", "..");
|
|
|
|
/* ---- 가짜 DOM(쓰는 것만) ---- */
|
|
function el(tag) {
|
|
const listeners = {};
|
|
const node = {
|
|
tag,
|
|
children: [],
|
|
hidden: false,
|
|
disabled: false,
|
|
checked: false,
|
|
textContent: "",
|
|
append(...items) {
|
|
items.forEach((item) =>
|
|
node.children.push(typeof item === "string" ? { text: item } : item),
|
|
);
|
|
},
|
|
replaceChildren(...items) {
|
|
node.children = [];
|
|
node.append(...items);
|
|
},
|
|
addEventListener(type, fn) {
|
|
(listeners[type] ??= []).push(fn);
|
|
},
|
|
fire(type) {
|
|
(listeners[type] ?? []).forEach((fn) => fn());
|
|
},
|
|
};
|
|
return node;
|
|
}
|
|
globalThis.document = { createElement: el };
|
|
|
|
const sent = [];
|
|
globalThis.fetch = async (url, init) => {
|
|
sent.push({ url, body: JSON.parse(init.body) });
|
|
return {
|
|
ok: true,
|
|
json: async () => ({
|
|
spacing: true,
|
|
proposals: [
|
|
{ chainage_m: 50, kind: "stream", state: "dismissed", stream_label: { stream: "S1", order: 1 } },
|
|
{ chainage_m: 150, kind: "stream", state: "held", stream_label: { stream: "S2", order: 1 } },
|
|
{
|
|
chainage_m: 320,
|
|
kind: "stream",
|
|
state: "new",
|
|
stream_label: { stream: "S4", order: 1 },
|
|
stream_name: "작은골",
|
|
},
|
|
{ chainage_m: 420, kind: "spacing", state: "new" },
|
|
],
|
|
}),
|
|
};
|
|
};
|
|
|
|
const { load } = makeLoader({ root: ROOT });
|
|
const { createDrainagePropose } = load("B05_Profile", "B05_Profile_UI_Drainage_Propose.ts");
|
|
const { createFacilityStore } = load("B05_Profile", "B05_Profile_UI_Drainage_Facility.ts");
|
|
|
|
(async () => {
|
|
const added = [];
|
|
const propose = createDrainagePropose({
|
|
projectId: () => "p1",
|
|
pipeRequest: () => [{ chainage_m: 150, source: "user" }],
|
|
addPipes: (picks) =>
|
|
picks.forEach((item) => added.push([item.chainage_m, item.stream_label?.stream ?? null])),
|
|
redraw: () => undefined,
|
|
});
|
|
await propose.open();
|
|
const [head, list] = propose.root.children;
|
|
const [title, add] = head.children;
|
|
const boxes = list.children.map((row) => row.children[0].children[0]);
|
|
const out = {
|
|
sent: { url: sent[0].url, points: sent[0].body.points.length },
|
|
rows: list.children.map((row) => row.children[0].children[1].text.trim()),
|
|
title: title.textContent,
|
|
addOff: add.disabled,
|
|
candidates: propose.candidates(),
|
|
};
|
|
boxes[1].checked = true;
|
|
boxes[1].fire("change");
|
|
boxes[2].checked = true;
|
|
boxes[2].fire("change");
|
|
add.fire("click");
|
|
out.added = added;
|
|
out.afterClose = { hidden: propose.root.hidden, candidates: propose.candidates() };
|
|
|
|
// 관 속성 보관소 — 응답 라벨이 다음 요청에 실림(라벨만 있는 맨 배관도 보관)
|
|
const store = createFacilityStore();
|
|
store.replaceFromResponse([{ chainage_m: 320, stream_label: { stream: "S4", order: 1 } }]);
|
|
out.carried = store.attach([{ chainage_m: 320, source: "user" }])[0].stream_label ?? null;
|
|
console.log(JSON.stringify(out));
|
|
})();
|