"""구조물도 **양식형 항목** 읽기 — 양식 파일 + 구조물 제원 → 식 풀이기에 넘길 장 한 벌. 양식은 `resources/library_structure/.json`(4장 프로그램 기본 자리 · 명세 13장 식 칸 계약). 풀이는 여기 없음 — `B08_Quantity_Engine_Formula.evaluate_sheets`(TS 한 벌을 Node 로)가 풂. ⚠ 규격(높이·뒷길이·돌종류)마다 항목을 늘리지 않음 — 제원은 `vars` 로 들어가고 같은 식이 수량을 다시 냄(명세 16장 「한 조합 + 규격별 수량표」). """ from __future__ import annotations import json from pathlib import Path from typing import Any ROOT = Path(__file__).resolve().parents[1] TEMPLATE_DIR = ROOT / "resources" / "library_structure" def load_template(type_id: str) -> dict[str, Any] | None: """프로그램 기본 양식. 없는 종류면 `None` — 그 종류는 지금 전개(고정형 모양)로 섬.""" path = TEMPLATE_DIR / f"{type_id}.json" if not path.is_file(): return None return json.loads(path.read_text(encoding="utf-8")) def _typed(value: Any, default: Any) -> Any: """제원 값을 양식 기본값과 같은 꼴로 — 수 칸은 수, 글 칸은 글.""" if isinstance(default, (int, float)) and not isinstance(default, bool): try: return float(value) except (TypeError, ValueError): return default return str(value) def template_vars( template: dict[str, Any], structure: dict[str, Any], judged_slope: float, settings: dict[str, Any] | None = None, ) -> dict[str, Any]: """양식이 적은 제원 칸을 구조물·산출 조건에서 채움. 빈 칸은 양식 기본값. ⚠ 전면 기울기는 **전개가 판정한 값**을 받음 — 표준경사 판정(성절토·직고)은 식 언어 밖이라 판정 한 벌(`face_slope_ratio`)을 그대로 씀. """ options = structure.get("options") or {} values: dict[str, Any] = {} for name, spec in (template.get("vars") or {}).items(): default = spec.get("default") source = spec.get("source") if source == "judged_face_slope": values[name] = float(judged_slope) continue if source: values[name] = float(structure.get(source) or 0.0) continue if "option" in spec: raw = options.get(spec["option"]) else: raw = (settings or {}).get(spec.get("setting")) values[name] = default if raw in (None, "") else _typed(raw, default) return values def template_sheet(template: dict[str, Any], values: dict[str, Any]) -> dict[str, Any]: """식 풀이기가 받는 장 한 벌 — 줄·표는 양식 그대로, 제원만 끼움.""" return { "rows": template.get("rows") or [], "vars": values, "tables": template.get("tables") or {}, }