wip(801-1): 수식 그 자리 고침 · 한 마디 줄 · 로직 부름 기호 · 반올림 · 안 탄 갈래 숨김 — 요구 664 로 멈춤(메인 안 합침)
- 서버: 한 마디 줄(표 찾기 · 요소 · 로직 부름 하나) = 줄 기호 · 「적용 · 값 · 기준」 칸 글 대신 조건 값 기호 · 로직 부름 기호(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>
This commit is contained in:
@@ -28,6 +28,7 @@ from pathlib import Path
|
||||
|
||||
import master_auto as ma
|
||||
import master_cut as mcut
|
||||
import master_equation_sign as msign
|
||||
import master_equation_view as view
|
||||
import master_formula as mf
|
||||
import master_material as mm
|
||||
@@ -345,7 +346,8 @@ def values(tree: dict) -> dict:
|
||||
if kind in ("변수", "블록"):
|
||||
value = tree.get("값")
|
||||
got = _num(value) if value is not None else {"꼴": "글", "글": "?"}
|
||||
return {**got, "열쇠": tree.get("열쇠"), "갈래": tree.get("갈래") or "블록"}
|
||||
unit = tree.get("단위") or tree.get("결과단위") or "" # 값 식 숫자 단위(801-4)
|
||||
return {**got, "열쇠": tree.get("열쇠"), "갈래": tree.get("갈래") or "블록", "단위": unit}
|
||||
if kind == "조건":
|
||||
if tree.get("걸림"):
|
||||
return values(tree["참" if tree["걸림"] == 1 else "거짓"])
|
||||
@@ -462,7 +464,7 @@ def export(master, key: str, given: dict | None = None, depth: int = 0) -> dict:
|
||||
total = {k: cut.get(k) for k in mf.BUNDLE}
|
||||
if depth == 0:
|
||||
sub = {"소계": subtotals(row, cut, total)}
|
||||
out = msym.apply( # 기호 먼저(800-1) → 정의는 기호 씌운 줄로(800-2)
|
||||
out = msym.apply( # 기호 먼저(800-1) → 한 마디 줄 · 로직 부름 기호(801) → 정의(800-2)
|
||||
{
|
||||
"열쇠": row.get("키"),
|
||||
"이름": row.get("이름") or "",
|
||||
@@ -474,6 +476,7 @@ def export(master, key: str, given: dict | None = None, depth: int = 0) -> dict:
|
||||
**sub,
|
||||
}
|
||||
)
|
||||
msign.settle(out)
|
||||
if depth == 0:
|
||||
out["정의"] = view.definitions(out_lines, row, out["변수표"], _unused(row))
|
||||
return _clean(out)
|
||||
|
||||
@@ -414,7 +414,13 @@ def apply(master, row: dict, edits: list, words=None) -> tuple[dict, list[str],
|
||||
_show(new, key, ed, why)
|
||||
elif job == "연결":
|
||||
add, bad = link.plan(master, ed)
|
||||
_add(new, add, why, spots, words) if add else why.append(bad)
|
||||
mid = key in {str(s.get("이름")) for s in new.get("중간") or []}
|
||||
if add and mid and add.get("식"): # 있는 계산 변수 연결 바꿈(801) = 그 줄 식
|
||||
_set_formula(new, {"자리": f"중간:{key}", "식": add["식"]}, why, spots, words)
|
||||
elif add and mid:
|
||||
why.append(f"「{key}」 계산 변수는 입력으로 못 바꿈 — 표 · 요소 · 로직 · 상수")
|
||||
else:
|
||||
_add(new, add, why, spots, words) if add else why.append(bad)
|
||||
else:
|
||||
why.append(f"모르는 할일 「{job}」")
|
||||
except (mf.FormulaError, KeyError, TypeError, ValueError) as e:
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
# -*- 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
|
||||
@@ -76,8 +76,8 @@ def definitions(lines: list[dict], row: dict, rows: list[dict], unused) -> list[
|
||||
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, []
|
||||
found = ([head] if head and line.get("갈래") in ("중간", "결과") else []) + (
|
||||
[] if line.get("한마디") else visible(tree, []) # 한 마디 줄 = 줄 변수 하나(801)
|
||||
)
|
||||
for node in found:
|
||||
key = str(node.get("열쇠") or "")
|
||||
@@ -97,7 +97,7 @@ def definitions(lines: list[dict], row: dict, rows: list[dict], unused) -> list[
|
||||
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
|
||||
name = node.get("칸") or name if kind == "찾기" and not node.get("칸글") else name
|
||||
one = {
|
||||
"열쇠": key if mine else "",
|
||||
"기호": look.get("기호") or name, # 줄 참조도 씌운 기호(master_symbol 한 곳)
|
||||
|
||||
Reference in New Issue
Block a user