test(B05·B06): 박스암거 컨테이너 화면 시나리오 — 고침 · 다시 열기 · B05 = B06 · 되돌림 (PLAN 52-2)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W4uKaV4ZBhsJN4GHG7yRj4
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
/* 52-2 — B05 · B06 좌측 「구조물 배치」 박스암거 = 사용자 구조물 표 02 고친 판(컨테이너 셋)
|
||||
* 시작 화면: B05 종단설계(#/b05-profile) · 검증 프로젝트(sub3_검증) · 목록에 「BOX암거」
|
||||
* 부르는 법: 단계마다 한 번씩 — 앞에 `window.__m522 = "단계";` 를 붙여
|
||||
* orca eval --expression "window.__m522='edit'; $(cat 이 파일)" → 고치고 [저장] (원래 관 지점은 sessionStorage 에 둠)
|
||||
* (orca reload 로 다시 열기)
|
||||
* orca eval --expression "window.__m522='verify'; $(cat 이 파일)" → 다시 연 값 · B06 같은 그리기
|
||||
* orca eval --expression "window.__m522='restore'; $(cat 이 파일)" → 원래 관 지점으로 되돌림(PUT) · 초안 비움
|
||||
* (연결이 끊기면 결과는 `sessionStorage.getItem("__522_out_{단계}")` 로 읽음)
|
||||
* 쓰는 것: 검증 프로젝트 pipe_points.json(되돌림 단계가 원래 값으로 다시 씀)
|
||||
* 기대 수치(edit): 컨테이너 3(본체 · 유입 구조 · 유출 구조 · 모두 필수 · [추가] 0) · 옛 값 3 × 2.5 = 사용자 입력 ·
|
||||
* 옛 「있음」 = 날개벽 · 규격 2.0 × 2.0 고르면 숫자 칸 0 · 사용자 입력 고르면 가로 · 세로 2 ·
|
||||
* 구조 선택지 없음/날개벽/흙막이 · 잇기 본체 · 유입 지정 · 유출 지정 뒤 풂 ·
|
||||
* 저장 = body 2.4 × 1.8 · wing_in 흙막이 · wing_out 없음 · group_items gboxbody · gboxin
|
||||
* 기대 수치(verify): 저장 값 그대로 · 같은 그리기(B05 = B06)
|
||||
*/
|
||||
(async () => {
|
||||
const MODE = window.__m522 || "edit";
|
||||
const w = (ms) => new Promise((r) => setTimeout(r, ms));
|
||||
const until = async (fn, ms = 20000) => {
|
||||
for (let t = 0; t < ms; t += 200) {
|
||||
if (fn()) return true;
|
||||
await w(200);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
const projectId = localStorage.getItem("frd_current_project_id");
|
||||
const modUrl = (part) =>
|
||||
performance
|
||||
.getEntriesByType("resource")
|
||||
.map((e) => e.name)
|
||||
.filter((n) => n.includes(part))
|
||||
.pop();
|
||||
const fetchApi = await import(modUrl("/B04_PreProcess/B04_PreProcess_Api_Fetch.ts"));
|
||||
const isBox = (p) => p.facility === "box_culvert";
|
||||
// 보이는 명세 폼(배관 · BOX 가 각자 폼을 가짐 — 숨은 것은 뺌)
|
||||
const spec = () =>
|
||||
[...document.querySelectorAll(".b05-structure__spec")].find((n) => n.offsetParent !== null);
|
||||
const box = (c) => spec()?.querySelector(`[data-spec-container="${c}"]`);
|
||||
const field = (c, item) => box(c)?.querySelector(`[data-spec-item="${c}.${item}"]`);
|
||||
const ctl = (c, item) => field(c, item)?.querySelector("select, input");
|
||||
const set = async (c, item, v) => {
|
||||
const el = ctl(c, item);
|
||||
el.value = v;
|
||||
el.dispatchEvent(new Event("change", { bubbles: true }));
|
||||
await w(200);
|
||||
};
|
||||
const labels = (c, item) => [...ctl(c, item).options].filter((o) => o.value).map((o) => o.text);
|
||||
const pickBox = async () => {
|
||||
await until(() => document.querySelectorAll(".b05-route__irregular-list li").length > 0);
|
||||
const li = [...document.querySelectorAll(".b05-route__irregular-list li")].find((l) =>
|
||||
/BOX암거$/.test(l.textContent.trim()),
|
||||
);
|
||||
// 다시 열면 고른 것이 복원돼 있음 — 누르면 풀리므로 풀렸으면 한 번 더(재선택 = 해제)
|
||||
(li.querySelector("button") ?? li).click();
|
||||
await w(800);
|
||||
if (!box("body")) (li.querySelector("button") ?? li).click();
|
||||
await until(() => !!box("body"));
|
||||
await w(500);
|
||||
};
|
||||
const shape = () =>
|
||||
[...spec().querySelectorAll("[data-spec-container]")].map((b) => ({
|
||||
c: b.dataset.specContainer,
|
||||
legend: b.querySelector("legend").firstChild.textContent,
|
||||
items: [...b.querySelectorAll("[data-spec-item]")].map((n) => n.dataset.specItem),
|
||||
values: [...b.querySelectorAll("[data-spec-item]")].map(
|
||||
(n) => n.querySelector("select, input").value,
|
||||
),
|
||||
link: b.querySelector(".b05-structure__summary-name")?.textContent,
|
||||
}));
|
||||
const linked = (c) =>
|
||||
box(c).querySelector(".b05-structure__summary-name").classList.contains("is-assigned");
|
||||
const pickLink = async (c) => {
|
||||
box(c).querySelector('[data-b05-summary="pick"]').click();
|
||||
await until(() => document.querySelector(".ui-item-picker__tree .ui-tree__row"));
|
||||
for (let k = 0; k < 8; k++) {
|
||||
const rows = [...document.querySelectorAll(".ui-item-picker__tree .ui-tree__row")];
|
||||
const leaf = rows.find((r) => !r.classList.contains("is-branch"));
|
||||
if (leaf) {
|
||||
leaf.click();
|
||||
break;
|
||||
}
|
||||
rows.find((r) => r.querySelector(".ui-tree__caret")?.textContent === "▸")?.click();
|
||||
await w(300);
|
||||
}
|
||||
await w(300);
|
||||
[...document.querySelectorAll(".ui-item-picker__actions button")]
|
||||
.find((b) => b.textContent.includes("적용"))
|
||||
.click();
|
||||
await w(500);
|
||||
};
|
||||
const out = { mode: MODE };
|
||||
|
||||
if (MODE === "edit") {
|
||||
const before = await fetchApi.fetchDetailPipePoints(projectId);
|
||||
// 원래 값은 처음 한 번만 둠(끊겨 다시 돌려도 고친 값으로 덮지 않음 · 되돌림이 비움)
|
||||
if (!sessionStorage.getItem("__522_original"))
|
||||
sessionStorage.setItem("__522_original", JSON.stringify(before.pipe_points));
|
||||
out.original = before.pipe_points.find(isBox)?.options;
|
||||
await pickBox();
|
||||
const s0 = shape();
|
||||
out.containers = s0.map((b) => [b.c, b.legend]);
|
||||
out.allVisible = ["body", "inlet", "outlet"].every((c) => box(c)?.offsetParent !== null);
|
||||
out.addButtons = spec().querySelectorAll("[data-spec-add]").length;
|
||||
out.oldRead = {
|
||||
body: s0[0].values,
|
||||
inlet: ctl("inlet", "structure").value,
|
||||
outlet: ctl("outlet", "structure").value,
|
||||
};
|
||||
out.sizes = labels("body", "size");
|
||||
out.structures = labels("inlet", "structure");
|
||||
await set("body", "size", "2.0×2.0");
|
||||
out.presetNumberFields = ["width", "height"].filter((i) => field("body", i)).length;
|
||||
await set("body", "size", "사용자 입력");
|
||||
out.customNumberFields = ["width", "height"]
|
||||
.filter((i) => field("body", i))
|
||||
.map((i) => field("body", i).querySelector("label, span")?.textContent ?? i);
|
||||
await set("body", "width", "2.4");
|
||||
await set("body", "height", "1.8");
|
||||
await set("inlet", "structure", "흙막이");
|
||||
await set("outlet", "structure", "없음");
|
||||
await pickLink("body");
|
||||
await pickLink("inlet");
|
||||
await pickLink("outlet");
|
||||
out.linkPicked = ["body", "inlet", "outlet"].map(linked);
|
||||
box("outlet").querySelector('[data-b05-summary="clear"]').click();
|
||||
await w(300);
|
||||
out.linkOutletCleared = !linked("outlet");
|
||||
document.querySelector('[data-dock-action="save"]').click();
|
||||
await w(500);
|
||||
out.saved = await until(() => !document.querySelector(".ui-overlay.is-active"), 60000);
|
||||
const after = await fetchApi.fetchDetailPipePoints(projectId);
|
||||
const p = after.pipe_points.find(isBox);
|
||||
out.file = p && { options: p.options, group_items: Object.keys(p.group_items ?? {}) };
|
||||
}
|
||||
|
||||
if (MODE === "verify") {
|
||||
await pickBox();
|
||||
const b05 = shape();
|
||||
out.reopened = b05.map((b) => [b.c, b.values, b.link]);
|
||||
out.linkReopened = ["body", "inlet", "outlet"].map(linked);
|
||||
location.hash = "#/b06-section";
|
||||
await until(() => location.hash.includes("b06"), 5000);
|
||||
await w(6000);
|
||||
await pickBox();
|
||||
const b06 = shape();
|
||||
out.sameDrawing = JSON.stringify(b05) === JSON.stringify(b06);
|
||||
if (!out.sameDrawing) out.diff = { b05, b06 };
|
||||
}
|
||||
|
||||
if (MODE === "restore") {
|
||||
const original = JSON.parse(sessionStorage.getItem("__522_original") || "null");
|
||||
if (!original) return JSON.stringify({ error: "원래 값 없음" });
|
||||
const keys = [
|
||||
"chainage_m",
|
||||
"source",
|
||||
"facility",
|
||||
"start_m",
|
||||
"end_m",
|
||||
"options",
|
||||
"summary_item",
|
||||
"group_items",
|
||||
];
|
||||
const points = original.map((p) =>
|
||||
Object.fromEntries(
|
||||
keys.filter((k) => p[k] !== undefined && p[k] !== null).map((k) => [k, p[k]]),
|
||||
),
|
||||
);
|
||||
await fetchApi.saveDetailPipePoints(projectId, points);
|
||||
for (const k of Object.keys(sessionStorage))
|
||||
if (k.startsWith("aislo:draft:pipes:") || k === "__522_original")
|
||||
sessionStorage.removeItem(k);
|
||||
const now = await fetchApi.fetchDetailPipePoints(projectId);
|
||||
const pick = (list) =>
|
||||
JSON.stringify(list.map((p) => [p.chainage_m, p.options ?? {}, p.group_items ?? {}]));
|
||||
out.restored = pick(now.pipe_points) === pick(original);
|
||||
}
|
||||
// 긴 단계는 ORCA 연결이 끊길 수 있어 결과를 남김 — `sessionStorage.__522_out_{단계}` 로 읽음
|
||||
sessionStorage.setItem(`__522_out_${MODE}`, JSON.stringify(out));
|
||||
return JSON.stringify(out);
|
||||
})();
|
||||
Reference in New Issue
Block a user