Files
Aislo/resources/tester/helper_411_b_pipe_id_pairing.mjs
T
eomsangdonandClaude Opus 5.5 274a0f892e fix(B06 측점 열쇠): 옛 자리 관 측점 헛 세션 id 걷음 · 헛 id 정리 (411-E)
- 관 계획을 아는 동안(초안 · 관 주인 있음) 계획에 없는 관 같은 측점 = 옮겨 간 옛 자리 — pipeIdAt 대신 pipeIdNear(안 지음) · 장부에 없으면 at: 열쇠
- 초안 없음 = 옛 갈래 그대로(지음)
- 화면 관 목록 맞춤 때 지금 관 자리 근처에 없는 기록 정리(prunePipeIds)
- 시험 test_411_b 덧붙임(헛 id 0 · 옛 갈래 · 정리)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TteK8mfYZetk5P3bEZkyVZ
2026-10-18 09:59:12 +09:00

184 lines
6.8 KiB
JavaScript

/* 411-B · 411-D 헬퍼 — vite ssr 로 묶은 진짜 모듈(helper_411_b_entry.ts)을 부르고 결과를 JSON 한 벌로.
* node helper_411_b_pipe_id_pairing.mjs <묶음.mjs>
* 사용자 길: 관 p2 를 앞 관 p1 을 지나 옮김(150 → 80) · 노선 따라감이 두 관을 함께 밂.
*/
import { pathToFileURL } from "node:url";
const store = () => {
const m = new Map();
return {
getItem: (k) => (m.has(k) ? m.get(k) : null),
setItem: (k, v) => m.set(k, String(v)),
removeItem: (k) => m.delete(k),
key: (i) => [...m.keys()][i] ?? null,
get length() {
return m.size;
},
clear: () => m.clear(),
};
};
globalThis.window = globalThis;
globalThis.sessionStorage = store();
globalThis.localStorage = store();
const any = new Proxy(function () {}, {
get: (_t, k) => (k === Symbol.toPrimitive ? () => 0 : any),
apply: () => any,
construct: () => any,
});
globalThis.document = any;
globalThis.requestAnimationFrame = (run) => setTimeout(run, 0);
const m = await import(pathToFileURL(process.argv[2]).href);
const out = {};
const P = "p411";
m.usePipeIds(P);
/* 1. 알림 목록 ↔ 가게 관 초안 짝 = id — 옮겨 차례가 뒤바뀌어도 그 관 */
const reports = [
{ id: "p10000", chainage_m: 100, facility: "pipe" },
{ id: "p15000", chainage_m: 150, facility: "pipe", start_m: 145, end_m: 155 },
];
const draft = [
{ id: "p15000", chainage_m: 80 },
{ id: "p10000", chainage_m: 100 },
];
out.reports = m
.followPipeReports(reports, draft)
.map((r) => [r.id, r.chainage_m, r.start_m ?? null]);
/* 2. 세션 id 장부 — 끌어 옮김(followMovedPipe 길) · 그 사이 옛 측점 열쇠가 옛 자리에 헛 id 를 지음 →
* 화면 목록 맞춤(shownPipes = 관 고정 id 가 쥔 세션 id 를 새 자리로 · placePipeIds) */
const idA = m.pipeIdAt(100, P);
const idB = m.pipeIdAt(150, P);
const sessionIds = new Map([
["p10000", idA],
["p15000", idB],
]);
m.movePipeId(150, 80, P); // 끌기 = 옮긴 관 id 그대로
const stray = m.pipeIdAt(150, P); // 옛 측점 열쇠가 옛 자리를 물음
const place = (shown, project) =>
m.placePipeIds(
shown.map((r) => [sessionIds.get(r.id), r.chainage_m]),
project,
);
place(m.followPipeReports(reports, draft), P);
out.ids = { idA, idB, stray, at80: m.pipeIdAt(80, P), at100: m.pipeIdAt(100, P) };
/* 2-1. 되돌림 — 관이 옛 자리로 돌아감 · 그 자리에 헛 id 가 먼저 있어도 그 관 id(헛 기록은 뺌) */
place(
[
{ id: "p15000", chainage_m: 150 },
{ id: "p10000", chainage_m: 100 },
],
P,
);
out.back = { at150: m.pipeIdAt(150, P), strayAt: m.pipeChainageOf(stray, P) };
/* 3. 노선 따라감이 두 관을 함께 밂(앞 관이 뒤 관 옛 자리로) — 기록 안 잃음 · 헛 id 안 생김 */
const Q = "q411";
const q1 = m.pipeIdAt(100, Q);
const q2 = m.pipeIdAt(103, Q);
m.placePipeIds(
[
[q1, 103],
[q2, 106],
],
Q,
);
out.batch = {
q1,
q2,
at103: m.pipeIdAt(103, Q),
at106: m.pipeIdAt(106, Q),
next: m.pipeIdAt(500, Q),
};
/* 4. 알약 따라감 — 알약이 이미 따라간 자리면 같은 자리 짝(차례 뒤바뀜에도 그 관) */
const marks = [
{ structure_id: idB, chainage_m: 80 },
{ structure_id: idA, chainage_m: 100 },
{ structure_id: "st-1", chainage_m: 40 },
];
out.marks = m
.followedMarks(marks, [{ structure_id: "st-1", chainage_m: 42 }], draft)
.map((mk) => [mk.structure_id, mk.chainage_m]);
/* 5. 배수 편집기 — 따라간 관 자리(id 짝)를 받음 · 시설 속성 · 고름도 따라감 */
const editor = m.createPipeEditor(() => {});
editor.setPipes([
{ chainage_m: 100, reason: "stream", id: "p10000" },
{ chainage_m: 150, reason: "confirmed", id: "p15000" },
]);
editor.select(1);
const facilities = m.createFacilityStore();
facilities.set(150, { facility: "ford", options: { 월류높이: 0.3 } });
m.followEditorPipes(editor, facilities, [
{ id: "p10000", chainage_m: 103 },
{ id: "p15000", chainage_m: 98 },
]);
out.editor = {
pipes: editor.pipes().map((p) => [p.id, p.chainage_m, p.reason]),
selected: editor.pipes()[editor.selected()]?.id ?? null,
ford98: facilities.get(98)?.facility ?? null,
at150: facilities.get(150),
};
m.followEditorPipes(editor, facilities, [{ id: "p10000", chainage_m: 103 }]); // 같은 값 = 그대로
out.editorSame = editor.pipes().map((p) => p.chainage_m);
/* 5-1. 막 놓은 관 — 초안엔 id 없음 · 편집기는 서버 id(재계산 응답) → id 없는 것끼리 차례 짝 */
const fresh = m.createPipeEditor(() => {});
fresh.setPipes([
{ chainage_m: 120, reason: "confirmed", id: "p12000" },
{ chainage_m: 351, reason: "stream", id: "p35100" },
]);
m.followEditorPipes(fresh, m.createFacilityStore(), [
{ chainage_m: 120 },
{ id: "p35100", chainage_m: 353 },
]);
const fresh2 = m.createPipeEditor(() => {});
fresh2.setPipes([
{ chainage_m: 200, reason: "confirmed", id: "p20000" },
{ chainage_m: 351, reason: "stream", id: "p35100" },
]);
m.followEditorPipes(fresh2, m.createFacilityStore(), [
{ chainage_m: 204 },
{ id: "p35100", chainage_m: 353 },
]);
out.fresh = [fresh.pipes(), fresh2.pipes()].map((list) => list.map((p) => [p.id, p.chainage_m]));
/* 6. B06 측점 열쇠 — 서버 관 id 도 관(계산 묶음 `pipe:` 와 같음) */
const planned = [
{ chainage_m: 80.17, owners: ["p8017"], role: "anchor" },
{ chainage_m: 52.5, owners: ["st-1"], role: "anchor" },
];
const sections = [
{ chainage_m: 52.5, kind: "irregular" },
{ chainage_m: 80.17, kind: "irregular" },
];
m.useStationOwners(P, planned, [{ id: "p8017", chainage_m: 80.17 }]);
out.keys = m.stationKeysOf(P, sections, 20).map((k) => k.key);
m.useStationOwners(P, planned);
out.keysNoPipes = m.stationKeysOf(P, sections, 20).map((k) => k.key);
out.pipelineKey = m.pipelineStationKey("pipe", "p8017");
/* 7. 411-E — 관 계획을 아는 동안 옛 자리 관 측점(옮겨 간 자리)은 세션 id 를 안 지음 · 헛 id 정리 */
const E = "e411";
m.usePipeIds(E);
const e1 = m.pipeIdAt(80, E); // 옮긴 관(새 자리)
const bookSize = () => JSON.parse(sessionStorage.getItem(`aislo:draft:pipe-ids:${E}`)).ids.length;
m.useStationOwners(E, [{ chainage_m: 80, owners: ["p15000"], role: "anchor" }], [{ id: "p15000" }]);
const staleSections = [
{ chainage_m: 80, kind: "irregular", structure: "파형강관 D800", culvert: {} },
{ chainage_m: 150, kind: "irregular", structure: "파형강관 D800", culvert: {} }, // 옛 자리
];
out.staleKeys = m.stationKeysOf(E, staleSections, 20).map((k) => k.key);
out.staleBook = bookSize();
m.useStationOwners(E, []); // 관 계획 모름(초안 없음) = 옛 갈래 그대로 지음
out.legacyKey = m.stationKeysOf(E, [staleSections[1]], 20)[0].key;
out.legacyBook = bookSize();
m.prunePipeIds([80], E); // 지금 관 자리만 남김
out.pruned = { size: bookSize(), at80: m.pipeIdAt(80, E), e1 };
m.usePipeIds(P);
process.stdout.write(JSON.stringify(out));