refactor(812-1): 옛 엑셀 엔진 걷기 2 · 실무 11 금액 100 % · NativeEst 자리 dict 묶음 고침 · 옛 시험 정리
- M02_Doc_NativeEst.triple: 세 줄 수량 식이 같은지 = repr 로 맞댐(자리 규칙 dict 가 set 에 안 들어가 TypeError — 엑셀 줄은 보인 값이 반올림 자리를 타 원파일에 없던 꼴 · 812-3 끝나 브레인이 맡김) - 엑셀 읽기기: 절 소계 덧셈이 뺀 오타 줄 = 비목 없음(블록 금액도 그래야 맞을 때만) · 세 줄 계 금액 칸 비목 하나 = 옮김 · 소계 61 = 금액 칸 비목 하나 · 「.1」 수 · 총괄표 당초 칸 표지 · STmate 엑셀 줄 금액 · 계 꼬리(검산 줄) - 화면: 가져온 식 규격 칸 꼬리표 = 원파일 · 엑셀 갈림(line_stack_sourced) - 시험: 793_1 지움(옛 EST · STmate 엑셀 글 추정 엔진 · 812_1 골든이 대신) · 793_2_san_emit EST 시험 지움(STmate 남김) · 797_1a 옛 표지 ① ② · 줄 단위 합격 · 표본 밖 수 · 버림1 감시 지움(옛 엔진) · 810_1 (c) 엑셀 엔진 대조 지움 · 793_2 실무 블록 · 793_3b 끝전 = 새 길 · 812_1 금액 엇갈림 없음 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -52,7 +52,10 @@ def pack(got: dict, name: str) -> dict[str, Any]:
|
||||
out: dict[str, Any] = {"꼴": got["꼴"], "파일": name, "표지": got.get("표지") or []}
|
||||
out |= {"엑셀": True} if got.get("엑셀") else {} # 812-1 엑셀 읽기기(`M02_San_Xlsx`) — 같은 꼴
|
||||
head = ("코드", "번", "이름", "규격", "단위", "저장")
|
||||
if got.get("엑셀"): # 엑셀 읽기기 — 줄 행 = 시트 행(원문 카드 · 옛 엑셀 길과 같은 자리)
|
||||
if got.get(
|
||||
"엑셀"
|
||||
): # 엑셀 읽기기 — 줄 행 = 시트 행(원문 카드 · 옛 엑셀 길과 같은 자리) · 블록 표지
|
||||
head += ("표지", "몸", "꼬리")
|
||||
got = {**got, "산근": [_rows(b) for b in got["산근"]]}
|
||||
if got["꼴"] == "EST":
|
||||
out["산근"] = [
|
||||
@@ -106,27 +109,29 @@ def emit(saved: dict, no: int, keys: bool = True) -> dict[str, Any]:
|
||||
names = {b["코드"]: n for n, b in numbers(saved).items()}
|
||||
out = ne.block(blk, int(no), keys, saved["파일"], names)
|
||||
out["원본"] |= {"원코드": blk["코드"]} | ({"규격": blk["규격"]} if blk.get("규격") else {})
|
||||
return _excel(saved, out)
|
||||
return _excel(saved, out, blk)
|
||||
from M02_MasterTemplete import M02_San_Stmate as stm
|
||||
|
||||
nodes = [{"행": ln["행"], "글": ln["글"], **stm.parse_line(ln["글"])} for ln in blk["줄"]]
|
||||
saved_amt = blk.get("저장") or {}
|
||||
head = {"C": saved_amt.get("T"), "D": saved_amt.get("L"), "E": saved_amt.get("M")}
|
||||
head["F"] = saved_amt.get("S")
|
||||
block = {"코드": blk["코드"], "이름": blk.get("이름"), "몸": [], "꼬리": [], "머리": head}
|
||||
block = {"코드": blk["코드"], "이름": blk.get("이름"), "머리": head}
|
||||
block |= {"몸": blk.get("몸") or [], "꼬리": blk.get("꼬리") or []} # 엑셀 = 줄 금액 · 계 꼬리
|
||||
out = em.stmate(block, nodes, saved["단가"], saved["끝전"], keys, saved["파일"])
|
||||
marks = sum(1 for one in out["원본"]["글줄"] if one.get("표지"))
|
||||
sure = len(out["로직"]["호표"]) + len(out["로직"].get("덧줄") or []) + len(out["로직"]["중간"])
|
||||
out["원본"] |= {"원파일": True, "갈래": "STmate", "확정": {"확정": sure, "표지": marks}}
|
||||
return _excel(saved, out)
|
||||
return _excel(saved, out, blk)
|
||||
|
||||
|
||||
def _excel(saved: dict, out: dict) -> dict[str, Any]:
|
||||
def _excel(saved: dict, out: dict, blk: dict) -> dict[str, Any]:
|
||||
"""엑셀 읽기기 꼴(812-1) — 원본 `원파일` 거짓 · `엑셀` 참(화면 꼬리표 「엑셀」 · 원코드 = 단산 번)."""
|
||||
if saved.get("엑셀"):
|
||||
out["원본"] |= {"원파일": False, "엑셀": True}
|
||||
out["원본"] |= {"시트": "단가산출"} if saved["꼴"] == "EST" else {}
|
||||
out["원본"].pop("원코드", None)
|
||||
out["원본"]["표지"] += [m for m in blk.get("표지") or [] if m.startswith("참고 · ")]
|
||||
return out
|
||||
|
||||
|
||||
|
||||
@@ -302,7 +302,7 @@ class Block:
|
||||
"""기계 · 산근 · 견적 세 줄 → 로직 값묶음 한 줄(수량 식 · 자리 같을 때) · 아니면 줄마다."""
|
||||
got = [self.money(ln) for ln in rows]
|
||||
parts = [ln["비목"] for ln in rows]
|
||||
same = all(got) and len({g for g in got}) == 1 and sorted(parts) == ["L", "M", "S"]
|
||||
same = all(got) and len({repr(g) for g in got}) == 1 and sorted(parts) == ["L", "M", "S"]
|
||||
if not same:
|
||||
for ln, g in zip(rows, got):
|
||||
self.machine_line(ln, g)
|
||||
|
||||
@@ -141,8 +141,9 @@ def resources(sheets: dict[str, list]) -> dict[str, list[dict[str, Any]]]:
|
||||
got = []
|
||||
for one in _table(sheets.get(sheet) or [], ()):
|
||||
r = list(one["줄"]) + [None] * 30
|
||||
vals = {k: float(v or 0) for k, v in book.applied(r).items()}
|
||||
got.append({**_drop(one), "표": sheet, "값": vals})
|
||||
vals, note = book.applied_how(r)
|
||||
vals = {k: float(v or 0) for k, v in vals.items()}
|
||||
got.append({**_drop(one), "표": sheet, "값": vals} | ({"칸": note} if note else {}))
|
||||
out[kind] = got
|
||||
return out
|
||||
|
||||
|
||||
@@ -300,6 +300,45 @@ class Lines:
|
||||
self.plain(ln)
|
||||
return self.done(ln)
|
||||
|
||||
def sections(self, saved: dict) -> None:
|
||||
"""절 소계(가 · 나 … 머리 아래 합계 줄 「노무비 : a + b = X」)가 뺀 줄 하나 = 합에 안 든 줄(비목 없음) —
|
||||
절(앞 숫자 머리부터) 안 그 비목 줄 결과 합 − X 가 꼭 한 줄 값이고 나머지 줄 값은 모두 덧셈 글에 있을
|
||||
때만 · 블록 금액도 그 줄을 빼야 맞을 때만(엑셀 글 덧셈 · 원파일 SCheck 0)."""
|
||||
lines, start = self.lines, 0
|
||||
for i, ln in enumerate(lines):
|
||||
text = ln["보임"]
|
||||
if ln["단"] == 1 and re.match(r"^\s*\d", text):
|
||||
start = i
|
||||
if not (ln["합계"] and ln["비목"] in ("L", "M", "S") and ln["결과"] and "+" in text):
|
||||
continue
|
||||
head = next((k for k in range(i - 1, start - 1, -1) if lines[k]["단"] == 1), None)
|
||||
if head is None or not re.match(r"^\s*[가-하]", lines[head]["보임"]):
|
||||
continue
|
||||
part, want = ln["비목"], ln["결과"][-1]
|
||||
kids = [
|
||||
x for x in lines[start:head] if x["비목"] == part and x["결과"] and not x["합계"]
|
||||
]
|
||||
kids += [
|
||||
x for x in lines[start:head] if x["비목"] == part and x["줄참조"] and not x["결과"]
|
||||
]
|
||||
value = {id(x): (x["결과"] or x["줄참조"])[-1] for x in kids}
|
||||
extra = sum(value.values()) - want
|
||||
odd = [x for x in kids if abs(value[id(x)] - extra) < 0.5]
|
||||
colon = _COLON.search(text)
|
||||
adds = [v for _, _, v in _nums(text, colon.end() if colon else 0, text.rfind("="))]
|
||||
rest = [value[id(x)] for x in kids if odd and x is not odd[0]]
|
||||
listed = all(any(_close(v, a) for a in adds) for v in rest)
|
||||
if len(odd) != 1 or abs(extra) < 0.5 or not listed:
|
||||
continue
|
||||
every = sum(
|
||||
(x["결과"] or x["줄참조"])[-1]
|
||||
for x in lines
|
||||
if x["비목"] == part and not x["합계"] and (x["결과"] or x["줄참조"])
|
||||
)
|
||||
block = float(saved.get(part) or 0) # 블록 금액이 그 줄을 빼야 맞을 때만
|
||||
if abs(every - block) >= 1 and abs(every - extra - block) < 1:
|
||||
odd[0]["비목"] = None
|
||||
|
||||
def unused(self) -> None:
|
||||
"""머리 아닌 줄의 기계 이름 — 아래 세 줄이 안 쓰면 글 줄(설명 속 장비 이름)."""
|
||||
for h in self.heads:
|
||||
@@ -597,10 +636,13 @@ def read(sheets: dict[str, list]) -> dict[str, Any]:
|
||||
}
|
||||
if not one:
|
||||
tags.append(f"{sx.NOTE}총괄표에 단산{b['번']} 없음")
|
||||
elif one.get("칸"): # 총괄표 당초 / 적용 칸(797-1a)
|
||||
tags.append(f"참고 · {one['칸']}")
|
||||
work = Lines(look, tags)
|
||||
for src in b["줄"]:
|
||||
work.run(src)
|
||||
work.unused()
|
||||
work.sections(head["저장"] or {})
|
||||
lines = []
|
||||
for ln in work.lines:
|
||||
marks = ln.pop("_marks")
|
||||
|
||||
@@ -59,7 +59,14 @@ def read(sheets: dict[str, list]) -> dict[str, Any]:
|
||||
head = {"코드": blk["코드"], "이름": blk.get("이름") or me.get("이름")}
|
||||
head |= {"규격": me.get("규격"), "단위": me.get("단위"), "저장": _amt(blk["머리"])}
|
||||
_, tot = ev.run_stmate([ln["풀이"] for ln in lines], prices)
|
||||
out["산근"].append({**head, "줄": lines, "줄합": tot, "표지": tags, "엑셀행": blk["행"]})
|
||||
body = [{k: ln.get(k) for k in ("행", "B", "C", "D", "E", "F")} for ln in blk["몸"]]
|
||||
out["산근"].append(
|
||||
{**head, "줄": lines, "줄합": tot, "표지": tags, "엑셀행": blk["행"]}
|
||||
| {
|
||||
"몸": body,
|
||||
"꼬리": blk["꼬리"],
|
||||
} # 엑셀 줄 금액 · 계 꼬리(검산 · `M02_San_Emit.stmate`)
|
||||
)
|
||||
rule, got = vote(out["산근"], prices)
|
||||
out["옵션"] = {"SAN_TYP": RULE[rule]}
|
||||
out["내역"] = None
|
||||
|
||||
Reference in New Issue
Block a user