Merge remote-tracking branch 'origin/sub_desktop_1' into sub_laptop_1

This commit is contained in:
2026-09-13 14:48:37 +09:00
10 changed files with 489 additions and 2 deletions
@@ -35,6 +35,8 @@
| 26 편집기와 사이클식 | **`Cm` 54꼴·품셈 인자·식 편집기·낙찰율** — 계약/실행/기성 단계 발견 | (저장소 파일) |
| 27 계약·실행·기성 단계 | **설계 뒤 네 단계** — 낙찰율 3갈래, 기성은 계약제잡비율, 실행 차액보정 | (저장소 파일) |
| 28 변환·수량산출·식언어 | **식 변수의 대상/저장 비목** · 수량산출서 셀별명 · 조달청 변환 · 직종 106종 | (저장소 파일) |
| 29 암호화자료의 뼈대 | **값 없이 구조만** — 스키마 평문, 카탈로그 규모, 분류 4~5단, 단위 59~130종 | (저장소 파일) |
| 30 조달청 호환규정 XSD | ⭐ **국가 표준 납품 규격 전문** — 문서 뼈대·제경비 적용산식·기계경비 산출 | (저장소 파일) |
> **정본은 저장소 파일이다** — `resources/knowledge/original/경쟁사 프로그램/STmate 분석/20_분석/`.
> 위 Orca 링크는 보기용이며, 문서를 지식DB 자리로 옮기면서 주소가 한 번 바뀌었다.
@@ -124,6 +126,17 @@
| 조달청 호환 | 몰랐음 | **`Conv_Jodal_ST8`·`Conv_ST8_XML` 양방향** | 28번 §3 |
| 노임 직종 | 코드만 | **직종 사전 106종** 평문 | 28번 §3.1 |
| 암호화 파일 | 2개 | ⚠ **3개**`EQSYNC.DBF` 추가 | 28번 §5 |
| 암호화 자료의 **스키마** | 「못 읽음」으로만 | **전부 평문** — 필드명·형식·길이 | 29번 §1 |
| 자원 사전 구조 | 몰랐음 | **분류3단+`JDCODE`17자리+명칭+표준명칭+규격110자+단위** | 29번 §1.1 |
| 분류 트리 | 몰랐음 | **4~5단 깊이**, 부모 포인터, 형제 순서 | 29번 §1.2·§3.1 |
| 카탈로그 규모 | 건수만 | **명칭 1,761종 : 자재 57,580건** — 규격이 난관 | 29번 §3 |
| 단위 사전 | 몰랐음 | **59종(자재)·130종(통합)** | 29번 §3 |
| 표준시장단가 | 건수만 | **노무만 요율 조정** (`RATE_M`·`RATE_S` 빈칸) | 29번 §3.2 |
| XML 스키마 | ⛔ 「못 얻음」이라 적었음 | **정정 — `Valid_Xml.vsl` 에 XSD 전문** | 30번 |
| 납품 규격 | STmate 고유로 봄 | **조달청 공개 국가 표준** V1.0.5 — 그대로 따름 | 30번 §1 |
| 식을 데이터로 저장 | 우리 계약 | **규격이 `적용산식`·`적용산식설명`을 요구** | 30번 §3 |
| 노임 환산 갈래 | 화면 문자열 | **`H0`~`H5` 규격 코드** (일반·터널·장대터널·준설선 3종) | 30번 §4 |
| 손료 산출 | 한 갈래로 봄 | ⚠ **주간/야간/2교대/3교대 네 갈래** — 뽑은 25개는 `E0` 뿐 | 30번 §4 |
분석일: 2026-09-13
대상: `C:\경영정보(주)`
@@ -85,7 +85,7 @@ ST_Conv_Mode1/2/3 · ST_Conv_Data · ST_Copy_Data
**납품 호환 경로가 프로그램 안에 있다.** `호환규정코드``wM_Mrg_BSC`의 매칭 키 1순위였던 것(20번 §2)과 이어진다.
XML **스키마는 문자열로 안 남는다** — 실행 중에 조립한다. 태그 이름을 정적으로는 못 얻는다.
> ⛔ **이 판정은 틀렸다. 30번에서 정정했다.** 스키마는 `System\Valid_Xml.vsl` 에 **XSD 파일로 있다**(1,429줄, 조달청 공사원가호환규정 V1.0.5).
### 3.1 노임 직종 사전 106종
@@ -163,7 +163,7 @@ EQSYNC.DBF 54행 × 3열 (2.9 KB)
| 무엇 | 상태 |
|---|---|
| XML 스키마 태그 | 실행 중 조립 — 정적으로 못 얻음 |
| ~~XML 스키마 태그~~ | ✅ **해결**`Valid_Xml.vsl` XSD 전문 (30번) |
| `EQSYNC` 내용 | 암호화 |
| 수량산출서 파일 형식 | 표본 0건 (`QCODE` 전부 빈 표) |
| 조달청 변환 결과물 | 표본 0건 |
@@ -0,0 +1,121 @@
# 암호화 자료의 뼈대 — 값을 못 읽어도 구조는 잰다
점검일: 2026-09-13
전제: **가격 값은 중요하지 않다.** 반기마다 바뀌고 Aislo는 자기 원천을 따로 구독한다. 중요한 것은 **코드 체계·분류 깊이·명칭/규격/단위 자리·카탈로그 규모**다.
재현 스크립트: `40_스크립트/encrypted_schema_probe.py`
## 1. ⭐ 스키마는 암호화돼 있지 않다
DBF 헤더(필드 이름·형식·길이)는 **전부 평문**이다. 막힌 것은 레코드 본문뿐이다.
### 1.1 `JDCODE_*.BSC` — 자원 코드 사전 (12필드)
```text
TYP_1(C16) TYP_2(C10) TYP_(C11) 분류 3단
JDCODE(C17) ⭐ 자원 코드 — 17자리
NAME(C60) SIZE(C110) UNIT(C10) 명칭 / 규격 / 단위
EQCODE(C11) 시설코드
GNCODE(C11) 그룹코드
TYP_STN(L1) 표준 여부 (논리)
PSCODE(C11) 연계 코드
ST_NAME(C70) ⭐ 표준 명칭 (별도 칸)
```
**`NAME` 말고 `ST_NAME`(표준 명칭)이 따로 있다.** 물가지 표기와 표준 표기를 나눠 담는다 — 자원 축 매칭에 그대로 쓸 개념이다.
`SIZE`가 **110자**다. 규격 문자열이 길다는 뜻이고, 매칭을 규격까지 걸면 어려운 까닭이다.
### 1.2 `GRPCOD_*.BSC` — 분류 트리 (7필드)
```text
TYP_1(C16) TYP_(C10) 분류 갈래
CUR_COD(C10) 현재 노드 코드
ROT_COD(C10) 상위 노드 코드 ← 부모 포인터
LEV(N2) ⭐ 깊이
NAME(C80) 분류 이름
ORD(C5) 형제 순서
```
**`CUR_COD` / `ROT_COD` / `LEV` 의 부모–자식 트리**다. 구조가 그대로 드러난다.
### 1.3 `*.CSTA` — 표준시장단가 (32필드)
```text
CODE(C6) · NAME(C50) · SIZE(C60) · UNIT(C10)
CODEA(C11) · JDCODE(C17) · BQCODE(C11) · EQCODE(C11) · PG_J(C12)
AAMT1~4 · MAMT1/2 · LAMT1/2 · SAMT1/2 · TAMT1/2 금액 두 벌
MAMT1_R · LAMT1_R · SAMT1_R · MAMT2_R · LAMT2_R · SAMT2_R _R 계열
RATE_L · RATE_M · RATE_S 비목별 요율
TYP_C(C1) · EDT_DATE(C12)
```
⇒ 표준시장단가도 **재·노·경 세 성분으로 나뉘고 두 벌(1/2)**을 든다. `_R` 계열과 `RATE_*`가 따로 있는 것이 27번 §2의 「노임외 재료비로 적용 / 경비로 적용」(`ACTTYP`)과 이어진다.
## 2. 암호는 **오프셋별 고정 변환**이다
같은 필드 안에서 **같은 평문은 늘 같은 암호문**이 된다. `JDCODE_M.BSC` 57,580행에서 `EQCODE`가 **단 한 가지 암호문**인 것이 증거다(= 전 행이 빈칸).
⚠ 다만 **필드가 다르면 키가 다르다.** `GRPCOD_Z`에서 `ROT_COD`가 다른 행의 `CUR_COD`와 일치하는 비율이 **0.0%**다. 같은 코드라도 자리가 다르면 다른 암호문이 된다.
**필드 안 동일성만 셀 수 있고, 필드 사이를 잇지는 못한다.** 트리의 부모–자식 연결은 복원 불가다.
②트랙 `original/원가계산/STmate/STC_난독화_상태.md` 의 「오프셋별 고정 변환」 판정과 같은 결론이고, 이번에 **기준자료(BSC/CSTA)에서도 성립**함을 확인했다.
## 3. 값을 못 읽어도 잰 것 — 카탈로그 규모
| 파일 | 행수 | 서로 다른 `JDCODE` | `NAME` | `SIZE` | `UNIT` |
|---|---:|---:|---:|---:|---:|
| `JDCODE_L` 노무 | 460 | **460** | 371 | 23 | — |
| `JDCODE_M` 자재 | **57,580** | **57,580** | **1,761** | 57,069 | **59** |
| `JDCODE_S` 경비 | 851 | 850 | 219 | 654 | 9 |
| `JDCODE_X` 중기 | 833 | 831 | 210 | 657 | — |
| `JDCODE_Z` 통합 | **33,927** | 33,927 | **6,170** | 18,247 | **130** |
읽는 법 몇 가지.
- **자재 57,580건이 전부 고유 코드**이고, **명칭은 1,761종**뿐이다. 같은 이름이 규격만 달리해 평균 **33건**씩 갈린다 — 규격 매칭이 자원 축의 실제 난관임을 수치로 보여 준다.
- **단위는 59종**(자재) · **130종**(통합). 단위 사전 크기를 미리 알 수 있다.
- `JDCODE_Z``TYP_1`·`TYP_2`가 **각 6종**으로 갈린다 — 통합 사전이 6갈래 분류를 가진다.
- `JDCODE_S`·`JDCODE_X``EQCODE`·`PSCODE`·`ST_NAME`**750~800종**으로 채워져 있다(자재는 비어 있음). **경비·중기는 시설코드와 표준명칭을 쓰고 자재는 안 쓴다.**
### 3.1 분류 트리 규모
| 파일 | 행수 | `CUR_COD` 고유 | `ROT_COD` 고유 | `LEV` 값 | `NAME` 고유 |
|---|---:|---:|---:|---:|---:|
| `GRPCOD_E` | 2,539 | 2,277 | 596 | **4단** | 2,221 |
| `GRPCOD_Z` | 12,125 | 12,125 | 5,792 | **5단** | 4,295 |
**분류가 4~5단 깊이**이고, 상위 노드가 596 / 5,792개, 한 부모의 자식이 최대 22개다. 이름은 4,295종이지만 행이 12,125이므로 **같은 이름이 여러 갈래에 걸린다.**
### 3.2 표준시장단가
```text
4,921행 · CODE 4,921 고유 · NAME 488종 · SIZE 2,072종 · UNIT 22종
BQCODE 28종 · EQCODE 89종 · PG_J 257종 · TYP_C 3종
금액 AAMT1/TAMT1 4,719종 · MAMT 3,294 · LAMT 4,671 · SAMT 1,945
RATE_L 72종 · LAMT1_R / LAMT2_R 각 71종
비어 있는 필드: MAMT1_R · SAMT1_R · MAMT2_R · SAMT2_R · AAMT3 · AAMT4 · RATE_M · RATE_S · EDT_DATE
```
**`RATE_L`(노무 요율)만 72종으로 채워져 있고 `RATE_M`·`RATE_S`는 비어 있다.** 표준시장단가는 **노무비만 요율로 조정**한다는 뜻이고, 설치 폴더의 파일명 `표준시장[노임외 재료비적용]`·`[노임외 경비적용]`(21번 §4)과 정확히 맞는다.
`BQCODE` 28종 = **공종 분류 28갈래**, `EQCODE` 89종 = 시설 89종.
## 4. 이로써 Aislo 가 얻는 것
| 무엇 | 얻은 것 |
|---|---|
| 자원 코드 자릿수 | `JDCODE` **17자리**, 그룹 `GNCODE`·시설 `EQCODE` 각 11자리 |
| 자원 사전 구조 | 분류 3단 + 코드 + 명칭 + **표준명칭 별도** + 규격(110자) + 단위 |
| 분류 트리 | **4~5단 깊이**, 부모 포인터 방식, 형제 순서 칸 |
| 카탈로그 규모 | 자재 57,580 · 통합 33,927 · 중기 833 · 경비 851 · 노무 460 |
| 단위 사전 | **59~130종** |
| 매칭 난이도 | **명칭 1,761종 : 코드 57,580건** — 규격으로 갈린다 |
| 표준시장단가 | 재·노·경 세 성분, **노무만 요율 조정** |
**가격을 못 읽는 것이 설계에 걸림돌이 되지 않는다.** 축을 세우는 데 필요한 것은 전부 나왔다.
## 5. 끝내 못 얻는 것
`JDCODE` 값 자체 · `NAME`·`SIZE`·`UNIT` 문자열 · 가격.
**이름·코드 목록이 필요하면 프로젝트 파일 쪽에서 얻는다**`COSTN.DBF`는 평문이고 실무 7건에서 894개를 뽑아 뒀다(`30_원자료/stmate_code_name_list.csv`).
@@ -0,0 +1,149 @@
# 조달청 공사원가호환규정 XSD — 국가 표준 납품 규격
발견일: 2026-09-13
계기: 최종 빈칸 점검에서 **확장자 기준으로 한 번도 안 연 파일 종류**를 훑다가 나옴.
**28번 §3의 「XML 스키마는 실행 중 조립이라 정적으로 못 얻음」은 틀렸다.** 스키마가 **파일로 있다.**
원본: `C:\경영정보(주)\System\Valid_Xml.vsl` (57.4 KB · 1,429줄)
재현 스크립트: `40_스크립트/xsd_parse.py` · 사본 `30_원자료/조달청_공사원가호환규정.xsd`
## 1. 무엇인가
```xml
<xsd:documentation>
이 문서는 공사원가호환규정 V1.0.4 XML스키마이다. 최종수정일 2022-10-06
… 1.0.5 건축공사의 사업내용 정보 추가 (2022-11-28)
</xsd:documentation>
```
**조달청 공사원가통합관리시스템(`npccs.g2b.go.kr`)이 발표하는 공개 규격**이다. STmate 고유 포맷이 아니라 **국가 표준**이므로 Aislo가 그대로 따라 쓰면 된다.
같은 폴더에 `호환규정코드(2026_09_01)` 안내문도 있다.
```text
호환규정코드 2026년 9월 1일 조달청 발표분 반영
조달청 공사원가통합관리시스템 https://npccs.g2b.go.kr 발표
```
**STmate는 이 규격을 따라 `Conv_Jodal_ST8`·`Conv_ST8_XML`(28번 §3)로 변환한다.** 규정 코드는 반기마다 갱신된다.
버전 이력이 그대로 남아 있다 — `1.0.0``1.0.5`. 내역공종코드 길이가 **16 → 20자**로 늘어난 것(2017-04-19)도 적혀 있다.
## 2. 문서 뼈대
```text
공사원가호환규정
├ 스키마버전 1.0.0 ~ 1.0.5
├ 작성정보 작성업체명 · 프로그램명 · 프로그램버전 · 파일제작일
│ · 파일검증여부 · 건축공사사업내용작성여부
├ 공사정보 공사관리번호 · 주공사 · 공사명 · 비고
│ · 기계경비산출 · 건축공사사업내용
└ 공사내역서
├ 공사제경비 → 제경비항목
└ 단일공사내역서
├ 단일공사정보 (공사구분 · 공사설명 · 전역변수)
├ 내역서 → 공종 → 세부공종
├ 일위대가 → 일위대가상세
├ 중기단가산출
├ 기계경비 → 기계경비상세
├ 자재 → 조사처별단가
├ 노무
├ 경비항목 → 조사처별단가_경비
├ 실적단가
└ 제경비
```
**우리가 판 STmate 구조와 한 겹씩 대응한다.**
| 호환규정 | STmate |
|---|---|
| 일위대가 / 일위대가상세 | `B` 코드 호표 (17번) |
| 중기단가산출 | `D` 코드 (18번 §2.2) |
| 기계경비 / 기계경비상세 | 중기사용료 호표 (17번 §3) |
| 자재 · 노무 · 경비항목 | `M` · `L` · `S` 코드 |
| 실적단가 | 표준시장단가 `CSTA` (29번 §1.3) |
| 제경비항목 | 간접비 (25번 §2) |
| 내역서 → 공종 → 세부공종 | `BOQ11` 계층 (16번 §4.1) |
## 3. ⭐ 제경비 항목이 **적용산식을 문자열로** 싣는다
```text
제경비항목정보 : 세부공종코드 · 집계항목여부 · 비목명
· 적용산식 · 적용요율 · 추가금액 · 산출금액 · 적용산식설명
```
**국가 규격 자체가 「밑수 산식을 글로 적어 함께 보내라」고 정한다.** 25번 §2의 간접비 식 템플릿 26개와 같은 요구다. 우리가 「식을 데이터로 저장하라」고 세운 계약이 **납품 규격과 맞아떨어진다.**
`직접공사비정보`도 따로 있다.
```text
직접공사비_재료비 · 직접공사비_노무비 · 직접공사비_경비
· 미확정설계공종_금액 · 제요율적용제외공종_금액 · 관급자재공종_금액
```
**「제요율적용제외공종」이 규격에 못 박혀 있다** — 16번 §4.2의 `C*` 제외금액 구역, 27번 §2.3의 낙찰율 적용제외와 같은 개념이 **국가 표준에도 있다.**
## 4. ⭐ 기계경비 산출 규격 — 우리가 캔 것과 정확히 맞는다
```text
기계경비산출형식 : 환율 · 시간당손료산출 · 시간당노임산출
환율형식 미국_1USD · 유럽연합_1EUR · 일본_100엔
시간당손료산출 E0-주간 · E1-야간 · E2-주야간2교대 · E3-주야간3교대
시간당노임산출 H0-일반구간 · H1-터널구간 · H2-장대터널
· H3-펌프준설선 · H4-그래브준설선 · H5-버킷준설선 · H_-사용자정의
```
**22번 §3.4에서 `wM_Set_Sys`의 `cmBx_Sel_RX`가 「계수 ; 터널구간 / 계수-1 ; 장대터널 / 계수-2 ; 펌프준설선 / 계수-3 ; GRAB준설선 / 계수-4 ; 버켓준설선」이라 한 것과 하나도 안 틀리고 같다.**
`Start8x.Ini``RXXNM`·`RX1NM`~`RX4NM`(20번 §2.5)이 **규격의 `H0`~`H5` 자리**다. 18번 §2.1의 노임 환산식 `1/8*16/12*25/20``H0-일반구간`에 해당한다.
`환율형식``EXNM_`·`EXEUR`·`EXYEN`(18번 §2.3)과 그대로 맞는다.
**`시간당손료산출`이 주간/야간/2교대/3교대 네 갈래**다 — 우리가 17번 §4에서 뽑은 손료율 25개는 **`E0-주간` 한 갈래**일 뿐이다.
## 5. 열거형 — 코드 목록이 규격에 박혀 있다
| 열거 | 개수 | 값 |
|---|---:|---|
| **주공사** | 9 | 토목 · 건축 · 설비 · 전기 · 통신 · 조경 · 소방 · 문화재수리 · **국가유산수리** |
| **공사현장지역코드** | **290** | 행정구역 코드 (`11110` 서울 종로 …) |
| 인도조건구분 | 40 | 일반 · 납품장소도 · 상차도 · 하차도 · 현장설치도 · 생산공장도 … |
| 시설물유형 | 27 | 일반청사 · 대형청사 · 초중고 · 대학교 · 도서관 · 체육시설 … |
| 지역구분 | 3 | 비혼잡(일반) · 혼잡(특수) · **산간도서(특수)** |
| 구조형식 | 4 | 철골조 · 철골철근콘크리트조 · 철근콘크리트조 · 기타 |
| 내진등급 | 3 | 특등급 · 1등급 · 2등급 |
| 에너지효율등급 | 5 | `1+++` ~ 7등급 · 해당 없음 |
| 녹색건축인증 | 5 | 최우수 · 우수 · 우량 · 일반 · 해당 없음 |
| 철거공사 포함여부 · BF인증 · 신재생에너지 · 지반형태 · 흙막이 | 각 2 | |
**`주공사``문화재수리공사``국가유산수리공사`가 둘 다 있다** — 10번 §4에서 2020-05-27에 국가유산 열이 붙은 것과 이어진다(명칭 개정 과도기).
**`지역구분``산간도서지역(특수)`** 은 임도에 바로 걸린다.
## 6. 건축공사 사업내용 36요소
```text
연면적 · 대지면적 · 건축면적 · 조경면적 · 지하층연면적 · 용적률 · 건폐율
기준층층고 · 최고높이 · 최대지하층수 · 최대지상층수 · 공사일수 · 공사현장 …
```
건축 전용이라 임도와 직접 관계는 없으나, **규격이 공사 종류별로 사업내용을 따로 요구**한다는 점은 알아 둘 것.
## 7. 이 발견이 바꾸는 것
| 항목 | 이전 | 지금 |
|---|---|---|
| XML 스키마 | ⛔ 「실행 중 조립이라 못 얻음」 | ✅ **파일로 있음** — XSD 1,429줄 전문 |
| 납품 규격 | STmate 고유로 봄 | ✅ **조달청 공개 국가 표준** — 그대로 따라 쓰면 됨 |
| 식을 데이터로 | 우리 계약 | ✅ **규격이 `적용산식`·`적용산식설명`을 요구** |
| 제외공종 | STmate 구현으로 봄 | ✅ **규격에 `제요율적용제외공종_금액`** |
| 노임 환산 갈래 | 화면 문자열로만 | ✅ **`H0`~`H5` 규격 코드** |
| 손료 산출 | 한 갈래로 봄 | ⚠ **주간/야간/2교대/3교대 네 갈래** — 우리가 뽑은 25개는 `E0` 뿐 |
| 공사 종류 | 임도 중심 | ✅ **9종 + 지역코드 290** |
## 8. 남은 것
1. `30_원자료/조달청_공사원가호환규정.xsd` 로 사본을 떠 뒀다. **최신판은 `npccs.g2b.go.kr` 에서 직접 받을 것** — 이 사본은 V1.0.5(2022-11-28)이다.
2. 세부공종 28요소·일위대가상세 21요소의 **필드별 뜻**은 아직 안 풀었다.
3. 손료 `E1`~`E3`(야간·교대) 계수는 STmate 자료에 없다 — 품셈에서 가져와야 한다.
@@ -0,0 +1,56 @@
### 조달청 공사원가호환규정 XSD
complexType 32개 · simpleType 21개
■ complexType (구조 정의)
공사원가호환규정형식 요소 4 스키마버전, 작성정보, 공사정보, 공사내역서
공사정보형식 요소 6 공사관리번호, 주공사, 공사명, 비고, 기계경비산출, 건축공사사업내용
건축공사사업내용형식 요소 36 연면적, 대지면적, 건축면적, 조경면적, 지하층연면적, 용적률, 건폐율, 기준층층고, 최고높이, 최대지하층수, 최대지상층수, 공사일수, 공사현장
작성정보형식 요소 6 작성업체명, 프로그램명, 프로그램버전, 파일제작일, 파일검증여부, 건축공사사업내용작성여부
실적단가형식 요소 11 항목구분, 공종구분, 실적공사비코드, 품명, 규격, 단위, 재료비단가, 노무비단가, 경비단가, 비고, 기타
노임산출근거형식 요소 4 산출수량, 노임별공량, 노임할증, 공량품셈근거
일위대가상세형식 요소 21 자원구분, 자원코드, 계산제외, 품명, 규격, 단위, 수량, 재료비단가, 노무비단가, 경비단가, 재료비, 노무비, 경비, 관급, 손료코드군, 손
일위대가형식 요소 12 일위대가코드, 번호, 품명, 규격, 단위, 재료비, 노무비, 경비, 비목구분, 비고, 기타, 일위대가상세
중기단가산출형식 요소 12 중기단가산출코드, 번호, 품명, 규격, 단위, 재료비, 노무비, 경비, 비목구분, 비고, 중기단가산출식, 기타
기계경비형식 요소 13 기계경비코드, 번호, 품명, 규격, 단위, 작업시간, 작업장소, 재료비, 노무비, 경비, 비고, 기타, 기계경비상세
자재형식 요소 9 자재코드, 품명, 규격, 단위, 재료비단가, 인도조건구분, 비고, 기타, 조사처별단가
노무형식 요소 7 노무코드, 품명, 규격, 단위, 노무비단가, 비고, 기타
경비항목형식 요소 16 경비항목코드, 경비구분, 품명, 규격, 단위, 통화구분, 재료비단가, 노무비단가, 경비단가, 외화경비단가, 상각비계수, 정비비계수, 관리비계수,
조사처별단가형식 요소 5 상호, 전화번호, 재료비단가, 인도조건구분, 비고
조사처별단가형식_경비 요소 7 상호, 전화번호, 재료비단가, 노무비단가, 경비단가, 인도조건구분, 비고
공사내역서형식 요소 2 공사제경비, 단일공사내역서
단일공사내역서형식 요소 10 단일공사정보, 내역서, 일위대가, 중기단가산출, 기계경비, 자재, 노무, 경비항목, 실적단가, 제경비
공종형식 요소 11 내역서번호, 공종구분, 계산제외, 공종번호, 공종명, 재료비, 노무비, 경비, 비고, 기타, 세부공종
세부공종형식 요소 28 세부공종코드, 자원구분, 계산제외, 세부공종번호, 세부공종명, 규격, 단위, 수량, 재료비단가, 노무비단가, 경비단가, 재료비, 노무비, 경비,
단일공사정보형식 요소 3 공사구분, 공사설명, 전역변수
전역변수형식 요소 2 변수명, 실수값
개별노임산출형식 요소 2 노무코드, 공량
직접공사비정보 요소 6 직접공사비_재료비, 직접공사비_노무비, 직접공사비_경비, 미확정설계공종_금액, 제요율적용제외공종_금액, 관급자재공종_금액
제경비항목정보 요소 8 세부공종코드, 집계항목여부, 비목명, 적용산식, 적용요율, 추가금액, 산출금액, 적용산식설명
공사제경비형식 요소 1 제경비항목
기계경비상세 요소 22 자원구분, 자원코드, 계산제외, 품명, 규격, 단위, 수량, 재료비단가, 노무비단가, 경비단가, 재료비, 노무비, 경비, 손료코드군, 손료계산비
사용자정의_시간당노임산출정보 요소 2 사용자정의코드, 노임산출
노임산출형식 요소 3 산출식, 계산값, 적용구분
기계경비산출형식 요소 3 환율, 시간당손료산출, 시간당노임산출
환율형식 요소 3 미국_1USD, 유럽연합_1EUR, 일본_100엔
시간당손료산출형식 요소 4 E0-주간, E1-야간, E2-주야간2교대, E3-주야간3교대
시간당노임산출형식 요소 7 H0-일반구간, H1-터널구간, H2-장대터널, H3-펌프준설선, H4-그래브준설선, H5-버킷준설선, H_-사용자정의
■ 열거형 (코드 목록)
인도조건구분형식 40개: 일반, 납품장소도, 납품장소상차도, 납품장소하차도, 납품장소입고도, 현장설치도, 생산공장도(상차제외), 최기역레일도, 운반구상차도, 분공장도(상차제외), 수요기관 부
열거형 1개
■ 인라인 열거 40곳 (앞 14)
스키마버전 6개: 1.0.5, 1.0.4, 1.0.3, 1.0.2, 1.0.1, 1.0.0
주공사 9개: 토목공사, 건축공사, 설비공사, 전기공사, 통신공사, 조경공사, 소방공사, 문화재수리공사, 국가유산수리공사
공사현장지역코드 290개: 11110, 11140, 11170, 11200, 11215, 11230, 11260, 11290, 11305, 11320, 11350, 113
시설물유형 27개: 일반청사, 대형청사, 일반형초중고, 복합형초중고, 강의형대학교, 복합형대학교, 일반형수련시설, 복합형수련시설, 도서관, 야외형체육시설, 복합형체
철거공사포함여부 2개: 철거공사 포함, 철거공사 미포함
지역구분 3개: 비혼잡지역(일반), 혼잡지역(특수), 산간도서지역(특수)
지반공사.지반형태 2개: 일반지반, 특수지반
지반공사.흙막이공사 2개: 흙막이공사가 없는 경우, 흙막이공사가 있는 경우
구조형식 4개: 철골조, 철골철근콘크리트조, 철근콘크리트조, 기타
내진등급 3개: 내진설계특등급, 내진설계1등급, 내진설계2등급
건축물인증.신재생에너지 2개: 대상시설 해당 있음, 대상시설 해당 없음
건축물인증.에너지효율등급 5개: 1+++ 등급, 1등급 ~ 1++등급, 2등급 ~ 4등급, 5등급 ~ 7등급, 해당 없음
건축물인증.녹색건축인증 5개: 최우수, 우수, 우량, 일반, 해당 없음
건축물인증.BF인증 2개: 해당 있음, 해당 없음
@@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
"""암호화 기준자료에서 '값 말고 뼈대'를 건진다 — 스키마·필드·부분 평문 여부."""
import sys, io, struct, pathlib, collections, re
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", errors="replace")
R = pathlib.Path(r"C:\경영정보(주)\System")
def schema(b):
nrec,hlen,rlen=struct.unpack_from("<IHH",b,4)
f=[];o=32
while o<len(b) and b[o]!=0x0D:
f.append((b[o:o+11].rstrip(b"\0").decode("cp949","replace"), chr(b[o+11]), b[o+16], b[o+17])); o+=32
return nrec,hlen,rlen,f
print("### 암호화 기준자료 — 스키마는 평문인가, 레코드는 어디까지 막혔나\n")
for p in sorted(R.rglob("*")):
if not p.is_file() or p.suffix.upper() not in (".BSC",".CSTA"): continue
b=p.read_bytes()
try: nrec,hlen,rlen,f = schema(b)
except Exception: continue
if not f: continue
print("%-42s %6d× %2d%7.1f KB" % (p.name[:42], nrec, len(f), len(b)/1024))
print(" 필드: %s" % ", ".join("%s(%s%d%s)"%(n,t,l,("."+str(d)) if d else "") for n,t,l,d in f))
# 필드별 평문 비율 — 앞 200 레코드
off=[1]
for n,t,l,d in f: off.append(off[-1]+l)
ratio=[]
N=min(nrec,200)
for i,(n,t,l,d) in enumerate(f):
pr=tot=0
for k in range(N):
seg=b[hlen+k*rlen+off[i] : hlen+k*rlen+off[i]+l]
for c in seg:
tot+=1
if 32<=c<127 or c>=0xA1: pr+=1
ratio.append((n, pr/max(tot,1)))
good=[n for n,r in ratio if r>0.9]
print(" 평문 비율 0.9 넘는 필드: %s" % (", ".join(good) if good else "없음"))
print(" 필드별: %s" % " ".join("%s=%.2f"%(n,r) for n,r in ratio))
print()
@@ -0,0 +1,52 @@
# -*- coding: utf-8 -*-
"""암호를 풀지 않고 구조만 복원 — 같은 값은 같은 암호문이라는 성질만 쓴다.
값(이름·가격)은 끝내 모르지만 분류 트리·군집 크기·연결 관계는 나온다."""
import sys, io, struct, pathlib, collections, hashlib
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", errors="replace")
R=pathlib.Path(r"C:\경영정보(주)\System")
def table(p):
b=p.read_bytes(); nrec,hlen,rlen=struct.unpack_from("<IHH",b,4)
f=[];o=32
while b[o]!=0x0D: f.append((b[o:o+11].rstrip(b"\0").decode("cp949","replace"),b[o+16]));o+=32
off=[1]
for nm,l in f: off.append(off[-1]+l)
rows=[]
for k in range(nrec):
base=hlen+k*rlen
rows.append({nm: b[base+off[i]:base+off[i]+f[i][1]] for i,(nm,l) in enumerate(f)})
return [x[0] for x in f], rows
def key(v): return hashlib.blake2s(v, digest_size=5).hexdigest()
print("### ① 같은 값 → 같은 암호문 인가 (동일성 검사)")
names,rows=table(next(R.rglob("JDCODE_M.BSC")))
for fl in ("TYP_1","TYP_2","TYP_","EQCODE","GNCODE","UNIT"):
d=collections.Counter(key(r[fl]) for r in rows)
print(" %-8s 서로 다른 암호문 %6d개 / %d행 최빈 %d" % (fl, len(d), len(rows), d.most_common(1)[0][1]))
print("\n### ② 분류 트리 복원 — GRPCOD_Z (값은 몰라도 모양은 나옴)")
gn,gr=table(next(R.rglob("GRPCOD_Z.BSC")))
lev=collections.Counter(bytes(r["LEV"]).strip() for r in gr)
print(" LEV 서로 다른 값 %d개 (암호문 기준): %s" % (len(lev), dict(list(lev.most_common(6)))))
cur=collections.Counter(key(r["CUR_COD"]) for r in gr)
rot=collections.Counter(key(r["ROT_COD"]) for r in gr)
print(" CUR_COD 고유 %d / %d행 ROT_COD 고유 %d" % (len(cur), len(gr), len(rot)))
# 부모-자식: ROT_COD 가 다른 행의 CUR_COD 와 같은가
curset={key(r["CUR_COD"]) for r in gr}
linked=sum(1 for r in gr if key(r["ROT_COD"]) in curset)
print(" ROT_COD 가 다른 행의 CUR_COD 와 일치: %d / %d 행 (%.1f%%)" % (linked, len(gr), 100*linked/len(gr)))
ch=collections.Counter(key(r["ROT_COD"]) for r in gr)
print(" 자식 수 분포 상위: %s" % [c for _,c in ch.most_common(8)])
print("\n### ③ 자재 57,580건의 군집 — GNCODE(그룹코드) 로 묶기")
names,jm=table(next(R.rglob("JDCODE_M.BSC")))
g=collections.Counter(key(r["GNCODE"]) for r in jm)
print(" 서로 다른 그룹 %d개, 전체 %d" % (len(g), len(jm)))
sz=[c for _,c in g.most_common()]
print(" 군집 크기 상위 12: %s" % sz[:12])
print(" 1건짜리 군집 %d개, 10건 이상 군집 %d" % (sum(1 for c in sz if c==1), sum(1 for c in sz if c>=10)))
t1=collections.Counter(key(r["TYP_1"]) for r in jm)
t2=collections.Counter(key(r["TYP_2"]) for r in jm)
t3=collections.Counter(key(r["TYP_"]) for r in jm)
print("\n 분류 3단 고유 개수: TYP_1 %d · TYP_2 %d · TYP_ %d" % (len(t1),len(t2),len(t3)))
print(" TYP_ 군집 크기 상위 10: %s" % [c for _,c in t3.most_common(10)])
@@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
"""최종 빈칸 점검 — 아직 한 번도 안 연 파일 종류가 있나."""
import sys, io, pathlib, struct, collections, re
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", errors="replace")
R=pathlib.Path(r"C:\경영정보(주)")
COVERED_EXT = {".CPM",".EXE",".BPL",".DLL",".BSC",".CSTA",".STBSC",".DBF",".SMT",".STC",
".JB_1",".JB_M",".JB_R",".JB_RA",".INI",".MEM",".XLSX"}
kinds=collections.Counter(); other=collections.defaultdict(list)
for p in R.rglob("*"):
if not p.is_file(): continue
e=p.suffix.upper()
kinds[e]+=1
if e not in COVERED_EXT: other[e].append(p)
print("### `C:\경영정보(주)` 전체 파일 종류")
for e,c in kinds.most_common(): print(" %-10s %3d %s" % (e or "(없음)", c, "✅ 다룸" if e in COVERED_EXT else "·"))
print("\n### 아직 안 다룬 종류의 실제 파일")
for e,ps in sorted(other.items()):
for p in ps[:4]:
try: head=p.open("rb").read(16)
except Exception: head=b""
print(" %-12s %-30s %7.1f KB 머리=%r" % (e or "(없음)", p.name[:30], p.stat().st_size/1024, head[:10]))
@@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
"""조달청 공사원가호환규정 XSD 구조 추출."""
import sys, io, re, pathlib, collections
import xml.etree.ElementTree as ET
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", errors="replace")
p=next(pathlib.Path(r"C:\경영정보(주)").rglob("Valid_Xml.vsl"))
t=p.read_text(encoding="utf-8")
NS={"xsd":"http://www.w3.org/2001/XMLSchema"}
root=ET.fromstring(t)
ct=root.findall("xsd:complexType",NS); st=root.findall("xsd:simpleType",NS)
print("### 조달청 공사원가호환규정 XSD")
print(" complexType %d개 · simpleType %d" % (len(ct), len(st)))
print("\n■ complexType (구조 정의)")
for c in ct:
nm=c.get("name")
els=[e.get("name") or e.get("ref") for e in c.iter("{http://www.w3.org/2001/XMLSchema}element")]
ats=[a.get("name") for a in c.iter("{http://www.w3.org/2001/XMLSchema}attribute")]
print(" %-22s 요소 %2d %s" % (nm, len(els), ", ".join(x for x in els if x)[:80]))
if ats: print(" 속성: %s" % ", ".join(x for x in ats if x)[:80])
print("\n■ 열거형 (코드 목록)")
n=0
for s in st:
nm=s.get("name")
en=[e.get("value") for e in s.iter("{http://www.w3.org/2001/XMLSchema}enumeration")]
if not en: continue
n+=1
print(" %-22s %2d개: %s" % (nm, len(en), ", ".join(en)[:92]))
print(" 열거형 %d" % n)
# 인라인 열거
inline=re.findall(r'name="([^"]+)"[^>]*>\s*<xsd:simpleType>\s*<xsd:restriction[^>]*>((?:\s*<xsd:enumeration value="[^"]*"/>)+)', t)
print("\n■ 인라인 열거 %d곳 (앞 14)" % len(inline))
for nm,blk in inline[:14]:
vals=re.findall(r'value="([^"]*)"', blk)
print(" %-22s %2d개: %s" % (nm, len(vals), ", ".join(vals)[:80]))
@@ -67,6 +67,8 @@
| 26 | **편집기와 사이클식**`Cm` 54꼴, 품셈 인자, 식 편집기, 낙찰율 |
| 27 | **계약·실행·기성 단계** — 설계 뒤 네 단계의 계산 구조 |
| 28 | **변환·수량산출·식언어** — 식 변수 대상/저장, 조달청 변환, 직종 106종 |
| 29 | **암호화자료의 뼈대** — 값 없이 구조만, 카탈로그 규모와 분류 깊이 |
| 30 | ⭐ **조달청 호환규정 XSD** — 국가 표준 납품 규격 전문 |
## 확정된 굵직한 것