Files
Aislo/resources/master_data/scripts/master_equation_view.py
eomsangdonandClaude Opus 5.5 2376e70fbb revert(802-1): 801-1 wip 옛 나무 위 고침 걷음 — 요구 664 수식 문서로 다시 짬
- 걷음: 43784a4c0 의 옛 수식 나무 위 고침(서버 · 화면 · css) = 그 앞 판으로 되돌림
- 남김: master_equation_sign.py · ui_template_equation_text.ts · ui_template_equation_edit.ts(다시 쓸 조각 · 지금 안 부름) · text 는 `입력글` 을 제 타입에
- 지움: test_801_1_equation_inline.py — 걷은 옛 나무 고침을 재는 시험

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 17:55:58 +09:00

134 lines
6.4 KiB
Python

# -*- coding: utf-8 -*-
"""수식 변수 정의 영역(PLAN 800-2 · 요구 660-2 · 3 · 6) — 수식 나무 → 오른쪽 「변수 정의」 목록.
줄 구분 없이 한 목록 · 같은 변수는 한 번만(겹침 합침) · 기호 : 국문 이름 — 연결(입력 · 표 찾기 ·
요소 · 로직 · 계산을 사람 말로) · 값 · 단위 · DB 열쇠 글은 담지 않음.
지금 고른 옵션 갈래만 — 만약의 탄 갈래 표지 `걸림`(1 참 · 2 거짓 · 0 모름 = 둘 다)을 그대로 씀(새 판정 없음) ·
`안씀` = 어느 식에도 안 쓰이는 입력(지울 수 있음) · 쓰는 변수 지움 막기는 `master_equation_edit._drop`.
"""
from __future__ import annotations
CAT = {"LB": "인력", "EQ": "기계", "MT": "재료", "MO": "재료"}
WHAT = {
"입력": "입력",
"중간": "계산",
"결과": "계산 결과",
"찾기": "표 찾기",
"요소": "요소",
"블록": "로직 부르기",
}
def visible(node: dict | None, out: list[dict]) -> list[dict]:
"""나무에서 보이는(탄 갈래) 변수 · 블록 마디를 차례대로."""
if not isinstance(node, dict):
return out
kind = node.get("꼴")
if kind in ("변수", "블록"):
out.append(node)
elif kind == "조건":
visible(node.get("조건"), out)
for key, at in (("참", 1), ("거짓", 2)):
if node.get("걸림") in (0, None, at):
visible(node.get(key), out)
else:
for key in ("좌", "우", "안", "위", "아래"):
visible(node.get(key), out)
for arg in node.get("인자") or []:
visible(arg, out)
return out
def _link(node: dict, spec: dict | None, leaf: dict | None) -> str:
"""연결 설명 — 사람 말(열쇠 · 값 · 단위 없음)."""
kind = node.get("갈래") or ("블록" if node.get("꼴") == "블록" else "")
if kind == "입력":
return "입력 — " + ("옵션에서 고름" if (spec or {}).get("고르기") else "직접 적음")
if kind == "중간" and leaf is not None and leaf is not node:
return _link(leaf, None, None)
if kind == "상수":
return f"상수 — {node.get('글')}"
if kind == "찾기":
cond = " · ".join(f"{k} = {v}" for k, v in (node.get("조건식") or {}).items())
head = f"표 찾기 — {node.get('표이름') or '표'}"
return head + (f" · 조건 {cond}" if cond else "") + f" · 칸 {node.get('칸') or ''}".rstrip()
if kind == "요소":
pick = node.get("고르기")
if isinstance(pick, dict):
return "요소 · 재료 고름 — " + " · ".join(str(v) for v in pick.values() if v)
return f"요소 · {CAT.get(str(node.get('식') or '')[:2], '단가')} — {node.get('이름') or ''}"
if kind == "블록":
return f"로직 부르기 — {node.get('이름') or ''}"
return WHAT.get(kind, "계산") + (" — 수식 영역의 식" if kind in ("중간", "결과") else "")
def definitions(lines: list[dict], row: dict, rows: list[dict], unused) -> list[dict]:
"""보이는 식의 변수 정의 목록 — `rows` = 변수 표 · `unused(열쇠)` = 어느 식에도 안 쓰임."""
specs = {str(s.get("이름")): s for k in ("입력", "중간") for s in row.get(k) or []}
table = {v["열쇠"]: v for v in rows}
got: dict[str, dict] = {}
leaf: dict[str, dict] = {}
for line in lines:
head, tree = line.get("결과"), line.get("이름식")
if line.get("갈래") in ("중간", "결과") and isinstance(tree, dict):
if tree.get("꼴") == "수": # 상수 — 연결 설명에 그 수
leaf[str(line.get("열쇠"))] = {"갈래": "상수", "글": tree.get("글")}
elif tree.get("갈래") in ("찾기", "요소") or tree.get("꼴") == "블록": # 한 마디 식
leaf[str(line.get("열쇠"))] = tree
found = ([head] if head and line.get("갈래") in ("중간", "결과") else []) + visible(
tree, []
)
for node in found:
key = str(node.get("열쇠") or "")
if key and key not in got and node.get("갈래") in (*WHAT, "합", None):
got[key] = node
out: dict[tuple, dict] = {} # 같은 기호 글 = 같은 정의(겹침 합침) — 연결은 모아 보임
for key, node in got.items():
mine = table.get(key)
look = mine or node
kind = node.get("갈래") or "블록"
if kind == "합":
kind = "결과" if key == "결과" else "중간"
if key.startswith("줄."): # 위 호표 줄 금액 부름
name, link = key[2:].strip("'"), f"호표 줄 금액 — {key[2:].strip(chr(39))}"
else:
link = _link({**node, "갈래": kind}, specs.get(key), leaf.get(key))
if kind == "블록" and not leaf.get(key):
link = "로직 부르기" # 이름이 곧 그 로직 — 되풀이 안 함
name = (look.get("이름") or key) if mine else look.get("이름") or ""
name = node.get("칸") or name if kind == "찾기" else name
one = {
"열쇠": key if mine else "",
"기호": look.get("기호") or name, # 줄 참조도 씌운 기호(master_symbol 한 곳)
"위": look.get("위") or "",
"아래": look.get("아래") or "",
"이름": name,
"갈래": kind,
"연결": [link],
"고침": bool(mine),
}
same = out.setdefault((one["기호"], one["위"], one["아래"]), one)
if same is not one:
same["연결"] += [x for x in one["연결"] if x not in same["연결"]]
if one["열쇠"] and not same["열쇠"]:
same |= {k: one[k] for k in ("열쇠", "이름", "갈래", "고침")}
out = list(out.values())
seen = {d["열쇠"] for d in out}
for v in rows: # 어느 식에도 안 쓰이는 입력 — 지울 수 있게
if v["갈래"] == "입력" and v["열쇠"] not in seen and unused(v["열쇠"]):
out.append(
{
"열쇠": v["열쇠"],
"기호": v["기호"],
"위": v["위"],
"아래": v["아래"],
"이름": v["이름"],
"갈래": "입력",
"연결": ["입력 — 쓰는 식 없음"],
"고침": True,
"안씀": True,
}
)
return out