- design_pipeline_page follow 되살림 차례 = 계획고 사진 + 가게 관 · 구조물 · 추가 측점(묶음 측점 유령 · 빠짐 없앰) - Section_Store 가 노선 초안 동안 상세 틀을 정해 넘김 · Drafts = 옛 틀이면 저장분으로 맞춤 · 얹음 · 새 틀이면 저장분 종류 대조 안 함 - 새 시험 test_280_3_route_undo_facilities(헬퍼 둘 · 검증_sub4 읽기만) · 옛 코드에서 되돌리기 넷 실패 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
193 lines
7.0 KiB
JavaScript
193 lines
7.0 KiB
JavaScript
/* 요구 280-3 원인 3 헬퍼 — 노선 초안 동안 초안 측점 맞춤(`withDraftStations` · `withDraftShapes`)이 상세의 틀을 앎.
|
|
* old = 옛 노선 틀 상세(저장 정본 · 새로고침 첫 화면) → 새 틀 초안 대신 저장분으로 · new = 묶음이 갈아끼운 새 틀 →
|
|
* 저장분(옛 틀) 종류와 같은 m 로 견주지 않음 · null = 옛 동작(대조). 진짜 TS: Drafts · 측점 계획 · 형상 얹기 · 표.
|
|
* 결과 = 표준출력 JSON. 짝 = `test_280_3_route_undo_facilities.py`. */
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
const ROOT = path.join(__dirname, "..", "..");
|
|
const ts = require(path.join(ROOT, "config", "node_modules", "typescript"));
|
|
const CATALOG = require("./helper_322_catalog_module.cjs");
|
|
|
|
const S = {
|
|
savedPipes: [],
|
|
savedStructures: [],
|
|
draftPipes: null,
|
|
draftStructures: null,
|
|
types: [],
|
|
};
|
|
const STUBS = {
|
|
design_page_data: {
|
|
forgetPageData: () => {},
|
|
pagePipes: async () => ({ pipe_points: S.savedPipes }),
|
|
pageStructures: async () => ({ structures: S.savedStructures }),
|
|
},
|
|
B05_Profile_Api_Structures: {
|
|
fetchStructureTypes: async () => S.types,
|
|
readPendingStructures: () => S.draftStructures,
|
|
},
|
|
B05_Profile_Api_Pipes_Draft: { readPendingPipes: () => S.draftPipes },
|
|
B05_Profile_Api_PlusStations: { readPlusDraft: () => null },
|
|
B06_Section_Station_Keys: { useStationKeys: () => {}, useStationOwners: () => {} },
|
|
ui_template_elements: { showToast: () => {} },
|
|
};
|
|
const cache = new Map();
|
|
function resolveTs(base) {
|
|
for (const c of [`${base}.ts`, base]) if (fs.existsSync(c) && fs.statSync(c).isFile()) return c;
|
|
throw new Error(`없음: ${base}`);
|
|
}
|
|
function load(full) {
|
|
if (cache.has(full)) return cache.get(full).exports;
|
|
const js = ts.transpileModule(fs.readFileSync(full, "utf8"), {
|
|
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 },
|
|
}).outputText;
|
|
const box = { exports: {} };
|
|
cache.set(full, box);
|
|
const req = (r0) => {
|
|
if (CATALOG.isCatalogRequest(r0)) return CATALOG;
|
|
const r = r0.replace(/\.js$/, "");
|
|
const stub = STUBS[r.split("/").pop()];
|
|
if (stub) return stub;
|
|
if (r.endsWith(".json"))
|
|
return JSON.parse(fs.readFileSync(path.join(path.dirname(full), r), "utf8"));
|
|
if (r.startsWith("@util/")) return load(resolveTs(path.join(ROOT, "common_util", r.slice(6))));
|
|
if (r.startsWith("@ui/")) return STUBS[r.split("/").pop()] ?? {};
|
|
if (r.startsWith(".")) return load(resolveTs(path.join(path.dirname(full), r)));
|
|
return require(r);
|
|
};
|
|
new Function("exports", "module", "require", js)(box.exports, box, req);
|
|
return box.exports;
|
|
}
|
|
const P = (...a) => path.join(ROOT, ...a);
|
|
const D = load(P("B06_Section", "B06_Section_Section_Drafts.ts"));
|
|
const def = JSON.parse(
|
|
fs.readFileSync(P("resources", "master_template", "구조물정의.json"), "utf8"),
|
|
);
|
|
S.types = def.types.map((t) => ({
|
|
type_id: t.type_id,
|
|
group: t.group,
|
|
placement: t.placement,
|
|
managed_by: t.managed_by,
|
|
name: t.name,
|
|
options: (t.options || []).map((o) => ({ key: o.key, label: o.label, default: o.default })),
|
|
}));
|
|
|
|
const sec = (m, kind, extra = {}) => ({
|
|
station_id: `station_${String(Math.round(m * 1000)).padStart(12, "0")}`,
|
|
chainage_m: m,
|
|
label: "",
|
|
kind,
|
|
center_x: m,
|
|
center_y: 0,
|
|
center_z: 100,
|
|
frame: { left_xy: [0, 1] },
|
|
samples: [{ offset_m: 0, elevation_m: 100, valid: true }],
|
|
design: { design_elevation_m: 100 },
|
|
...extra,
|
|
});
|
|
const detailOf = (marks, len = 300) => {
|
|
const grid = [];
|
|
for (let m = 0; m <= len; m += 20) grid.push(m);
|
|
const all = [...new Set([...grid, ...marks.map((x) => x.m)])].sort((a, b) => a - b);
|
|
const cross = all.map((m, i) => {
|
|
const mk = marks.find((x) => x.m === m);
|
|
const kind = i === 0 ? "bp" : i === all.length - 1 ? "ep" : mk ? "irregular" : "regular";
|
|
return sec(m, kind, mk ? { structure: mk.title, ...(m % 20 === 0 ? { grid: true } : {}) } : {});
|
|
});
|
|
return { longitudinal: { length_m: len, stations: [] }, cross_sections: cross };
|
|
};
|
|
const show = (detail) =>
|
|
detail.cross_sections
|
|
.filter((s) => s.kind === "irregular" || s.structure || s.preview)
|
|
.map(
|
|
(s) =>
|
|
`${s.chainage_m}:${s.kind}${s.grid ? "/grid" : ""}${s.preview ? "/preview" : ""}=${s.structure ?? "-"}[${Object.keys(
|
|
s,
|
|
)
|
|
.filter(
|
|
(k) =>
|
|
![
|
|
"station_id",
|
|
"chainage_m",
|
|
"label",
|
|
"kind",
|
|
"center_x",
|
|
"center_y",
|
|
"center_z",
|
|
"frame",
|
|
"samples",
|
|
"design",
|
|
"structure",
|
|
"grid",
|
|
"preview",
|
|
].includes(k),
|
|
)
|
|
.join(",")}]`,
|
|
);
|
|
|
|
const ud = (id, m) => ({
|
|
structure_id: id,
|
|
type_id: "cross_underdrain",
|
|
placement: "point",
|
|
chainage_m: m,
|
|
start_m: null,
|
|
end_m: null,
|
|
options: {},
|
|
});
|
|
const rw = (id, s, a, e) => ({
|
|
structure_id: id,
|
|
type_id: "retaining_wall",
|
|
placement: "interval",
|
|
chainage_m: a,
|
|
start_m: s,
|
|
end_m: e,
|
|
options: {},
|
|
});
|
|
|
|
/** 상세 하나를 맞춘 뒤 — 숨김(빠진 측점) · 구조물 없는 사본 · 측점마다 카드 이름. */
|
|
async function run(saved, draft, marks, frame) {
|
|
S.savedStructures = saved;
|
|
S.draftStructures = draft;
|
|
const detail = detailOf(marks);
|
|
const before = detail.cross_sections.map((s) => s.chainage_m);
|
|
await D.withDraftStations(detail, "p", 1, frame);
|
|
await D.withDraftShapes(detail, "p", false, frame);
|
|
const after = detail.cross_sections.map((s) => s.chainage_m);
|
|
return {
|
|
hidden: before.filter((m) => !after.includes(m)),
|
|
preview: detail.cross_sections.filter((s) => s.preview).map((s) => s.chainage_m),
|
|
names: Object.fromEntries(
|
|
detail.cross_sections.filter((s) => s.structure).map((s) => [s.chainage_m, s.structure]),
|
|
),
|
|
};
|
|
}
|
|
|
|
(async () => {
|
|
const out = {};
|
|
// 옛 틀 상세(저장 정본 · 새로고침) + 새 틀 초안(+20 m) — 저장분 자리 그대로여야 함
|
|
const oldFrame = [ud("A", 100), rw("B", 153, 160, 167)];
|
|
const oldMarks = [
|
|
{ m: 100, title: "맹암거" },
|
|
{ m: 153, title: "옹벽" },
|
|
{ m: 160, title: "옹벽" },
|
|
{ m: 167, title: "옹벽" },
|
|
];
|
|
const shifted = [ud("A", 120), rw("B", 173, 180, 187)];
|
|
for (const frame of ["old", null])
|
|
out[`old_${frame}`] = await run(oldFrame, shifted, oldMarks, frame);
|
|
// 새 틀 상세(갈아끼움 뒤) — 옛 틀 B 중심 120 자리에 새 틀 A 가 옴(종류 다름) · 사본 · 숨김 없어야 함
|
|
const savedB = [ud("A", 100), rw("B", 113, 120, 127)];
|
|
const draftB = [ud("A", 120), rw("B", 133, 140, 147)];
|
|
const newMarks = [
|
|
{ m: 120, title: "맹암거" },
|
|
{ m: 133, title: "옹벽" },
|
|
{ m: 140, title: "옹벽" },
|
|
{ m: 147, title: "옹벽" },
|
|
];
|
|
for (const frame of ["new", null])
|
|
out[`new_${frame}`] = await run(savedB, draftB, newMarks, frame);
|
|
process.stdout.write(JSON.stringify(out));
|
|
})().catch((error) => {
|
|
process.stderr.write(String(error && error.stack ? error.stack : error));
|
|
process.exit(1);
|
|
});
|