Merge remote-tracking branch 'origin/sub_laptop_5' into sub_laptop_6
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
/* 구조물 정의 → 칸 모양 단위검증 헬퍼(PLAN 48-3 · 48-4) — `B05_Profile_UI_Structures_Define.ts` 를
|
||||
* 그 자리에서 트랜스파일해 Node 로 돌림(import 없는 파일). 결과는 표준출력에 JSON 한 벌.
|
||||
* 판 1 정의(`resources/master_template/구조물정의.json`)도 읽어 지금 화면과 같은지(차례 · 2열) 봄.
|
||||
*/
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript"));
|
||||
|
||||
const ROOT = path.join(__dirname, "..", "..");
|
||||
const src = fs.readFileSync(
|
||||
path.join(ROOT, "B05_Profile", "B05_Profile_UI_Structures_Define.ts"),
|
||||
"utf8",
|
||||
);
|
||||
const js = ts.transpileModule(src, {
|
||||
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 },
|
||||
}).outputText;
|
||||
const box = { exports: {} };
|
||||
new Function("exports", "module", "require", js)(box.exports, box, require);
|
||||
const d = box.exports;
|
||||
|
||||
const opt = (key, extra = {}) => ({
|
||||
key,
|
||||
label: key,
|
||||
input: "select",
|
||||
choices: ["a", "b", "c"],
|
||||
default: null,
|
||||
...extra,
|
||||
});
|
||||
const type = {
|
||||
options: [
|
||||
opt("p"),
|
||||
opt("q"),
|
||||
opt("r", { enabled: false }),
|
||||
opt("s", { visible: false }),
|
||||
opt("t"),
|
||||
],
|
||||
spots: { t: { 줄: 1, 칸: 1, 너비: 2 }, p: { 줄: 2, 칸: 2 } },
|
||||
rules: [
|
||||
{
|
||||
종류: "x",
|
||||
만약: { 옵션: "p", 값들: ["a"] },
|
||||
그러면: { 옵션: "q", 선택지: ["b", "c"], 기본값: "c" },
|
||||
},
|
||||
{ 종류: "x", 만약: { 옵션: "p", 값들: ["b"] }, 그러면: { 옵션: "q", 보이기: false } },
|
||||
{ 종류: "x", 만약: { 옵션: "q", 값들: ["c"] }, 그러면: { 옵션: "t", 보이기: false } },
|
||||
],
|
||||
};
|
||||
const plain = (states) => Object.fromEntries([...states].map(([k, v]) => [k, v]));
|
||||
|
||||
const def = JSON.parse(
|
||||
fs.readFileSync(path.join(ROOT, "resources", "master_template", "구조물정의.json"), "utf8"),
|
||||
);
|
||||
const merged = d.withDefinition(
|
||||
def.types.map((t) => ({ ...t, groups: (def.그룹[t.type_id] ?? []).map((g) => ({ id: g.id })) })),
|
||||
def,
|
||||
);
|
||||
const v1 = merged.map((t) => ({
|
||||
id: t.type_id,
|
||||
same:
|
||||
JSON.stringify(d.orderedOptions(t).map((o) => o.key)) ===
|
||||
JSON.stringify(t.options.filter((o) => o.enabled !== false).map((o) => o.key)),
|
||||
columns: d.columnsOf(t),
|
||||
anchor: d.showsAnchor(t),
|
||||
}));
|
||||
|
||||
const out = {
|
||||
order: d.orderedOptions(type).map((o) => o.key),
|
||||
columns: d.columnsOf(type),
|
||||
columnsNone: d.columnsOf({}),
|
||||
placeT: d.gridPlace(type.spots.t, 2),
|
||||
placeNone: d.gridPlace(undefined, 2),
|
||||
stateA: plain(d.ruleStates(type, { p: "a", q: "c" })),
|
||||
stateB: plain(d.ruleStates(type, { p: "b", q: "c" })),
|
||||
defaultsA: d.ruleDefaults(type, "p", { p: "a" }),
|
||||
defaultsB: d.ruleDefaults(type, "p", { p: "b" }),
|
||||
stale: d.staleValues({ p: "a", old_key: 3, g1__length_m: 2 }, ["p", "g1__length_m"]),
|
||||
shapes: d.shapeFields({
|
||||
길이: { 받기: true, 뜻: "연장" },
|
||||
높이: { 받기: false },
|
||||
후: { 받기: true },
|
||||
}),
|
||||
shapeKey: d.shapeKey("g1", "length_m"),
|
||||
withNull: d.withDefinition([{ type_id: "a", group: "A" }], null),
|
||||
withDef: d.withDefinition([{ type_id: "a", group: "A", groups: [{ id: "g1" }] }], {
|
||||
구조물군: { A: "가 군" },
|
||||
종류: { a: { 기준측점: false, 동작: ["계곡통과시설"] } },
|
||||
그룹: { a: [{ id: "g1", 형상: { 길이: { 받기: true } } }] },
|
||||
배치: { a: { k: { 줄: 1, 칸: 1 } } },
|
||||
규칙: [
|
||||
{ ...type.rules[0], 종류: "a" },
|
||||
{ ...type.rules[1], 종류: "b" },
|
||||
],
|
||||
}),
|
||||
v1Types: v1.length,
|
||||
v1Same: v1.every((t) => t.same),
|
||||
v1Columns: [...new Set(v1.map((t) => t.columns))],
|
||||
v1Anchor: v1.every((t) => t.anchor),
|
||||
};
|
||||
process.stdout.write(JSON.stringify(out));
|
||||
@@ -355,8 +355,14 @@ async function saveWith({
|
||||
setTempPipeChainage() {},
|
||||
summary: () => summaryValue,
|
||||
setSummary: (value) => (summaryValue = value),
|
||||
groupItems: () => ({}), // 옵션 그룹(PLAN 46-3) — 이 시험은 그룹 없음
|
||||
setGroupItems() {},
|
||||
// 옵션 그룹(PLAN 46-3) · 형상 칸(48-3) — 이 시험은 그룹 없음
|
||||
groupBoxes: {
|
||||
get: () => ({}),
|
||||
set() {},
|
||||
shapes: () => ({}),
|
||||
shapeKeys: () => [],
|
||||
setShapes() {},
|
||||
},
|
||||
};
|
||||
if (summaryOnly) {
|
||||
const done = commitModule.commitSummaryOnly(ctx);
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""B05/B06 「구조물 배치」 칸 = 구조물 정의대로 — PLAN 48-3 · 48-4 (2026-10-05).
|
||||
|
||||
정의(`구조물정의.json`)가 주는 차례 · 배치 격자 · 안 씀(`enabled:false`) · 규칙(상위 값 → 하위
|
||||
선택지 · 보이기 · 기본값) · 지난 정의 값 · 그룹 형상 칸 · 정의 덧칸 얹기를 본다.
|
||||
판 1 정의로는 지금 화면과 같음(차례 그대로 · 2열 · 기준 측점 보임).
|
||||
순수 규칙은 Node 헬퍼(`helper_b05_structures_define.cjs`)가 돌림 · 화면은 ORCA `ui_checks/48-3_구조물배치_정의그리기.js`.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
import pytest
|
||||
|
||||
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def out():
|
||||
proc = subprocess.run(
|
||||
["node", os.path.join(HERE, "helper_b05_structures_define.cjs")],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
encoding="utf-8",
|
||||
timeout=60,
|
||||
)
|
||||
assert proc.returncode == 0, proc.stderr
|
||||
return json.loads(proc.stdout)
|
||||
|
||||
|
||||
def test_차례는_배치_줄_칸_뒤는_정의_차례_안씀_숨김_뺌(out):
|
||||
assert out["order"] == ["t", "p", "q"]
|
||||
|
||||
|
||||
def test_격자_칸수와_자리(out):
|
||||
assert out["columns"] == 2
|
||||
assert out["columnsNone"] == 2
|
||||
assert out["placeT"] == {"row": "1", "column": "1 / span 2"}
|
||||
assert out["placeNone"] is None
|
||||
|
||||
|
||||
def test_규칙_선택지_보이기_사슬(out):
|
||||
assert out["stateA"]["q"]["choices"] == ["b", "c"]
|
||||
assert out["stateA"]["t"]["visible"] is False # q=c → t 가림
|
||||
assert out["stateB"]["q"]["visible"] is False # p=b → q 가림
|
||||
assert out["stateB"]["t"]["visible"] is True # 가려진 q 에 매인 줄은 안 걸림
|
||||
|
||||
|
||||
def test_규칙_기본값(out):
|
||||
assert out["defaultsA"] == {"q": "c"}
|
||||
assert out["defaultsB"] == {}
|
||||
|
||||
|
||||
def test_지난_정의_값(out):
|
||||
assert out["stale"] == [["old_key", 3]]
|
||||
|
||||
|
||||
def test_그룹_형상_칸(out):
|
||||
assert [s["suffix"] for s in out["shapes"]] == ["length_m", "after_m"]
|
||||
assert out["shapes"][0]["meaning"] == "연장"
|
||||
assert out["shapeKey"] == "g1__length_m"
|
||||
|
||||
|
||||
def test_정의_덧칸_얹기(out):
|
||||
assert out["withNull"] == [{"type_id": "a", "group": "A"}]
|
||||
t = out["withDef"][0]
|
||||
assert t["group_name"] == "가 군"
|
||||
assert t["show_anchor"] is False
|
||||
assert t["behaviors"] == ["계곡통과시설"]
|
||||
assert t["spots"] == {"k": {"줄": 1, "칸": 1}}
|
||||
assert [r["종류"] for r in t["rules"]] == ["a"]
|
||||
assert t["groups"][0]["shape"] == {"길이": {"받기": True}}
|
||||
|
||||
|
||||
def test_판1_정의는_지금_화면과_같음(out):
|
||||
assert out["v1Types"] == 37
|
||||
assert out["v1Same"] is True
|
||||
assert out["v1Columns"] == [2]
|
||||
assert out["v1Anchor"] is True
|
||||
Reference in New Issue
Block a user