feat(M01): 흐름 로직 옛 엔진 한 곳 갈래 · 인력/기계/유가 조건 찾기 · 표 수 식 글 · 재료 키 찾기(PLAN 36-4 덧)
- master_formula.run 에 FLOW_RUN 자리 — Store_Flow 가 꽂음 · 조합 · 프로젝트 단가 · 읽는 식 · 옛 식의 로직(…) 도 흐름 로직이면 흐름 셈(단가는 마스터 · 프로젝트 사본 단가는 아직) - 흐름 → 옛 → 흐름 돌고 도는 부름 막음 · /logic/auto 흐름 로직 = 설계 예시값 - 조건 찾기 요소 인력 · 기계 · 유가전력(group_find · 이름 · 키 · 원문번호 같음/포함 · 기본 키 대체) - 표 값 칸 수 식 글(「(0.05)」 「1/1.30」) = 옛 엔진 파서로 수 · 재료 조건 찾기 field 키(자재 키 · 품번) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KmELpdXFDRZHhfbGuRhSmL
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib
|
||||
from contextvars import ContextVar
|
||||
from decimal import Decimal, InvalidOperation
|
||||
from typing import Any
|
||||
|
||||
@@ -26,6 +27,7 @@ FLOW = "흐름"
|
||||
KINDS = ("input", "function", "output")
|
||||
CONVERT = "M02_MasterTemplete.DataFlow.M02_DF_Convert"
|
||||
NOT_READY = "변환 준비 중"
|
||||
_ACTIVE: ContextVar[tuple] = ContextVar("m01_flow_active", default=()) # 셈 중인 흐름 키
|
||||
|
||||
|
||||
# ── 검사(Model `link` · `ruleWhy` 와 같은 뜻) ──────────────────────────────
|
||||
@@ -152,9 +154,46 @@ def _value(v: Any) -> Any:
|
||||
|
||||
def run(flow: dict, key: str, inputs: dict) -> dict:
|
||||
"""흐름 셈 — 입력 = 「설계 때 정할 것」 이름 → 값."""
|
||||
given = {k: _value(v) for k, v in (inputs or {}).items()}
|
||||
flow = {**flow, "key": key}
|
||||
return dc.run(flow, dc._design_values(flow, given), load, flow.get("userElements") or [], [key])
|
||||
active = _ACTIVE.get()
|
||||
if key and key in active: # 옛 셈을 건너 다시 돌아온 흐름(흐름 → 옛 로직 → 흐름)
|
||||
raise store.cm.mf.FormulaError(f"로직이 서로를 부름 — {' → '.join([*active, key])}")
|
||||
token = _ACTIVE.set((*active, key))
|
||||
try:
|
||||
given = {k: _value(v) for k, v in (inputs or {}).items()}
|
||||
flow = {**flow, "key": key}
|
||||
values = dc._design_values(flow, given)
|
||||
return dc.run(flow, values, load, flow.get("userElements") or [], [key])
|
||||
finally:
|
||||
_ACTIVE.reset(token)
|
||||
|
||||
|
||||
def _engine(master, ref: str, row: dict, given: dict) -> dict:
|
||||
"""옛 엔진 `mf.run` 갈래(조합 · 프로젝트 단가 · 읽는 식 · 옛 식의 로직(…)) — `run` 과 같은 꼴.
|
||||
|
||||
ponytail: 단가는 마스터에서(`M02_DF_Values`) — 프로젝트 사본 단가(master 인자)는 아직 안 씀.
|
||||
"""
|
||||
got = run(row[FLOW], ref, given)
|
||||
if got["errors"]:
|
||||
raise store.cm.mf.FormulaError(f"「{ref}」 흐름 셈 — {' · '.join(got['errors'])}")
|
||||
cost = got["cost"]
|
||||
kinds = {(b.get("output") or {}).get("cost") for b in row[FLOW].get("boxes") or []
|
||||
if b.get("kind") == "output"} # fmt: skip
|
||||
if kinds and kinds <= {"값"} and len(cost["값들"]) == 1: # 돈 아닌 로직 = 결과 하나
|
||||
return {"결과": next(iter(cost["값들"].values())), "중간": {}}
|
||||
return {"줄": [], **{k: cost[k] for k in dc.COSTS}, "계": cost["계"], "중간": {}}
|
||||
|
||||
|
||||
store.cm.mf.FLOW_RUN = _engine # 옛 엔진을 부르는 곳이 모두 흐름 로직을 흐름 셈으로(한 곳 갈래)
|
||||
|
||||
|
||||
def auto(key: str) -> dict | None:
|
||||
"""견본 입력 — 흐름 로직이면 「설계 때 정할 것」 예시값 · 아니면 None(옛 자동값)."""
|
||||
flow = store.logic(key)["logic"].get(FLOW)
|
||||
if not isinstance(flow, dict):
|
||||
return None
|
||||
return {
|
||||
"값": {d["port"]: (d.get("variable") or {}).get("example") for d in dc.design_inputs(flow)}
|
||||
}
|
||||
|
||||
|
||||
def calc(key: str, inputs: dict, row: dict | None = None) -> dict | None:
|
||||
@@ -168,7 +207,10 @@ def calc(key: str, inputs: dict, row: dict | None = None) -> dict | None:
|
||||
return None
|
||||
if not isinstance(flow, dict):
|
||||
return None
|
||||
got = run(flow, key, inputs)
|
||||
try:
|
||||
got = run(flow, key, inputs)
|
||||
except store.cm.mf.FormulaError as e:
|
||||
return {"ok": False, "flow": True, "reason": str(e)}
|
||||
names = {b["id"]: b for b in flow.get("boxes") or []}
|
||||
outputs = [
|
||||
{"box": i, "name": names[i].get("name"), "cost": (names[i].get("output") or {}).get("cost"),
|
||||
|
||||
Reference in New Issue
Block a user