diff --git a/resources/knowledge/original/경쟁사 프로그램/STmate 분석/20_분석/08_규칙6_8_9_재계산_변경설계_일괄변경.md b/resources/knowledge/original/경쟁사 프로그램/STmate 분석/20_분석/08_규칙6_8_9_재계산_변경설계_일괄변경.md index 60a6995f..e5f0fb32 100644 --- a/resources/knowledge/original/경쟁사 프로그램/STmate 분석/20_분석/08_규칙6_8_9_재계산_변경설계_일괄변경.md +++ b/resources/knowledge/original/경쟁사 프로그램/STmate 분석/20_분석/08_규칙6_8_9_재계산_변경설계_일괄변경.md @@ -35,7 +35,22 @@ STC에는 두 형태가 동시에 확인된다. 1. 한 파일 안에 `BOQ11`, `BOQ12`를 함께 저장하는 통합형: 소광 표본은 각각 90행, 89행이다. 2. 변경 차수를 별도 STC로 저장하면서 그 파일의 `BOQ11`을 현재안으로 쓰는 분리형: 소광 변경1차 표본은 115행이다. -또한 `COSTN`과 여러 필드의 접미사 1~4는 원설계와 최대 3개 변경차수의 값을 나란히 담을 수 있다. 따라서 “접미사 n=항상 BOQ1n”으로 기계적으로 가정하지 말고 프로젝트 메타데이터와 실제 존재 테이블을 함께 해석해야 한다. +또한 `COSTN`과 여러 필드의 접미사 1~4는 원설계와 최대 3개 변경차수의 값을 나란히 담을 수 있다. + +### 실증으로 확정된 차수 규칙 — A등급 (2026-09-13, 16번 §4.5·§4.6) + +```text +통합형 한 STC 안에 BOQ11(당초) + BOQ12(현재안) + ⚠ STmate 출력은 BOQ12 를 쓴다. BOQ11 을 현재안으로 잡으면 통째로 틀린다. + +분리형 변경 차수를 새 STC 로 저장 + 새 파일 BOQ11 차수1 = 앞 파일의 BOQ12 ← 소광 표본에서 원 단위 일치 확인 + 새 파일 BOQ11 차수2 = 이번 변경분 +``` + +`PRJLST.TCOSTn = MCOSTn + LCOSTn + SCOSTn` 으로 **직접공사비 합계**다. 소광 변경1차는 당초 173,311,386 → 변경 257,410,433, 증감 +84,099,047이다. + +따라서 “접미사 n=항상 BOQ1n”으로 기계적으로 가정하지 말고 **실제 존재하는 테이블과 `PRJLST` 를 함께 보고 현재안을 고를 것.** ### STmate의 실제 변경설계 계산모드 — A등급 diff --git a/resources/knowledge/original/경쟁사 프로그램/STmate 분석/20_분석/16_골든셋_회귀_결과.md b/resources/knowledge/original/경쟁사 프로그램/STmate 분석/20_분석/16_골든셋_회귀_결과.md index f007daac..3c724e7f 100644 --- a/resources/knowledge/original/경쟁사 프로그램/STmate 분석/20_분석/16_골든셋_회귀_결과.md +++ b/resources/knowledge/original/경쟁사 프로그램/STmate 분석/20_분석/16_골든셋_회귀_결과.md @@ -1,7 +1,7 @@ # 골든셋 회귀 결과 — 원가계산을 원 단위로 다시 세워 맞췄다 실행일: 2026-09-13 -방법: 프로젝트 STC의 `BOQ11`만 입력으로 삼아 **직접비 → 간접비 → 이윤 → 끝전조정 → 총공사비**를 처음부터 다시 계산하고, STmate가 뽑은 XLSX 「공사원가계산서」와 **원 단위로 대조**함. +방법: 프로젝트 STC의 내역 표(`BOQ11`/`BOQ12`)만 입력으로 삼아 **직접비 → 간접비 → 이윤 → 끝전조정 → 총공사비**를 처음부터 다시 계산하고, STmate가 뽑은 XLSX 「공사원가계산서」와 **원 단위로 대조**함. 재현 스크립트: `40_스크립트/golden_regression.py` ## 1. 결과 한 줄 @@ -18,13 +18,11 @@ | 영월 2024 (기번6) | 96 | 288건 일치 | ✅ | ✅ | ✅ | ✅ | | 울진 대흥 2024 (기번3) | 129 | 387건 일치 | ✅ | ✅ | ✅ | ✅ | | 영덕 계류보전 2025 (변경) | 98 | 294건 일치 | ✅ | ✅ | ✅ | — | +| 소광 2025 원설계 (기번8) | 43 | 129건 일치 | ✅ | ✅ | ✅ | ✅ | | 소광 2025 변경 1차 (기번8) | 67 | 201건 일치 | ✅ | ✅ | ✅ | ✅ | -| 맛보기 | 36 | — | — | — | — | — | **행 금액 `ROUNDDOWN(수량 × 단가)` 대조 1,515건 중 불일치 0.** -> 소광 **원설계**는 표본 폴더에 대응 XLSX가 없어 자동 짝짓기가 변경분 XLSX를 물었다. 규칙 실패가 아니라 짝짓기 문제다. - ## 3. 봉화 2024 — 처음부터 끝까지 | 항목 | 다시 계산한 값 | STmate 출력 | | @@ -51,7 +49,7 @@ | 관급자재대 | 143,555,000 | 143,555,000 | ✅ | | **총공사비** | **1,414,283,000** | **1,414,283,000** | ✅ | -## 4. 이번에 새로 밝혀진 규칙 다섯 +## 4. 이번에 새로 밝혀진 규칙 일곱 문서에 없던 것들이다. 이것이 없으면 위 표가 맞지 않는다. @@ -104,7 +102,37 @@ C1~C5 제외금액 총계 행 **06번 §4가 세운 모델(`차액 → 세전 상당액 → 이윤·VAT 배분`)이 실데이터로 확인됐다.** 재구현은 `raw_amount / rounded_amount / adjustment_amount`를 반드시 분리해 저장해야 한다. -### 4.5 관급자재대는 천원 **올림** +### 4.5 한 파일에 `BOQ11`·`BOQ12`가 같이 있으면 **`BOQ12`가 현재안** + +소광 원설계 STC는 두 표를 함께 담는다. + +| 표 | 행 | 말단 | 재료비 | 노무비 | 경비 | 출력과 | +|---|---:|---:|---:|---:|---:|:--:| +| `BOQ11` | 90 | 43 | 54,699,532 | 93,741,594 | 48,693,912 | ✗ | +| `BOQ12` | 89 | 43 | 47,987,107 | 82,246,518 | 43,077,761 | **✅** | + +**STmate가 뽑은 XLSX는 `BOQ12`와 맞는다.** `BOQ11`을 무조건 현재안으로 잡으면 이 프로젝트만 통째로 틀린다. 처음 회귀에서 소광 한 건이 어긋난 원인이 이것이었다. + +### 4.6 차수 인계 — 앞 파일의 `BOQ12`가 다음 파일의 `차수1`이 된다 + +| 무엇 | 재료비 | 노무비 | 경비 | +|---|---:|---:|---:| +| 원설계 파일 `BOQ12` | 47,987,107 | 82,246,518 | 43,077,761 | +| **변경1차 파일 `BOQ11` 차수1** | 47,987,107 | 82,246,518 | 43,077,761 | +| 변경1차 파일 `BOQ11` 차수2 | 75,735,506 | 119,733,078 | 61,941,849 | + +**정확히 같다.** 08번이 「접미사 n = 항상 `BOQ1n` 으로 기계적으로 가정하지 말라」고 경고한 것이 옳았고, 실제 규칙은 이렇다. + +```text +통합형 : 한 STC 안에 BOQ11(당초) + BOQ12(현재안). 출력은 BOQ12. +분리형 : 변경 차수를 새 STC 로 저장. + 그 파일의 BOQ11 차수1 = 앞 파일의 BOQ12 + 그 파일의 BOQ11 차수2 = 이번 변경분 +``` + +`PRJLST.TCOSTn = MCOSTn + LCOSTn + SCOSTn` 이며 **직접공사비 합계**다. 소광 변경1차는 당초 173,311,386 → 변경 257,410,433, 증감 **+84,099,047**이다. + +### 4.7 관급자재대는 천원 **올림** ```text 관급자재대 = ROUNDUP(원자재대 143,554,309, 천원) = 143,555,000 ✅ @@ -124,16 +152,16 @@ C1~C5 제외금액 총계 행 ## 6. 아직 이 시험으로 못 건드린 것 -골든셋은 **`BOQ11`의 단가를 주어진 것으로 놓고** 그 위를 검증한다. 따라서 아래는 여전히 열려 있다. +골든셋은 **내역 표의 단가를 주어진 것으로 놓고** 그 위를 검증한다. 따라서 아래는 여전히 열려 있다. - 단가가 **어떻게 만들어지는가** — 일위대가·중기 시간당 단가 (`BDQTY` 암호화) - 자재 6후보 중 **무엇을 채택하는가** - 수량 **할증** 계산 - 수공·실적 형식(`S`/`TA`/`SA`) — 표본이 전부 일반형식 `T` -- 변경설계 차액 계산 — 소광 세 벌로 다음에 할 것 +- 변경설계 **간접비**의 계산모드 — 차수 인계와 직접비 증감(+84,099,047)까지는 확인했으나, 변경분 XLSX 출력이 표본에 없어 간접비 쪽 모드(방법 A/B/직접입력)는 아직 못 가름 ## 7. 다음 -1. **소광 원설계 ↔ 통합변경 ↔ 변경1차** 세 벌로 변경설계 차액 재현 (T9) -2. 수공·실적 형식 표본 확보 — 현재 표본에 없음 -3. 일위대가표 시트로 단가 조립 검증 — XLSX에 `일위대가표`·`중기사용료` 시트가 있어 `BDQTY` 없이도 일부 가능 +1. **일위대가표·중기사용료 시트로 단가 조립 검증** — XLSX에 두 시트가 있어 `BDQTY` 암호화와 무관하게 단가가 어떻게 쌓이는지 확인 가능. 지금 자료로 되는 다음 칸 +2. 변경설계 **간접비** 모드 — 변경분 출력 XLSX 한 건만 있으면 정적으로 갈림 +3. 수공·실적 형식 표본 확보 — 현재 표본이 전부 일반형식 `T` diff --git a/resources/knowledge/original/경쟁사 프로그램/STmate 분석/40_스크립트/golden_regression.py b/resources/knowledge/original/경쟁사 프로그램/STmate 분석/40_스크립트/golden_regression.py index 9aa74c0f..05adaec3 100644 --- a/resources/knowledge/original/경쟁사 프로그램/STmate 분석/40_스크립트/golden_regression.py +++ b/resources/knowledge/original/경쟁사 프로그램/STmate 분석/40_스크립트/golden_regression.py @@ -66,7 +66,11 @@ for stc,xp in pairs: try: T,N = targets(xp) except Exception as e: print("%-42s 엑셀 실패" % stc.stem[:42]); continue if not T: continue - boq = dbf(zipfile.ZipFile(stc), "BOQ11.DBF") + zf = zipfile.ZipFile(stc) + have = {n.upper() for n in zf.namelist()} + # 한 파일에 BOQ11·BOQ12 가 함께 있으면 BOQ12 가 현재안(출력 기준)이다 + tbl = "BOQ12.DBF" if "BOQ12.DBF" in have and dbf(zf,"BOQ12.DBF") else "BOQ11.DBF" + boq = dbf(zf, tbl) M,L,S,nleaf,ok,bad = direct(boq) def get(*keys): for k in keys: diff --git a/resources/knowledge/original/경쟁사 프로그램/STmate 분석/40_스크립트/revision_chain_probe.py b/resources/knowledge/original/경쟁사 프로그램/STmate 분석/40_스크립트/revision_chain_probe.py new file mode 100644 index 00000000..a2b83f49 --- /dev/null +++ b/resources/knowledge/original/경쟁사 프로그램/STmate 분석/40_스크립트/revision_chain_probe.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +import sys, io, pathlib, zipfile, struct, re, warnings +from decimal import Decimal as D, ROUND_DOWN +sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", errors="replace") +warnings.filterwarnings("ignore"); import openpyxl +B = pathlib.Path(r"D:\aislo-wt\sub\resources\knowledge\original\실무문서\25년 산불진화임도(기번8)(울진소광)") +def dbf(zf,name): + b=zf.read(name); nrec,hlen,rlen=struct.unpack_from("