Merge remote-tracking branch 'origin/sub_laptop_4' into main_laptop_1
This commit is contained in:
@@ -1,21 +1,21 @@
|
||||
"""경쟁사 산근 → 우리 엔진 로직 줄 꼴 내보내기(PLAN 793-2a · 요구서_652 · eval 없음).
|
||||
|
||||
793-1 줄 나무(`M02_San_Stmate` · `M02_San_Est`) → 로직 JSON 한 개(`_틀.md` 7 장 GX 꼴 ·
|
||||
셈 = `master_formula.run` → `master_cut.engine`).
|
||||
|
||||
내보낸 로직 꼴:
|
||||
- 키 · 이름 · 결과단위 · 입력 [] · 끝전 · 조정 · 단계 [{이름, 단, 줄, 제외?, 원문, 검산}]
|
||||
- 중간 [{이름, 식, 표시?, 원문}] — STmate = 식(같은 이름 다시 대입 = `이름_2`) · EST = 얼린 값
|
||||
- 호표 [{종류 로직, 요소 None, 이름, 단위, 수량, 값묶음, 자원, 번지?, 합밖?, 자리?, 원문, 검산}]
|
||||
· 값묶음 = 「엑셀 단가 그대로」 · 자원 = 이음 열쇠 {꼴, 갈래, 코드?, 이름, 규격, 단위,
|
||||
단가 {L, M, S}, 비목?, 옮김?, M01?}
|
||||
(M01 = 1차 줄 판정 `M02_Hopyo_Row.m01_picks` 유일 짝 · 나중 [우리 단가로])
|
||||
- 덧줄 [{이름, 식, 비목, 번지?, 합밖?, 자리?, 원문, 검산}] — 율 · 특수 % · 앞줄 참조 · 값 줄
|
||||
- 글줄 [{자리, 글, 행?, 표지?}] — 셈 없는 원본 글(자리 = 그 앞 줄 이름 · `mid:이름` · "" = 맨 위)
|
||||
- 가져옴 {꼴, 코드, 검산 {노무비, 재료비, 경비, 계}, 계약?, 표지 [..]}
|
||||
검산 = 엑셀 값(줄마다 · 블록) · 표지 = 못 옮긴 까닭(0 이 목표).
|
||||
EST 는 블록 성분을 낸 줄만 합에 듦(나머지 줄 = 합밖) ·
|
||||
STmate 계약단가(낙찰률)는 B09 몫 — 가져옴.계약.
|
||||
793-1 줄 나무(`M02_San_Stmate` · `M02_San_Est`) → `{로직, 원본}` — 꼴 = 793-2 가져온 식 SK
|
||||
만들기 몸(`M02_Sangeun_Imported.py` 머리) · 로직 = `_틀.md` 7 장 꼴(셈 = `master_formula.run` →
|
||||
`master_cut.engine` · `요소` 는 SK 서버가 채움).
|
||||
- 로직 = {이름, 결과단위, 입력 [], 중간 [{이름, 식, 표시?}], 호표,
|
||||
덧줄 [{이름, 식, 비목, 번지?, 합밖?, 자리?}], 단계? [{이름, 단, 줄, 제외?}], 끝전, 조정?} ·
|
||||
STmate 변수 = 식(다시 대입 = `이름_2`) · EST 변수 = 얼린 값 · EST 는 블록 성분을 낸 줄만 합
|
||||
(나머지 = 합밖)
|
||||
- 호표 줄 = {종류 인력|재료|기계, 이름, 규격, 단위, 수량, 비목, 단가(엑셀), 이음(M01 키 | null)}
|
||||
(비목 하나 자원) | {종류 로직, 이름, 단위, 수량, 값묶음(엑셀), 이음 null}(기계 셋 · 산근 · 고정) ·
|
||||
번지? · 합밖? · 자리? · 덧칸 `자원` {꼴, 갈래, 코드?, 종류?, 이름, 규격, 단위, 단가 {L, M, S},
|
||||
비목?, 옮김?}(경쟁사 코드 · 엑셀 단가 원본 · `reprice`) · 이음 = 1차 줄 판정
|
||||
`M02_Hopyo_Row.m01_picks` 유일 짝(keys=True 일 때)
|
||||
- 원본 = {파일, 시트, 행 [처음, 끝], 갈래 STmate|EST, 엑셀금액 {노무비, 재료비, 경비, 계}(1 단위 ·
|
||||
계약 전), 글줄 [{행, 글, 자리?, 자리들?, 값?, 표지?}], 코드, 표지 [..], 계약? {낙찰률, 금액}}
|
||||
· 글줄 자리 = 셈 줄 이름 | `mid:이름` | `단계:이름` · 값 = 그 줄 엑셀 금액(계)
|
||||
표지 = 못 옮긴 까닭(0 이 목표) · STmate 계약단가(낙찰률)는 B09 몫.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -148,14 +148,27 @@ def bundle(src: dict) -> dict[str, Decimal]:
|
||||
return out
|
||||
|
||||
|
||||
def resource(name: str, unit: Any, qty: str, res: dict, link: str | None) -> dict:
|
||||
"""자원 → 호표 줄 — 비목 하나인 인력 · 재료 · 기계 = 단가 줄 · 그 밖 = 로직 값묶음 줄."""
|
||||
one = {"이름": name, "규격": res.get("규격") or "", "단위": unit or "", "수량": qty}
|
||||
if res.get("비목") and res["갈래"] in ("인력", "재료", "기계"):
|
||||
price = Decimal(str(res["단가"].get(res["비목"]) or 0))
|
||||
one |= {"종류": res["갈래"], "비목": COMP[res.get("옮김") or res["비목"]], "단가": price}
|
||||
return {**one, "이음": link, "자원": res}
|
||||
return {**one, "종류": "로직", "값묶음": bundle(res), "이음": None, "자원": res}
|
||||
|
||||
|
||||
def reprice(logic: dict, where: dict, price: dict[str, float]) -> int:
|
||||
"""단가 바꿈 — 자원이 where 칸과 같은 호표 줄 단가 {L, M, S} 고침 · 값묶음 다시 · 고친 줄 수."""
|
||||
"""단가 바꿈 — where 칸이 같은 자원 단가 {L, M, S} 고침 · 줄 단가 · 값묶음 다시 · 고친 줄 수."""
|
||||
n = 0
|
||||
for item in logic.get("호표", []):
|
||||
src = item.get("자원") or {}
|
||||
if all(src.get(k) == v for k, v in where.items()):
|
||||
src["단가"] = {**src["단가"], **price}
|
||||
item["값묶음"] = bundle(src)
|
||||
if "단가" in item:
|
||||
item["단가"] = Decimal(str(src["단가"].get(src["비목"]) or 0))
|
||||
else:
|
||||
item["값묶음"] = bundle(src)
|
||||
n += 1
|
||||
return n
|
||||
|
||||
@@ -173,46 +186,52 @@ def _m01(kind: str, src: dict) -> str | None:
|
||||
|
||||
# ── 내보낼 로직 틀 ─────────────────────────────────────────────────────
|
||||
class Out:
|
||||
def __init__(self, key: str, name: str, unit: str, form: str, code: Any) -> None:
|
||||
def __init__(self, name: str, unit: str, form: str, code: Any) -> None:
|
||||
self.names = Names()
|
||||
self.mid: list[dict] = []
|
||||
self.items: list[dict] = []
|
||||
self.adds: list[dict] = []
|
||||
self.steps: list[dict] = []
|
||||
self.texts: list[dict] = []
|
||||
self.texts: list[dict] = [] # 원본 글줄(원문 차례)
|
||||
self.at: dict[Any, dict] = {} # 행 → 글줄
|
||||
self.marks: list[str] = []
|
||||
self.step_src: dict[str, dict] = {} # 단계 이름 → {원문, 검산}(엔진 단계 칸 밖)
|
||||
self.last = "" # 글줄 자리
|
||||
self.row = {"키": key, "이름": name or key, "결과단위": f"원/{unit or '식'}", "입력": []}
|
||||
self.head = {"꼴": form, "코드": code}
|
||||
self.row = {"이름": name or str(code), "결과단위": f"원/{unit or '식'}", "입력": []}
|
||||
self.head = {"갈래": form, "코드": code}
|
||||
|
||||
def text_line(self, glyph: str, at: Any = None, mark: str | None = None) -> None:
|
||||
where = "행" if self.head["꼴"] == "STmate" else "차례"
|
||||
one = {"자리": self.last, "글": glyph} | ({where: at} if at is not None else {})
|
||||
self.texts.append(one | ({"표지": mark} if mark else {}))
|
||||
def glyph(self, at: Any, glyph: str, where: str | None = None, value: Any = None, mark=None):
|
||||
"""원본 글줄 한 줄(같은 행이면 자리만 더함)."""
|
||||
one = self.at.get(at)
|
||||
if one is None:
|
||||
one = {"행": at, "글": glyph}
|
||||
self.texts.append(one)
|
||||
self.at[at] = one
|
||||
if where and "자리" in one:
|
||||
one.setdefault("자리들", [one["자리"]]).append(where)
|
||||
elif where:
|
||||
one["자리"] = where
|
||||
if value is not None:
|
||||
one["값"] = value
|
||||
if mark:
|
||||
one["표지"] = mark
|
||||
self.marks.append(f"{at}: {mark}")
|
||||
|
||||
def middle(self, name: str, formula: str, show: int | None, source: dict) -> None:
|
||||
def middle(self, name: str, formula: str, show: int | None, at: Any, glyph: str) -> None:
|
||||
self.mid.append({"이름": name, "식": formula, **({"표시": show} if show else {})})
|
||||
self.mid[-1]["원문"] = source
|
||||
self.last = f"mid:{name}"
|
||||
self.glyph(at, glyph, f"mid:{name}")
|
||||
|
||||
def add_line(self, one: dict, item: bool) -> dict:
|
||||
def add_line(self, one: dict, item: bool, at: Any, glyph: str, value: Any) -> dict:
|
||||
(self.items if item else self.adds).append(one)
|
||||
self.last = one["이름"]
|
||||
self.glyph(at, glyph, one["이름"], value)
|
||||
return one
|
||||
|
||||
def done(self, end: str, adjust: dict | None, check: dict, **more: Any) -> dict:
|
||||
out = {**self.row, "중간": self.mid, "호표": self.items, "덧줄": self.adds}
|
||||
if self.steps:
|
||||
out["단계"] = self.steps
|
||||
out |= {"끝전": end, **({"조정": adjust} if adjust else {})}
|
||||
out |= {"글줄": self.texts, "가져옴": {**self.head, "검산": check, "표지": self.marks}}
|
||||
if self.step_src:
|
||||
out["가져옴"]["단계"] = self.step_src
|
||||
out["가져옴"] |= more
|
||||
return out
|
||||
def done(self, end: str, adjust: dict | None, check: dict, sheet: str, file: str, **more):
|
||||
logic = {**self.row, "중간": self.mid, "호표": self.items, "덧줄": self.adds}
|
||||
logic |= {"단계": self.steps} if self.steps else {}
|
||||
logic |= {"끝전": end, **({"조정": adjust} if adjust else {})}
|
||||
rows = [x["행"] for x in self.texts if isinstance(x["행"], int)] or [0]
|
||||
source = {"파일": file, "시트": sheet, "행": [min(rows), max(rows)], **self.head}
|
||||
source |= {"엑셀금액": check, "글줄": self.texts, "표지": self.marks, **more}
|
||||
return {"로직": logic, "원본": source}
|
||||
|
||||
|
||||
def _money(d: dict | None) -> dict[str, Any]:
|
||||
@@ -245,10 +264,6 @@ class _Stm:
|
||||
self.out: dict[str, int] = {} # 제외 단계 줄 → 그 계 줄까지 줄 수(합에서 빠지는 때)
|
||||
self.fix: list[tuple[dict, int]] = [] # 누계 % 덧줄 · 그때 줄 수
|
||||
|
||||
def xl(self, at: Any) -> dict:
|
||||
ln = self.rows.get(at) or {}
|
||||
return {c: ln.get(k) or 0 for c, k in (("L", "D"), ("M", "E"), ("S", "F"))}
|
||||
|
||||
def brackets(self, node: tuple, src: dict, kept: dict) -> None:
|
||||
"""끼움 `[Q=0.208]` → 중간(왼쪽부터 · 원문 차례)."""
|
||||
kind = node[0]
|
||||
@@ -259,7 +274,7 @@ class _Stm:
|
||||
eng = self.o.names.line(node[1].lower())
|
||||
self.names[node[1].lower()] = eng
|
||||
kept[id(node)] = eng
|
||||
self.o.middle(eng, body, None, src)
|
||||
self.o.middle(eng, body, None, src["행"], src["글"])
|
||||
elif kind == "셈":
|
||||
self.brackets(node[2], src, kept)
|
||||
self.brackets(node[3], src, kept)
|
||||
@@ -288,14 +303,14 @@ class _Stm:
|
||||
except (ex.ExprError, EmitError) as error:
|
||||
if part["이름"] is None:
|
||||
continue
|
||||
self.o.text_line(node["글"], src["행"], f"셈 못 함 — {error}")
|
||||
self.o.glyph(src["행"], src["글"], mark=f"셈 못 함 — {error}")
|
||||
return
|
||||
if part["이름"] is None:
|
||||
continue
|
||||
self.V[part["이름"]] = ex.rnd(v, 2) if part["찍기"] else v
|
||||
eng = self.o.names.line(part["이름"])
|
||||
self.names[part["이름"]] = eng
|
||||
self.o.middle(eng, body, 2 if part["찍기"] else None, src)
|
||||
self.o.middle(eng, body, 2 if part["찍기"] else None, src["행"], src["글"])
|
||||
|
||||
def total(self, node: dict, src: dict) -> None:
|
||||
o = self.o
|
||||
@@ -308,27 +323,26 @@ class _Stm:
|
||||
self.open = keep if node["제외"] else [*keep, (node["단"], mine)]
|
||||
for n in mine if node["제외"] else []:
|
||||
self.out[n] = len(self.order)
|
||||
o.step_src[name] = {"원문": src, "검산": _money(self.xl(src["행"]))}
|
||||
o.glyph(src["행"], src["글"], f"단계:{name}", self.rows.get(src["행"], {}).get("C"))
|
||||
o.steps.append(step)
|
||||
self.pending = []
|
||||
if node["누계번지"]:
|
||||
self.tsum[node["누계번지"]] = name
|
||||
self.last_step = name
|
||||
o.last = f"단계:{name}"
|
||||
|
||||
def line(self, one: dict, node: dict, item: bool) -> None:
|
||||
def line(self, one: dict, node: dict, item: bool, src: dict) -> None:
|
||||
if node.get("번지") and node["번지"].startswith("A"):
|
||||
one["번지"] = node["번지"]
|
||||
self.addr.add(node["번지"])
|
||||
money = one.get("값묶음") or {}
|
||||
comps = {c for c in COMP if money.get(COMP[c])} if item else {_CODE[one["비목"]]}
|
||||
comps = {c for c in COMP if money.get(COMP[c])} if "값묶음" in one else {_CODE[one["비목"]]}
|
||||
self.calls[one["이름"]] = (f"줄.'{one['이름']}'" if item else one["이름"], comps)
|
||||
if node.get("빼기"):
|
||||
one["합밖"] = True
|
||||
else:
|
||||
self.pending.append(one["이름"])
|
||||
self.order.append(one["이름"])
|
||||
self.o.add_line(one, item)
|
||||
self.o.add_line(one, item, src["행"], src["글"], self.rows.get(src["행"], {}).get("C"))
|
||||
|
||||
def ref(self, node: dict, src: dict, cf: str) -> None:
|
||||
o, code = self.o, node["자원"]["코드"]
|
||||
@@ -336,7 +350,6 @@ class _Stm:
|
||||
unt = (pr.get("meta") or {}).get("UNT")
|
||||
one_, to = node["자원"]["비목"], node["자원"]["옮김"]
|
||||
name = _label(node) or str(pr.get("이름") or code)
|
||||
xl = self.xl(src["행"])
|
||||
if unt in ev.SPECIAL: # 특수 % — 처음부터 비목 누계 · 앞 계표시
|
||||
dst = to or {"L": "L", "M": "M", "S": "S"}.get(code[0])
|
||||
if unt == "T%":
|
||||
@@ -346,18 +359,18 @@ class _Stm:
|
||||
else:
|
||||
formula = f"{_SUM.format(unt[0])} * ({cf}) / 100"
|
||||
one = {"이름": o.names.line(name), "식": formula, "비목": COMP[dst]}
|
||||
one |= {"원문": src, "검산": {COMP[dst]: xl[dst]}}
|
||||
self.fix.append((one, len(self.order)))
|
||||
return self.line(one, node, False)
|
||||
return self.line(one, node, False, src)
|
||||
res = {"꼴": "STmate", "갈래": KIND.get(code[0], "고정"), "코드": code}
|
||||
res |= {k: pr.get(k) for k in ("이름", "규격", "단위")}
|
||||
res |= {"단가": {c: pr.get(c) or 0 for c in COMP}}
|
||||
sole = [c for c in COMP if res["단가"][c]]
|
||||
if not one_ and len(sole) == 1: # 비목 꼬리 없어도 값 든 비목 하나면 단가 줄(셈 같음)
|
||||
one_, to = sole[0], None
|
||||
res |= {"비목": one_, "옮김": to} if one_ else {}
|
||||
if self.keys and (m01 := _m01(res["갈래"], res)):
|
||||
res["M01"] = m01
|
||||
one = {"종류": "로직", "요소": None, "이름": o.names.item(name)}
|
||||
one |= {"단위": pr.get("단위") or "", "수량": cf, "값묶음": bundle(res), "자원": res}
|
||||
self.line(one | {"원문": src, "검산": _money(xl)}, node, True)
|
||||
link = _m01(res["갈래"], res) if self.keys else None
|
||||
one = resource(o.names.item(name), pr.get("단위"), cf, res, link)
|
||||
self.line(one, node, True, src)
|
||||
|
||||
def rate(self, node: dict, src: dict, cf: str) -> None:
|
||||
rate, o = node["율"], self.o
|
||||
@@ -389,14 +402,12 @@ class _Stm:
|
||||
else:
|
||||
parts = [(c, base(c)) for c in COMP]
|
||||
label = _label(node) or "율"
|
||||
xl = self.xl(src["행"])
|
||||
for c, b in parts:
|
||||
nm = o.names.line(label if len(parts) == 1 else f"{label}_{COMP[c]}")
|
||||
one = {"이름": nm, "식": f"({b}) * {pct}", "비목": COMP[c]}
|
||||
one |= {"원문": src, "검산": {COMP[c]: xl[c]}}
|
||||
if "@합" in b:
|
||||
self.fix.append((one, len(self.order)))
|
||||
self.line(one, node, False)
|
||||
self.line(one, node, False, src)
|
||||
|
||||
def finish(self) -> None:
|
||||
"""누계 % 밑 = 그 줄 앞까지 합 — 엔진 비목 합(호표 다 · 앞 덧줄 · 제외 단계 뺌)에서
|
||||
@@ -424,18 +435,20 @@ def _cols(row: dict) -> dict[str, Any]:
|
||||
return _money({"L": row["D"], "M": row["E"], "S": row["F"]}) | {"계": row["C"] or 0}
|
||||
|
||||
|
||||
def stmate(block: dict, nodes: list[dict], prices: dict, rule: str, key: str, keys: bool = False):
|
||||
"""STmate 블록(`M02_San_Book.stmate_blocks` 한 개) + 줄 나무 + 같은 책 단가 → 로직 JSON.
|
||||
rule = 블록 끝전(비목버림 | 합버림_큰나머지 · 파일 설정) · keys = 자원 M01 키 찾기."""
|
||||
def stmate(
|
||||
block: dict, nodes: list[dict], prices: dict, rule: str, keys: bool = False, file: str = ""
|
||||
) -> dict:
|
||||
"""STmate 블록(`M02_San_Book.stmate_blocks` 한 개) + 줄 나무 + 같은 책 단가 → {로직, 원본}.
|
||||
rule = 블록 끝전(비목버림 | 합버림_큰나머지 · 파일 설정) · keys = 자원 M01 키(이음) 찾기."""
|
||||
me = prices.get(block["코드"]) or {}
|
||||
meta = me.get("meta") or {}
|
||||
o = Out(key, block.get("이름"), me.get("단위"), "STmate", block["코드"])
|
||||
o = Out(block.get("이름"), me.get("단위"), "STmate", block["코드"])
|
||||
st = _Stm(o, block, prices, keys)
|
||||
for node in nodes:
|
||||
kind, src = node["종류"], {"행": node.get("행"), "글": node.get("글") or ""}
|
||||
if kind in ("빈", "글"):
|
||||
if src["글"].strip():
|
||||
o.text_line(src["글"], src["행"])
|
||||
o.glyph(src["행"], src["글"])
|
||||
elif kind == "대입":
|
||||
st.assign(node, src)
|
||||
elif kind == "계":
|
||||
@@ -450,7 +463,7 @@ def stmate(block: dict, nodes: list[dict], prices: dict, rule: str, key: str, ke
|
||||
cf = st.coef(node["식"], src)
|
||||
(st.rate if kind == "율" else st.ref)(node, src, cf)
|
||||
except (ex.ExprError, EmitError) as error:
|
||||
o.text_line(src["글"], src["행"], f"셈 못 함 — {error}")
|
||||
o.glyph(src["행"], src["글"], mark=f"셈 못 함 — {error}")
|
||||
try:
|
||||
st.finish()
|
||||
except EmitError as error:
|
||||
@@ -464,14 +477,14 @@ def stmate(block: dict, nodes: list[dict], prices: dict, rule: str, key: str, ke
|
||||
if meta.get("UC") == "T" and meta.get("NAG"): # 계약단가 = B09 몫(엔진 밖)
|
||||
more["계약"] = {"낙찰률": float(meta["NAG"]), "금액": _cols(block["머리"])}
|
||||
end = "큰나머지" if rule.startswith("합버림") else "비목버림"
|
||||
return o.done(end, adjust, _cols(kye), **more)
|
||||
return o.done(end, adjust, _cols(kye), "단가산출근거", file, **more)
|
||||
|
||||
|
||||
# ── EST ────────────────────────────────────────────────────────────────
|
||||
_VAR = re.compile(r"([A-Za-z][A-Za-z0-9_]*)\s*(?:\([^)]*\))?\s*=")
|
||||
|
||||
|
||||
def _est_res(role: dict, value: float, comp: str | None, keys: bool) -> dict:
|
||||
def _est_res(role: dict, value: float, comp: str | None) -> dict:
|
||||
"""EST 단가 토큰 정체 → 자원 이음 열쇠(옮김 = 성분 비목이 단가 비목과 다를 때)."""
|
||||
p = role["정체"]
|
||||
pc = p["비목"] if p["비목"] in COMP else (comp or "S")
|
||||
@@ -479,19 +492,16 @@ def _est_res(role: dict, value: float, comp: str | None, keys: bool) -> dict:
|
||||
res |= {"이름": p["이름"], "규격": p["규격"], "단위": None}
|
||||
res |= {"단가": {pc: value}}
|
||||
res |= {"비목": pc, "옮김": comp if comp and comp != pc else None, "열쇠비목": p["비목"]}
|
||||
if role.get("모호"):
|
||||
res["모호"] = True
|
||||
if keys and (m01 := _m01(res["갈래"], res)):
|
||||
res["M01"] = m01
|
||||
return res
|
||||
return res | ({"모호": True} if role.get("모호") else {})
|
||||
|
||||
|
||||
def est(block: dict, lines: list[dict], want: dict, key: str, keys: bool = False) -> dict:
|
||||
def est(block: dict, lines: list[dict], want: dict, keys: bool = False, file: str = "") -> dict:
|
||||
"""EST 블록(`M02_San_Book.est_blocks` 한 개) + 복원 줄(`M02_San_Est.parse_block`) +
|
||||
총괄표 성분 want {T, L, M, S} → 로직 JSON · 성분을 낸 줄만 합(나머지 = 합밖)."""
|
||||
총괄표 성분 want {T, L, M, S} → {로직, 원본} · 성분을 낸 줄만 합(나머지 = 합밖)."""
|
||||
des = ev.designate(lines, want)
|
||||
mine = {k: c for c, k in des.items() if isinstance(k, int)}
|
||||
o = Out(key, block.get("이름"), block.get("단위"), "EST", block.get("번"))
|
||||
o = Out(block.get("이름"), block.get("단위"), "EST", block.get("번"))
|
||||
rows = block.get("글행") or []
|
||||
for c, k in des.items():
|
||||
if k is None:
|
||||
o.marks.append(f"성분 {COMP[c]} {want[c]} 을 낸 줄 없음")
|
||||
@@ -499,32 +509,32 @@ def est(block: dict, lines: list[dict], want: dict, key: str, keys: bool = False
|
||||
ref: dict[int, str] = {} # 차례 → 엔진 부름 글(앞줄 · 숨은 합)
|
||||
for L in lines:
|
||||
k, form, kind = L["차례"], L["꼴"], L.get("종류")
|
||||
src = {"차례": k, "글": L["원글"]}
|
||||
at, glyph = rows[k] if k < len(rows) else k, L["원글"]
|
||||
comp = mine.get(k)
|
||||
if form == "빈":
|
||||
continue
|
||||
if form == "변수" and L.get("값") is not None:
|
||||
m = _VAR.search(L["원글"])
|
||||
eng = o.names.line(m.group(1) if m else "변수")
|
||||
o.middle(eng, num(L["값"]), None, src) # 얼린 값(금액엔 보인 값이 박힘)
|
||||
o.middle(eng, num(L["값"]), None, at, glyph) # 얼린 값(금액엔 보인 값이 박힘)
|
||||
continue
|
||||
if form not in ("돈", "값"):
|
||||
o.text_line(L["원글"], k)
|
||||
o.glyph(at, glyph)
|
||||
continue
|
||||
head = {"원문": src, "검산": {COMP[comp or L.get("비목") or "S"]: L["값"]}}
|
||||
head |= {} if comp else {"합밖": True}
|
||||
head = {} if comp else {"합밖": True}
|
||||
try:
|
||||
place = _place(L.get("규칙"))
|
||||
if k not in val:
|
||||
raise EmitError("보인 값이 되는 식 · 자리 못 찾음 — 보인 값으로 얼림")
|
||||
if kind == "단가줄":
|
||||
at, role = next((i, r) for i, r in L["역할"].items() if r["갈래"] == "단가")
|
||||
price = next(n[1] for n in ex.numbers(L["식"]) if n[2] == at)
|
||||
res = _est_res(role, price, comp, keys)
|
||||
one = {"종류": "로직", "요소": None, "이름": o.names.item(L.get("라벨") or "")}
|
||||
one |= {"단위": "", "수량": text(L["식"], {}, {at: "1"}), "값묶음": bundle(res)}
|
||||
one |= {"자원": res, **head, **({"자리": place} if place else {})}
|
||||
o.add_line(one, True)
|
||||
i, role = next((i, r) for i, r in L["역할"].items() if r["갈래"] == "단가")
|
||||
price = next(n[1] for n in ex.numbers(L["식"]) if n[2] == i)
|
||||
res = _est_res(role, price, comp)
|
||||
link = _m01(res["갈래"], res) if keys else None
|
||||
qty = text(L["식"], {}, {i: "1"})
|
||||
one = resource(o.names.item(L.get("라벨") or ""), None, qty, res, link)
|
||||
one |= {**head, **({"자리": place} if place else {})}
|
||||
o.add_line(one, True, at, glyph, L["값"])
|
||||
ref[k] = f"줄.'{one['이름']}'"
|
||||
continue
|
||||
if kind == "값줄":
|
||||
@@ -534,12 +544,12 @@ def est(block: dict, lines: list[dict], want: dict, key: str, keys: bool = False
|
||||
swap = {i: ref[r["줄"]] for i, r in L["역할"].items() if r.get("줄") in ref}
|
||||
formula = text(L["식"], {}, swap)
|
||||
except EmitError as error:
|
||||
o.marks.append(f"{k}: {error}")
|
||||
o.glyph(at, glyph, mark=str(error))
|
||||
formula, place = num(L["값"]), None
|
||||
name = o.names.line(L.get("라벨") or "줄")
|
||||
one = {"이름": name, "식": formula, "비목": COMP[comp or L.get("비목") or "S"]}
|
||||
o.add_line(one | head | ({"자리": place} if place else {}), False)
|
||||
o.add_line(one | head | ({"자리": place} if place else {}), False, at, glyph, L["값"])
|
||||
if k in val:
|
||||
ref[k] = name
|
||||
check = _money(want) | {"계": want["T"]}
|
||||
return o.done("비목버림", None, check)
|
||||
return o.done("비목버림", None, check, "단가산출", file)
|
||||
|
||||
Reference in New Issue
Block a user