refactor(472-5 5-B 값 주인 하나): 횡단 상세 객체 = 상세 가게 하나 — 계산 묶음 페이지는 지문(노선 · 표본)만
- 상세 가게 칸 셋(B06_Section_Section_Canon.ts · 가벼운 자리): 저장 정본 상세(받을 때 · 세션 · 판 바뀜 · 되돌릴 때 · 갈아끼움 제외) · 초안 전 hold 상세(판 바뀌면 새 판) · 노선 초안 상세(= pipelineDetail) - 페이지: canon.detail · held.detail · shown 사본 걷음 — 저장 기준 셈(savedEdits · storedPvi · crossNow)은 가게 칸을 읽음 · 초안 버림 = 가게 hold 상세로 정본 잡음 - 떠남(forgetSectionMemory) · invalidate 때 칸 셋 비움 · savedStations 는 sub2 관 · 구조물 줄로 셈 → 남김 - 시험: test_472_5b_detail_owner(옛 코드 빨강 3) · 묶음 헬퍼 넷(365 · 346_2 · 349_0j · 451_drop)이 종단도 흉내 정본을 가게 칸에도 채움 - 위키 design_page 값 · 규칙 · 층 줄 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -69,6 +69,8 @@ function loadTs(full) {
|
||||
return box.exports;
|
||||
}
|
||||
const load = (...parts) => loadTs(path.join(ROOT, ...parts));
|
||||
// 상세 가게 칸(472-5) — 실제는 상세 가게가 받을 때 채움 · 여기선 종단도가 내주는 저장 상세 그대로
|
||||
const slots = () => load("B06_Section", "B06_Section_Section_Canon.ts");
|
||||
|
||||
const sampler = load("common_util", "common_util_surface_sampler.ts");
|
||||
const bytes = fs.readFileSync(process.argv[3]);
|
||||
@@ -190,7 +192,7 @@ async function run() {
|
||||
pipelineSource: () => ({
|
||||
base: savedBase,
|
||||
edits: alignment.emptyEdits(),
|
||||
detail: job.detail,
|
||||
detail: (slots().keepSavedDetail(P, 7, job.detail), job.detail),
|
||||
routeId: 7,
|
||||
}),
|
||||
adoptPipeline: (base, edits, draft) => adopted.push({ draft, saved: base === savedBase }),
|
||||
|
||||
@@ -69,6 +69,8 @@ function loadTs(full) {
|
||||
return box.exports;
|
||||
}
|
||||
const load = (...parts) => loadTs(path.join(ROOT, ...parts));
|
||||
// 상세 가게 칸(472-5) — 실제는 상세 가게가 받을 때 채움 · 여기선 종단도가 내주는 저장 상세 그대로
|
||||
const slots = () => load("B06_Section", "B06_Section_Section_Canon.ts");
|
||||
|
||||
const sampler = load("common_util", "common_util_surface_sampler.ts");
|
||||
const bytes = fs.readFileSync(process.argv[3]);
|
||||
@@ -200,7 +202,7 @@ async function draftRun(P, grid) {
|
||||
pipelineSource: () => ({
|
||||
base: savedBase,
|
||||
edits: alignment.emptyEdits(),
|
||||
detail: job.detail,
|
||||
detail: (slots().keepSavedDetail(P, 7, job.detail), job.detail),
|
||||
routeId: 7,
|
||||
}),
|
||||
adoptPipeline: () => undefined,
|
||||
|
||||
@@ -68,6 +68,10 @@ function loadTs(full) {
|
||||
return box.exports;
|
||||
}
|
||||
const load = (...parts) => loadTs(path.join(ROOT, ...parts));
|
||||
// 상세 가게 칸(472-5) — 실제는 상세 가게가 받을 때 채움 · 여기선 종단도가 내주는 저장 상세 그대로
|
||||
const slots = () => load("B06_Section", "B06_Section_Section_Canon.ts");
|
||||
/** 이 시험은 묶음 여럿(P · Q · B)이 같은 종단도 흉내를 씀 — 칸 = 지금 연 프로젝트. */
|
||||
const here = () => window.localStorage.getItem("frd_current_project_id");
|
||||
|
||||
const sampler = load("common_util", "common_util_surface_sampler.ts");
|
||||
const bytes = fs.readFileSync(process.argv[3]);
|
||||
@@ -214,7 +218,7 @@ async function run() {
|
||||
pipelineSource: () => ({
|
||||
base: savedBase,
|
||||
edits: alignment.emptyEdits(),
|
||||
detail: job.detail,
|
||||
detail: (slots().keepSavedDetail(here(), 7, job.detail), job.detail),
|
||||
routeId: 7,
|
||||
}),
|
||||
adoptPipeline: () => undefined,
|
||||
@@ -222,7 +226,8 @@ async function run() {
|
||||
});
|
||||
const options = {
|
||||
stationIntervalM: job.interval,
|
||||
holdDraft: (_routeId, saved) => {
|
||||
holdDraft: (routeId, saved) => {
|
||||
slots().keepHeldDetail(here(), routeId, saved); // 초안 전 상세 칸(472-5 · 가게 hold 와 같음)
|
||||
holds.push(saved === job.detail ? "saved" : saved ? "other" : "null");
|
||||
return async () => "saved";
|
||||
},
|
||||
|
||||
@@ -67,6 +67,8 @@ function loadTs(full) {
|
||||
return box.exports;
|
||||
}
|
||||
const load = (...parts) => loadTs(path.join(ROOT, ...parts));
|
||||
// 상세 가게 칸(472-5) — 실제는 상세 가게가 받을 때 채움 · 여기선 종단도가 내주는 저장 상세 그대로
|
||||
const slots = () => load("B06_Section", "B06_Section_Section_Canon.ts");
|
||||
|
||||
const sampler = load("common_util", "common_util_surface_sampler.ts");
|
||||
const bytes = fs.readFileSync(process.argv[3]);
|
||||
@@ -215,7 +217,7 @@ async function run() {
|
||||
pipelineSource: () => ({
|
||||
base: savedBase,
|
||||
edits: alignment.emptyEdits(),
|
||||
detail: job.detail,
|
||||
detail: (slots().keepSavedDetail(P, 7, job.detail), job.detail),
|
||||
routeId: 7,
|
||||
}),
|
||||
adoptPipeline: (_base, _edits, draft) => adopts.push(draft ? "draft" : "saved"),
|
||||
@@ -223,10 +225,13 @@ async function run() {
|
||||
},
|
||||
{
|
||||
stationIntervalM: job.interval,
|
||||
holdDraft: () => async (stations) => {
|
||||
restores.push({ at: adopts.length, stations: stations.length });
|
||||
return "saved";
|
||||
},
|
||||
holdDraft: (routeId, saved) => (
|
||||
slots().keepHeldDetail(P, routeId, saved), // 초안 전 상세 칸(472-5 · 가게 hold 와 같음)
|
||||
async (stations) => {
|
||||
restores.push({ at: adopts.length, stations: stations.length });
|
||||
return "saved";
|
||||
}
|
||||
),
|
||||
},
|
||||
);
|
||||
pageMod.pipelineEarthwork(P, { conversion: job.conversion });
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/* 472-5 5-B 헬퍼 — 상세 가게 칸 셋(`B06_Section_Section_Canon.ts`) 넣고 비움. 짝 = `test_472_5b_detail_owner.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 file = path.join(ROOT, "B06_Section", "B06_Section_Section_Canon.ts");
|
||||
const js = ts.transpileModule(fs.readFileSync(file, "utf8"), {
|
||||
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 },
|
||||
}).outputText;
|
||||
const box = { exports: {} };
|
||||
new Function("exports", "module", "require", js)(box.exports, box, () => ({
|
||||
readState: () => null,
|
||||
}));
|
||||
const c = box.exports;
|
||||
const [a, b, d] = [{ tag: "a" }, { tag: "b" }, { tag: "d" }];
|
||||
c.keepSavedDetail("P", 1, a);
|
||||
c.keepSavedDetail("P", 2, b);
|
||||
c.keepHeldDetail("P", 1, b);
|
||||
c.setDraftSectionDetail("P", d);
|
||||
const tag = (x) => x?.tag ?? null;
|
||||
const out = {
|
||||
saved1: tag(c.savedSectionDetail("P", 1)),
|
||||
held1: tag(c.heldSectionDetail("P", 1)),
|
||||
draft: tag(c.draftDetailOf("P")),
|
||||
};
|
||||
c.forgetDetailSlots("P", 1);
|
||||
out.after1 = [
|
||||
tag(c.savedSectionDetail("P", 1)),
|
||||
tag(c.heldSectionDetail("P", 1)),
|
||||
tag(c.savedSectionDetail("P", 2)),
|
||||
tag(c.draftDetailOf("P")),
|
||||
];
|
||||
c.forgetDetailSlots("P");
|
||||
out.afterAll = [tag(c.savedSectionDetail("P", 2)), tag(c.draftDetailOf("P"))];
|
||||
console.log(JSON.stringify(out));
|
||||
@@ -0,0 +1,60 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""472-5 5-B — 횡단 상세 객체의 주인 = 상세 가게 하나(칸 셋: 저장 정본 · 초안 전 hold · 노선 초안).
|
||||
|
||||
옛 꼴: 계산 묶음 페이지가 상세 객체를 따로 쥠(정본 `canon.detail` · 초안 전 `held.detail` ·
|
||||
노선 초안 `shown`) — 가게가 판 바뀜(433-16)으로 hold 를 새 판으로 바꿔도 페이지는 옛 객체로
|
||||
정본을 잡았음.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
TS = ROOT / "config" / "node_modules" / "typescript"
|
||||
|
||||
|
||||
def _src(*parts: str) -> str:
|
||||
return (ROOT.joinpath(*parts)).read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def test_페이지는_상세를_안_쥠() -> None:
|
||||
page = _src("A00_Common", "design", "design_pipeline_page.ts")
|
||||
saved = _src("A00_Common", "design", "design_pipeline_page_saved.ts")
|
||||
assert "let shown" not in page # 노선 초안 상세 = 가게 칸
|
||||
assert "setDraftSectionDetail(projectId, shown)" in page
|
||||
assert "detail: () => draftDetailOf(projectId)" in page
|
||||
assert "detail: SectionDetailResponse | null;" not in page # hold 에 상세 사본 없음
|
||||
assert "heldSectionDetail(projectId, routeId as number)" in page
|
||||
assert "let canon: { routeId: unknown; samples: unknown } | null" in saved # 지문만
|
||||
assert "savedSectionDetail(projectId, canon.routeId)" in saved
|
||||
|
||||
|
||||
def test_가게가_칸을_채움() -> None:
|
||||
store = _src("B06_Section", "B06_Section_Section_Store.ts")
|
||||
# 받을 때(세션 · 새로 받음 · 판 바뀜) · 되돌릴 때 = 저장 정본 칸 · 갈아끼움은 안 씀
|
||||
assert store.count("keepSavedDetail(projectId, routeId,") == 4
|
||||
swap = store[store.index("export async function swapSectionStations(") :]
|
||||
assert "keepSavedDetail" not in swap[: swap.index("\n}\n")]
|
||||
# 판이 바뀌면 hold 도 새 판(433-16)
|
||||
renew = "if (heldSectionDetail(projectId, routeId) === stored) keepHeldDetail("
|
||||
assert renew + "projectId, routeId, fresh);" in store
|
||||
forget = store[store.index("export function forgetSectionMemory(") :]
|
||||
assert "forgetDetailSlots(projectId);" in forget[: forget.index("\n}\n")]
|
||||
|
||||
|
||||
@pytest.mark.skipif(not TS.is_dir(), reason="프론트엔드 의존성 미설치")
|
||||
def test_칸_셋_넣고_비움() -> None:
|
||||
helper = ROOT / "resources" / "tester" / "helper_472_5b_slots.cjs"
|
||||
run = subprocess.run(
|
||||
["node", str(helper)], capture_output=True, text=True, encoding="utf-8", timeout=60
|
||||
)
|
||||
assert run.returncode == 0, run.stderr
|
||||
got = json.loads(run.stdout)
|
||||
assert got["saved1"] == "a" and got["held1"] == "b" and got["draft"] == "d"
|
||||
assert got["after1"] == [None, None, "b", "d"] # 노선 하나만 · 초안 칸은 그대로
|
||||
assert got["afterAll"] == [None, None]
|
||||
Reference in New Issue
Block a user