fix(구조물표): 322-2 다듬기(브레인 화면 확인) — 화면에 영어 키 안 보임 · 검사 글 한국어(화면 · 서버 짝) · 부품 탭 읽는 칸 = 정의 이름 · 줄바꿈 · 한눈 표 폭 줄임 · 바꿨다 되돌리면 [저장] 꺼짐

- 자리꼴 점 · 구간 · 터 · 정본 관 지점 · 구조물(키는 툴팁) · 고르기 글 = 부품 짧은 이름(괄호 설명 · 키는 툴팁) · 횡단도 없음 = 「안 만듦」 · 「벽 스윕」 → 「벽」 · 종류 키는 툴팁
- 검사 글: 「형상이 「없음」이면 횡단도도 「안 만듦」」 · 부품 짧은 이름 · 칸 이름 · 종류 이름(M02_SO_Def_Check.ts = M02_SO_Check.py)
- 부품 탭: 읽는 칸 = 그 부품을 쓰는 종류의 칸 이름(단위) · 표 줄바꿈(table-layout fixed)
- 한눈 표 형상칸 「기본 형태」 = 그림 형태 고르기(REVET_FORMS)
- [저장] 켬 = 저장할 꼴(tidy · 목록 짝 enabled)끼리 지금 판과 다를 때만(M02_SO_Def_Reflect.differs)
- 시험: 322-2 검사 글 · 되돌림 견본

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ji4nuyLVHcxrXWHTdb5nRD
This commit is contained in:
2026-10-14 16:29:30 +09:00
co-authored by Claude Opus 5.5
parent 6c87207f76
commit 0da2fa0767
11 changed files with 207 additions and 89 deletions
@@ -17,6 +17,7 @@ import {
resolveCatalog,
type CatalogDefinition,
} from "../../common_util/common_util_structure_catalog";
import { OWNER_KO, PLACE_KO, shortName } from "./M02_SO_Def_Reflect";
type Branch = "횡단도" | "카드이름" | "형상" | "3D";
interface Part {
@@ -52,6 +53,7 @@ export interface CheckDef extends CatalogDefinition {
choices?: readonly string[];
default?: unknown;
empty_means?: string | null;
label?: string;
}>;
}>;
표시?: Record<string, Record<string, boolean>>;
@@ -123,7 +125,7 @@ function rowErrors(doc: CheckDef, before: CheckDef | null): string[] {
const row = rows.get(t.type_id);
if (!row) continue;
if (row.shape === "none" && row.station !== "none")
out.push(`「${row.name}」 형상 none — 횡단도도 none 이어야 함`);
out.push(`「${row.name}」 형상이 「없음」이면 횡단도도 「안 만듦」`);
const kept = hiddenIn(before ?? doc, t.type_id); // 앞 판 없음 = 새로 숨긴 것 없음
const hidden = hiddenIn(doc, t.type_id).filter((key) => !kept.includes(key));
// 숨기면 그림이 기본값을 씀 — 기본값도 비워 두는 뜻도 없는 칸만 못 숨김
@@ -132,6 +134,8 @@ function rowErrors(doc: CheckDef, before: CheckDef | null): string[] {
.filter((o) => (o.default === null || o.default === undefined) && !o.empty_means)
.map((o) => o.key),
);
const labelOf = (key: string): string =>
(t.options ?? []).find((o) => o.key === key)?.label ?? key;
const used: Array<[Branch, string]> = [
["횡단도", row.station],
["카드이름", row.title],
@@ -141,13 +145,16 @@ function rowErrors(doc: CheckDef, before: CheckDef | null): string[] {
for (const [branch, id] of used) {
const part = partOf(branch, id);
if (!part) continue;
const name = shortName(part.이름);
const place = PLACE_KO[row.placement] ?? row.placement;
const owner = OWNER_KO[row.owner] ?? row.owner;
if (!part.자리꼴.includes(row.placement) || !part.정본.includes(row.owner))
out.push(
`「${row.name}」 ${branch} 「${id}」 — 자리꼴 ${row.placement} · 정본 ${row.owner} 에 안 맞음`,
);
out.push(`「${row.name}」 ${branch} 「${name}」 — ${place} · ${owner} 에 안 맞음`);
for (const key of part["읽는 칸"])
if (keys.has(key) && hidden.includes(key))
out.push(`「${row.name}」 ${branch} 「${id}」 이 읽는 칸 「${key}」 — 숨길 수 없음`);
out.push(
`「${row.name}」 ${branch} 「${name}」 이 쓰는 칸 「${labelOf(key)}」 — 숨길 수 없음`,
);
}
}
return out;
@@ -159,8 +166,9 @@ function fixedErrors(doc: CheckDef, before: CheckDef): string[] {
const now = new Map((doc.types ?? []).map((t) => [t.type_id, t]));
for (const old of before.types ?? []) {
const t = now.get(old.type_id);
const name = old.name ?? old.type_id;
if (!t) {
out.push(`종류 「${old.type_id}」 — 지울 수 없음`);
out.push(`종류 「${name}」 — 지울 수 없음`);
continue;
}
const fixed: Array<[string, unknown, unknown]> = [
@@ -168,8 +176,7 @@ function fixedErrors(doc: CheckDef, before: CheckDef): string[] {
["정본", old.managed_by ?? null, t.managed_by ?? null],
["군 글자", old.group, t.group],
];
for (const [what, a, b] of fixed)
if (a !== b) out.push(`「${old.type_id}」 ${what} — 만든 뒤 고정`);
for (const [what, a, b] of fixed) if (a !== b) out.push(`「${name}」 ${what} — 만든 뒤 고정`);
const options = new Map((t.options ?? []).map((o) => [o.key, o]));
for (const o of old.options ?? []) {
const n = options.get(o.key);
@@ -177,7 +184,7 @@ function fixedErrors(doc: CheckDef, before: CheckDef): string[] {
const a = [...(o.choices ?? [])].sort().join("\u0000");
const b = [...(n.choices ?? [])].sort().join("\u0000");
if (a !== b)
out.push(`「${old.type_id}.${o.key}」 선택지 값 — 고칠 수 없음(이름은 이름 표로)`);
out.push(`「${name}」 「${o.label ?? o.key}」 선택지 값 — 고칠 수 없음(이름만 고침)`);
}
}
return out;