feat(785-2): 옵션값 읽기 Bind · 검산 판정 Solve · master_auto.defaults — 1차

- 새 M02_Hopyo_Bind: B1 규격 · 품명 괄호 · B6 같은 호표 레미콘 a-b-c · B2 선택값 줄 + 글에 없는 켜기 칸 = 아님 · B3 상수(기호표 · 이름 · 90˚ · 표 칸 = 기호) · B4 대입식(분자 · 분모 자리 + 단위) · B5 표 거꾸로 + 감률 배수 · 출처 꼬리표 · 엇갈림 · 안씀 · 입력필요 · 비움 · 기본 제안 · 엔진 몫 quantities(품만)
- 새 M02_Hopyo_Solve: 후보마다 바인딩 → 줄 짝(L · X · M · R) → 품 같음(자릿수 반올림 폭 · 0.5 %) · 절 · 블록 판정 · 덧 줄 Units · 금액 참고(입력 필요 없을 때 엔진 한 번)
- master_auto.defaults: 기본 칸 › 고르기 첫째 › 가드 0 › 0 을 품은 범위 0 › 표 첫 줄 › None(새 맞춤만 부름 · values · run_line 그대로)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-04 22:15:36 +09:00
co-authored by Claude Opus 5.5
parent c7d2e99a25
commit bf140c29fa
3 changed files with 740 additions and 0 deletions
@@ -88,6 +88,49 @@ def _lowest(master: mf.Master, uses: list):
return (both or next((s for s in sets if s), [None]))[0]
def _first_row(master: mf.Master, uses: list):
"""찾기 조건 칸의 표 첫 줄 값 — 범위 줄이면 아래 끝(열린 아래 끝 = 위 끝) · 빈 칸 줄은 건넘."""
for ref, cond in uses:
try:
rows = master.get(ref).get("줄", [])
except mf.FormulaError:
continue
for r in rows:
got = r.get(cond)
if isinstance(got, list):
got = next((v for v in got if v is not None), None)
if got is not None:
return got
return None
def _holds_zero(span) -> bool:
low, high = span[0], span[1]
return (low is None or Decimal(str(low)) <= 0) and (high is None or Decimal(str(high)) >= 0)
def defaults(master: mf.Master, row: dict) -> dict:
"""「기본」 제안(PLAN 785-2 · 639-1a) — 「기본」 칸 › 고르기 첫째 › 가드 0 › 0 을 품은 범위 0 ›
찾기 조건 표 첫 줄 › None(못 정함 = 사용자 입력). 1 을 지어 넣지 않음 · `values` 와 따로."""
specs = mf.inputs_of(row) if isinstance(row.get("흐름"), dict) else row.get("입력", [])
finds = {} if isinstance(row.get("흐름"), dict) else _uses(row)[0]
guard = guards(row)
out = {}
for spec in specs:
name, span = spec["이름"], spec.get("범위")
if spec.get("기본") not in (None, ""):
out[name] = spec["기본"]
elif spec.get("고르기"):
out[name] = spec["고르기"][0]
elif name in guard:
out[name] = Decimal(0)
elif span and _holds_zero(span):
out[name] = Decimal(0)
else:
out[name] = _first_row(master, finds.get(name, []))
return out
def values(master: mf.Master, row: dict) -> dict:
"""로직 줄 하나의 입력마다 자동값 · 흐름 로직은 「설계 때 정할 것」 예시값."""
if isinstance(row.get("흐름"), dict):