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
@@ -13,11 +13,22 @@
from __future__ import annotations
import re
from typing import Any
from common_util.common_util_structure_catalog import load_parts, resolve_catalog
BRANCHES = ("횡단도", "카드이름", "형상", "3D")
# 화면 글(322-2 다듬기 · TS `M02_SO_Def_Reflect` 짝) — 자리꼴 · 정본 한국어 · 부품 짧은 이름
PLACE_KO = {"point": "점", "interval": "구간", "site": "터"}
OWNER_KO = {"pipe_points": "관 지점", "structures": "구조물"}
def short_name(full: str) -> str:
"""괄호 설명을 뗀 부품 이름(TS `shortName` 짝)."""
return re.sub(r"\s*\(.*\)\s*$", "", full)
OFF_VALUE = {"횡단도": "none", "카드이름": "name", "형상": "none", "3D": "none"}
LISTS = ("both", "b06", "hidden")
_FIELDS = {"목록", "형상칸", *BRANCHES}
@@ -99,7 +110,7 @@ def _row_errors(doc: dict[str, Any], before: dict[str, Any] | None) -> list[str]
if row is None:
continue
if row["shape"] == "none" and row["station"] != "none":
out.append(f"「{row['name']}」 형상 none — 횡단도도 none 이어야 함")
out.append(f"「{row['name']}」 형상이 「없음」이면 횡단도도 「안 만듦」")
kept = _hidden_in(before or doc, t["type_id"]) # 앞 판 없음 = 새로 숨긴 것 없음
hidden = [key for key in _hidden_in(doc, t["type_id"]) if key not in kept]
# 숨기면 그림이 기본값을 씀 — 기본값도 비워 두는 뜻도 없는 칸만 못 숨김
@@ -114,19 +125,20 @@ def _row_errors(doc: dict[str, Any], before: dict[str, Any] | None) -> list[str]
("형상", row["shape"]),
("3D", row["model3d"]),
)
labels = {o["key"]: o.get("label") or o["key"] for o in t.get("options") or []}
for branch, part_id in used:
part = parts[branch].get(part_id)
if part is None:
continue
name = short_name(part["이름"])
place = PLACE_KO.get(row["placement"], row["placement"])
owner = OWNER_KO.get(row["owner"], row["owner"])
if row["placement"] not in part["자리꼴"] or row["owner"] not in part["정본"]:
out.append(
f"「{row['name']}」 {branch} 「{part_id}」 — 자리꼴 {row['placement']} · "
f"정본 {row['owner']} 에 안 맞음"
)
out.append(f"「{row['name']}」 {branch} 「{name}」 — {place} · {owner} 에 안 맞음")
for key in part["읽는 칸"]:
if key in keys and key in hidden:
out.append(
f"「{row['name']}」 {branch} 「{part_id}」 이 읽는 칸 「{key}」 — "
f"「{row['name']}」 {branch} 「{name}」 이 쓰는 칸 「{labels[key]}」 — "
"숨길 수 없음"
)
return out
@@ -138,9 +150,10 @@ def _fixed_errors(doc: dict[str, Any], before: dict[str, Any]) -> list[str]:
now = {t["type_id"]: t for t in doc.get("types") or []}
for old in before.get("types") or []:
tid = old["type_id"]
name = old.get("name") or tid
t = now.get(tid)
if t is None:
out.append(f"종류 「{tid}」 — 지울 수 없음")
out.append(f"종류 「{name}」 — 지울 수 없음")
continue
fixed = (
("자리꼴", old.get("placement"), t.get("placement")),
@@ -149,14 +162,15 @@ def _fixed_errors(doc: dict[str, Any], before: dict[str, Any]) -> list[str]:
)
for what, a, b in fixed:
if a != b:
out.append(f"「{tid}」 {what} — 만든 뒤 고정")
out.append(f"「{name}」 {what} — 만든 뒤 고정")
options = {o["key"]: o for o in t.get("options") or []}
for o in old.get("options") or []:
n = options.get(o["key"])
if o.get("input") != "select" or n is None:
continue
if sorted(o.get("choices") or []) != sorted(n.get("choices") or []):
out.append(f"「{tid}.{o['key']}」 선택지 값 — 고칠 수 없음(이름은 이름 표로)")
label = o.get("label") or o["key"]
out.append(f"「{name}」 「{label}」 선택지 값 — 고칠 수 없음(이름만 고침)")
return out