fix(M02): 흐름 셈 = 옛 셈 — 표 「·범위규칙」 줄 경계 말 · 검색어 조건 찾기 · 재료가 로직 입력 읽음 · 빈 단가 알림 · 고르기 글 값 그대로(PLAN 36-2 대조 49 → 8)
- main(sub7 a774b4e97 Model 덧) 받아 합침 · Compute 재료 조건 찾기는 sub7 의 틀 채우기 + 빈 단가 알림
- 남은 8: 표에 여럿 맞음 5(옛 find 의 값 칸 있는 줄만 거름 — lookup) · 빈 값이 든 식 3(옛 = 그 줄 비움 · 흐름 = 빈 칸 0)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KmELpdXFDRZHhfbGuRhSmL
This commit is contained in:
@@ -131,7 +131,10 @@ def _element_value(
|
||||
"unit": el.get("unit"),
|
||||
"inputs": env,
|
||||
}
|
||||
got = dv.slot_price(slot, ports.get(src.get("box"), {}).get(src.get("name")))
|
||||
value = ports.get(src.get("box"), {}).get(src.get("name"))
|
||||
if rule.get("field") == "검색어": # 틀의 자리마다 알약 값 → 채운 검색어 글(빈 자리면 None)
|
||||
value, slot["unit"] = _fill_template(rule, ports), el.get("unit")
|
||||
got = dv.slot_price(slot, value)
|
||||
if not got["ok"] and not got.get("blank") and el.get("default"):
|
||||
errors.append(
|
||||
f"「{box.get('name')} · {el.get('name')}」 {got['reason']} — 기본 품목으로 셈"
|
||||
@@ -160,6 +163,20 @@ def _element_value(
|
||||
return got.get("value")
|
||||
|
||||
|
||||
def _fill_template(rule: dict, ports: dict) -> str | None:
|
||||
"""재료 검색어 틀의 자리에 slots 알약 값 — 옛 엔진 fill 그대로(빈 자리 = None)."""
|
||||
env = {}
|
||||
for x in rule.get("slots") or []:
|
||||
src = x.get("from") or {}
|
||||
env[x.get("name")] = ports.get(src.get("box"), {}).get(src.get("name"))
|
||||
if any(v is None for v in env.values()):
|
||||
return None
|
||||
try:
|
||||
return store.cm.mf.fill(str(rule.get("template") or ""), env)
|
||||
except store.cm.mf.FormulaError:
|
||||
return None
|
||||
|
||||
|
||||
def _port(el: dict) -> str:
|
||||
"""요소 알약 이름 — Model `elementPort`(고정 아니면 자리 이름 slot · 없으면 name)."""
|
||||
slot = str(el.get("slot") or "").strip()
|
||||
@@ -349,6 +366,7 @@ def _lookup(rule: dict, block: Any, conds: dict) -> tuple[Any, str | None]:
|
||||
if out not in head and not two:
|
||||
return None, "오류"
|
||||
tests, ups = [], []
|
||||
rk = head.index(RANGE_RULE) if RANGE_RULE in head else None
|
||||
for c in rule.get("conds") or []:
|
||||
col, want = str(c.get("col")), _cond_of(conds, c.get("from") or {})
|
||||
if col in head:
|
||||
@@ -366,10 +384,17 @@ def _lookup(rule: dict, block: Any, conds: dict) -> tuple[Any, str | None]:
|
||||
low, high = _num_of(row[lo]), _num_of(row[hi])
|
||||
if low is not None and low == high: # 숫자 하나(아래 = 위) = 같음(브레인 정함)
|
||||
return x is not None and x == low
|
||||
word = str(row[rk] or "") if rk is not None else "" # 경계 — 이상 · 미만(Rule 같음)
|
||||
return (
|
||||
x is not None
|
||||
and (row[lo] is None or (low is not None and low < x))
|
||||
and (row[hi] is None or (high is not None and x <= high))
|
||||
and (
|
||||
row[lo] is None
|
||||
or (low is not None and (low <= x if word[:2] == "이상" else low < x))
|
||||
)
|
||||
and (
|
||||
row[hi] is None
|
||||
or (high is not None and (x < high if word[-2:] == "미만" else x <= high))
|
||||
)
|
||||
)
|
||||
|
||||
tests.append(fits)
|
||||
@@ -451,7 +476,12 @@ def _depends(lg: dict) -> list[tuple[str, str]]:
|
||||
for b in lg.get("boxes") or []:
|
||||
for el in (b.get("input") or {}).get("elements") or []:
|
||||
if el.get("mode") == "rule" and el.get("rule"):
|
||||
out.append(((el["rule"].get("from") or {}).get("box"), b["id"]))
|
||||
rule = el["rule"]
|
||||
srcs = [
|
||||
rule.get("from") or {},
|
||||
*[x.get("from") or {} for x in rule.get("slots") or []],
|
||||
]
|
||||
out += [(p.get("box"), b["id"]) for p in srcs]
|
||||
return out
|
||||
|
||||
|
||||
@@ -489,6 +519,7 @@ def _sheet_of(box: dict, arrived: dict, given: dict) -> dict:
|
||||
|
||||
|
||||
REST = "앞 조건이 안 맞아 쉬는 갈래"
|
||||
RANGE_RULE = "·범위규칙" # 표 블록 줄마다 범위 경계 규칙 칸(Values._table · Rule RANGE_RULE)
|
||||
NA_VALUE = "#N/A" # 함수 칸으로 가는 표 찾기 실패 — 칸에 NA() · 결과 오류일 때만 끊긴 곳(Eval 같음)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user