- 서버: 한 마디 줄(표 찾기 · 요소 · 로직 부름 하나) = 줄 기호 · 「적용 · 값 · 기준」 칸 글 대신 조건 값 기호 · 로직 부름 기호(master_equation_sign) · 값 식 숫자 단위 · 있는 계산 변수 연결 바꿈 = 그 줄 식 · 식 속 원자 키보드 글(입력글) - 화면: 박스 없는 조판 · 반올림 감싸개 · 안 탄 만약 숨김(감싸개 글로 구조 지킴) · 보이는 식 그 자리 고침(contenteditable · 원자 data-tok) · 값 숫자 그 자리 고침(valueEdit) - 시험 test_801_1 7 통과 · 넓은 왕복 199 로직 중 13 걸림(식 300 자 상한 · 요소 EQ/MO 글 · 표 칸 Q 기호 맞물림) · test_796_2 옛 createFormulaCell 기대 안 고침(멈춤) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
100 lines
4.5 KiB
Python
100 lines
4.5 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""수식 마디 기호 다듬기(PLAN 801-1 · 801-2 · 요구 662-4) — 기호 씌운(`master_symbol.apply`) 뒤 · 정의 영역 앞.
|
|
|
|
보이기만 — 셈 · 엔진 열쇠 · 식(`식` 칸) 안 바꿈.
|
|
- 한 마디 줄: 중간 · 결과 줄 식이 표 찾기 · 요소 · 로직 부르기 한 마디뿐이면 그 마디 = 줄 기호 · 줄 `한마디`
|
|
(화면은 「q = 0.7」 — 표 칸 글 「적용」 · 로직 이름은 정의 영역에만).
|
|
- 로직 부르기 마디 = 기호(부른 로직 결과 기호 + 아래 = 로직 이름 앞말) — 이름은 정의 영역 · 펼침 머리.
|
|
- 뜻 없는 표 칸 글(`PLAIN` — 적용 · 값 · 기준)로 지은 표 찾기 기호 = 그 행 조건 값(없으면 표 이름)으로.
|
|
- 한 로직 안 겹침 = 아래첨자 끝 숫자(`master_symbol.apply` 와 같은 꼴).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import master_symbol as msym
|
|
|
|
PLAIN = {"적용", "값", "기준"}
|
|
LEAF = ("찾기", "요소")
|
|
|
|
|
|
def _sign(n: dict) -> str:
|
|
return f"{n.get('기호') or ''}_{n.get('아래') or ''}^{n.get('위') or ''}"
|
|
|
|
|
|
def _nodes(tree, out: list[dict]) -> list[dict]:
|
|
"""변수 · 블록 마디(블록 속 나무는 따로 다듬음 — 안 들어감)."""
|
|
if isinstance(tree, list):
|
|
for one in tree:
|
|
_nodes(one, out)
|
|
elif isinstance(tree, dict):
|
|
if tree.get("꼴") in ("변수", "블록"):
|
|
out.append(tree)
|
|
for k, v in tree.items():
|
|
if k != "나무" and isinstance(v, (dict, list)):
|
|
_nodes(v, out)
|
|
return out
|
|
|
|
|
|
def lone(line: dict) -> bool:
|
|
"""줄 식이 표 찾기 · 요소 · 로직 부르기 한 마디뿐인 중간 · 결과 줄."""
|
|
tree = line.get("이름식") or {}
|
|
one = tree.get("꼴") == "블록" or (tree.get("꼴") == "변수" and tree.get("갈래") in LEAF)
|
|
return line.get("갈래") in ("중간", "결과") and one and isinstance(line.get("결과"), dict)
|
|
|
|
|
|
def _block_sign(node: dict) -> tuple[str, str, str]:
|
|
sub = node.get("나무") or {}
|
|
last = next((x for x in reversed(sub.get("줄") or []) if x.get("갈래") == "결과"), None)
|
|
head = (last or {}).get("결과") or {}
|
|
sign = head.get("기호") if msym.is_symbol(str(head.get("기호") or "")) else ""
|
|
sign = sign or msym.rule(str(node.get("결과단위") or ""), "결과")[0]
|
|
return sign, msym.short(str(node.get("이름") or node.get("열쇠") or "")), ""
|
|
|
|
|
|
def _find_sign(node: dict) -> tuple[str, str, str]:
|
|
said = [str(v) for v in (node.get("행") or {}).values() if isinstance(v, str) and v]
|
|
name = said[-1] if said else str(node.get("표이름") or "")
|
|
node["칸글"] = True # 정의 이름 = 표 · 조건 값(칸 글 아님)
|
|
node["이름"] = " ".join(x for x in (str(node.get("표이름") or ""), *said[-1:]) if x)
|
|
if msym.is_symbol(name):
|
|
return name, "", "표"
|
|
sign, low, _ = msym.lookup(name, "찾기")
|
|
return sign, low, "표"
|
|
|
|
|
|
def settle(out: dict) -> dict:
|
|
"""내보낸 수식 한 벌(한 깊이) 다듬기 — 제자리 고침 · 같은 것 돌려줌."""
|
|
lines = out.get("줄") or []
|
|
for line in lines:
|
|
if lone(line):
|
|
line["한마디"] = True
|
|
head = line["결과"]
|
|
line["이름식"] |= {k: head.get(k) or "" for k in ("기호", "아래", "위")}
|
|
nodes = _nodes(lines, [])
|
|
heads = [x["결과"] for x in lines if isinstance(x.get("결과"), dict)]
|
|
used = {_sign(n) for n in [*nodes, *heads, *(out.get("변수표") or [])]}
|
|
done: dict[str, tuple[str, str, str]] = {}
|
|
for line in lines:
|
|
skip = line["이름식"] if line.get("한마디") else None
|
|
for node in _nodes(line.get("이름식"), []):
|
|
if node is skip:
|
|
continue
|
|
if node.get("꼴") == "블록":
|
|
want = _block_sign
|
|
elif node.get("갈래") == "찾기" and node.get("칸") in PLAIN:
|
|
want = _find_sign
|
|
else:
|
|
continue
|
|
key = str(node.get("식") or node.get("열쇠"))
|
|
if key not in done:
|
|
used.discard(_sign(node))
|
|
sign, low, up = want(node)
|
|
n, base = 1, low
|
|
while _sign({"기호": sign, "아래": low, "위": up}) in used:
|
|
n += 1
|
|
low = base[: msym.SUBMAX - len(str(n))] + str(n)
|
|
used.add(_sign({"기호": sign, "아래": low, "위": up}))
|
|
done[key] = (sign, low, up)
|
|
node["기호"], node["아래"], node["위"] = done[key]
|
|
return out
|