- B05 Drainage_Saved 새 파일 — 저장분 받기를 패널 밖으로 뗌(Panel 700 → 688 줄) · 떠 있는 받기는 같이 씀 · 화면이 마지막 저장분 그대로면 초안 버림은 GET 없이 그 답을 다시 올림 · 뒤이어 온 reload 가 밀어내면 그 답을 기다림(낡음 남지 않음) - 원인 — Ctrl+Z 한 번에 관 자리 되돌림(setPipeChainages) · 시설 따라감(reload) · 묶음 초안 버림(backToSaved) 셋이 저장분을 따로 받음 - 관 자리 되돌림 건너뜀 조건 — 요청 몸통만 견주던 것을 「화면이 저장분 답 그대로」까지 봄(지금 노선 [업데이트] 답이 오른 뒤엔 다시 받음) - 지킴 시험 test_520_7 — 세 부름 = GET 한 번 · 초안 버림 먼저여도 올림 · 저장분 그대로면 GET 없음 · 세션 관 초안은 세부 유역 계산 - 낡은 시험 고침 — test_298 · test_472_d · test_b05_structures_form_summary 가 패널 원문에서 찾던 저장분 받기 줄이 새 파일로 옮겨짐 - 이음매 대조(tmp 일회) — primary-region 길 대 저장 노선 [업데이트] 길 네 프로젝트 도로로 오는 셀 · road_slot · 관별 면적 차이 0 · 초안 2.2~2.3 s · 저장 노선 2.1~2.6 s · Ctrl+Z GET 1 · 낡음 꺼짐 249~258 ms Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
136 lines
5.1 KiB
JavaScript
136 lines
5.1 KiB
JavaScript
/* 520-7 배수유역 저장분 받기 헬퍼 — `B05_Profile_UI_Drainage_Saved.ts` · `_Run.ts` 를 그 자리에서
|
|
* 트랜스파일해 가짜 fetch 로 돌리고 단계별 GET 수 · 「올렸나」를 JSON 으로 냄.
|
|
*/
|
|
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");
|
|
|
|
/* ---- 가짜 저장분 GET(답은 시험이 정할 때) ---- */
|
|
const gets = [];
|
|
let pending = null; // 세션 관 초안
|
|
const detailCalls = [];
|
|
const stubs = {
|
|
"../B04_PreProcess/B04_PreProcess_Api_Fetch": {
|
|
fetchDetailPipePoints: () => new Promise((resolve) => gets.push(resolve)),
|
|
computeDetailBasins: async (_projectId, points) => (
|
|
detailCalls.push(points),
|
|
{ basins: [], pipe_points: points, stale: null }
|
|
),
|
|
},
|
|
"./B05_Profile_Api_Pipes_Draft": { readPendingPipes: () => pending },
|
|
"./B05_Profile_UI_Drainage_Parts": { analyzeFailed: (_error, fallback) => fallback },
|
|
};
|
|
const cache = new Map();
|
|
function 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 local = (name) => {
|
|
if (stubs[name]) return stubs[name];
|
|
if (name.startsWith(".")) return load(path.join(path.dirname(file), `${name}.ts`));
|
|
return require(name);
|
|
};
|
|
new Function("exports", "module", "require", js)(box.exports, box, local);
|
|
return box.exports;
|
|
}
|
|
|
|
const { createSavedLoader } = load(path.join(B05, "B05_Profile_UI_Drainage_Saved.ts"));
|
|
const { createDetailRunner } = load(path.join(B05, "B05_Profile_UI_Drainage_Run.ts"));
|
|
const flush = async () => {
|
|
for (let i = 0; i < 10; i += 1) await new Promise((r) => setImmediate(r));
|
|
};
|
|
const el = () => ({ hidden: false, textContent: "", disabled: false });
|
|
|
|
async function main() {
|
|
const out = {};
|
|
let pipes = [{ chainage_m: 386, source: "stream" }];
|
|
const shown = [];
|
|
let loader;
|
|
const runner = createDetailRunner({
|
|
projectId: () => "p1",
|
|
updateButton: el(),
|
|
status: el(),
|
|
showProgress: () => undefined,
|
|
apply: (response) => (shown.push(response), loader.applied(response)), // 패널 takePipes 와 같은 줄
|
|
basinCount: () => 1,
|
|
scheduleDraw: () => undefined,
|
|
label: (key) => key,
|
|
});
|
|
loader = createSavedLoader(runner, () => pipes);
|
|
const answer = (tag) => ({ tag, basins: [], pipe_points: pipes, stale: null });
|
|
const results = [];
|
|
const keep = (promise) => promise.then((ok) => results.push(ok));
|
|
|
|
// 열 때 — GET 한 번
|
|
keep(loader.run());
|
|
await flush();
|
|
gets[0](answer("saved1"));
|
|
await flush();
|
|
out.open = { gets: gets.length, results: [...results], matches: loader.matches() };
|
|
|
|
// 되돌리기 ① — 관 자리가 노선 따라 옮겨진 뒤(몸통 다름): 관 자리 되돌림 · reload · 초안 버림 한 번에
|
|
pipes = [{ chainage_m: 386.4, source: "stream" }];
|
|
results.length = 0;
|
|
const before = gets.length;
|
|
keep(loader.matches() ? Promise.resolve(true) : loader.run(true)); // setPipeChainages(null)
|
|
keep(loader.run()); // followFacilities → reload()
|
|
keep(loader.back()); // 묶음 초안 버림 → backToSaved
|
|
await flush();
|
|
pipes = [{ chainage_m: 386, source: "stream" }];
|
|
gets[gets.length - 1](answer("saved2"));
|
|
await flush();
|
|
out.undoMoved = { gets: gets.length - before, results: [...results], shown: shown.at(-1).tag };
|
|
|
|
// 되돌리기 ② — 화면이 저장분 그대로 · 초안 버림이 먼저 오고 reload 가 뒤따름
|
|
results.length = 0;
|
|
const before2 = gets.length;
|
|
const shownBefore = shown.length;
|
|
keep(loader.back());
|
|
keep(loader.run());
|
|
await flush();
|
|
gets[gets.length - 1](answer("saved3"));
|
|
await flush();
|
|
out.backThenReload = {
|
|
gets: gets.length - before2,
|
|
results: [...results],
|
|
shown: shown.slice(shownBefore).map((r) => r.tag),
|
|
};
|
|
|
|
// 초안 버림만 — 화면이 저장분 그대로면 GET 없이 그 답을 다시 올림
|
|
results.length = 0;
|
|
const before3 = gets.length;
|
|
keep(loader.back());
|
|
await flush();
|
|
out.backOnly = { gets: gets.length - before3, results: [...results], shown: shown.at(-1).tag };
|
|
|
|
// 다른 답(지금 노선 [업데이트] 등)이 오른 뒤 초안 버림 — 다시 받음
|
|
await runner.run(async () => answer("live"), true);
|
|
results.length = 0;
|
|
const before4 = gets.length;
|
|
keep(loader.back());
|
|
await flush();
|
|
gets[gets.length - 1](answer("saved4"));
|
|
await flush();
|
|
out.afterLive = { gets: gets.length - before4, results: [...results], shown: shown.at(-1).tag };
|
|
|
|
// 세션 관 초안이 있으면 그 관 목록으로(GET 아님)
|
|
pending = [{ chainage_m: 500, source: "user" }];
|
|
const before5 = gets.length;
|
|
results.length = 0;
|
|
keep(loader.run(true));
|
|
await flush();
|
|
out.pending = { gets: gets.length - before5, detail: detailCalls.length, results: [...results] };
|
|
|
|
process.stdout.write(JSON.stringify(out));
|
|
}
|
|
|
|
main().catch((error) => {
|
|
process.stderr.write(String(error && error.stack ? error.stack : error));
|
|
process.exit(1);
|
|
});
|