Merge remote-tracking branch 'origin/dev' into sub_laptop_1
This commit is contained in:
@@ -35,6 +35,8 @@ from B09_Estimation.B09_Estimation_ResourceAxis import (
|
||||
)
|
||||
|
||||
_RE_NUMBER = re.compile(r"^\d+(?:,\d{3})*(?:\.\d+)?$")
|
||||
#: 두께 갈래 칸 — 「20㎝」. 넓히면 규격 칸(「0.6㎥」)을 갈래로 오해한다.
|
||||
_RE_THICKNESS = re.compile(r"^\d+(?:\.\d+)?\s*(?:㎝|cm)$")
|
||||
#: 시공량 열을 알아보는 말. 「시 공 량 (㎡)」처럼 띄어쓰기가 섞여 온다.
|
||||
_OUTPUT_WORDS = ("시공량", "기준시공량", "적용시공량")
|
||||
|
||||
@@ -101,6 +103,7 @@ def parse_crew_table(
|
||||
members: list[CrewMember] = []
|
||||
outputs: list[Decimal] = []
|
||||
labels: list[str] = []
|
||||
thickness: list[tuple[str, Decimal]] = []
|
||||
|
||||
for row in rows:
|
||||
if not row or not row[0]:
|
||||
@@ -117,6 +120,11 @@ def parse_crew_table(
|
||||
names = [part for part in _normalize(head).split(" ") if part]
|
||||
resolved = [_resolve(catalog, name) for name in names]
|
||||
if not all(resolved):
|
||||
# 두께 갈래 줄 — 「30㎝ | 150」. 콘크리트 포장 12-6 은 두께 칸이 작업조 칸과
|
||||
# **줄을 엇갈려** 병합돼 있어(hwpx 확인) 마스터가 작업조 줄 사이에 두께 줄을 끼워 둔다.
|
||||
if _RE_THICKNESS.match(head) and len(_numbers_in(" ".join(row[1:]))) == 1:
|
||||
thickness.append((head, _numbers_in(" ".join(row[1:]))[0]))
|
||||
continue
|
||||
# 자원이 아니면 유형 라벨 줄로 본다 — 「복 잡 | 보 통 | 간 단」.
|
||||
if not _numbers_in(" ".join(row)):
|
||||
if not members:
|
||||
@@ -143,9 +151,17 @@ def parse_crew_table(
|
||||
# 시공량은 보통 **첫 작업조 줄**에 붙어 온다.
|
||||
if not outputs:
|
||||
outputs = _outputs_of(row, counts)
|
||||
# 작업조 줄에 두께 갈래가 붙어 온 자리 — 「포장공 | 3 | 20㎝ | 100 | …」.
|
||||
for label, value in zip(row, row[1:]):
|
||||
if _RE_THICKNESS.match(label) and _RE_NUMBER.match(value):
|
||||
thickness.append((label, Decimal(value.replace(",", ""))))
|
||||
|
||||
if not members:
|
||||
return "작업조 줄을 못 찾았습니다"
|
||||
if thickness:
|
||||
# 두께마다 시공량이 하나 — 그 옆 시공량 칸(「후진 진입·경운기 운반은 좌측의 50%까지 감」)은
|
||||
# **범위라 값이 아니다.** 유형 라벨은 그 두 칸의 머리라 두께 갈래와 짝이 아니다.
|
||||
return CrewTable(members=tuple(members), outputs=tuple(thickness))
|
||||
if not outputs:
|
||||
return "시공량 값을 못 찾았습니다"
|
||||
if labels and len(labels) != len(outputs):
|
||||
@@ -206,6 +222,16 @@ def match_crew_table(
|
||||
work_item_code = node.get("work_item_code", "")
|
||||
table_id = str(table.get("pum_table_id", ""))
|
||||
form = str(table.get("pum_form", ""))
|
||||
from B09_Estimation.B09_Estimation_WorkItemUnit import unit_of
|
||||
|
||||
if not unit and not unit_of(work_item_code):
|
||||
# 밑수가 「일당」이라 비어 있는 표(12-6) — 1단위당 품의 단위는 **시공량 열 머리**의 단위다.
|
||||
# ⚠ 공종 단위가 따로 적힌 자리는 그대로 둔다(12-2 에 딸린 비계 표가 m 를 들고 옴).
|
||||
headers = table.get("condition_note") or []
|
||||
found = [
|
||||
re.search(r"[((]\s*([^))]+?)\s*[))]", str(headers[i])) for i in output_columns(table)
|
||||
]
|
||||
unit = found[0].group(1) if found and found[0] else ""
|
||||
parsed = parse_crew_table(table, catalog)
|
||||
if isinstance(parsed, str):
|
||||
result.unmatched.append(
|
||||
|
||||
@@ -446,6 +446,13 @@ def match_table(
|
||||
|
||||
if match_process_sum_table(node, table, catalog, result, basis_quantity, unit):
|
||||
return
|
||||
# 머리가 두 단으로 병합된 표(인력 돌쌓기 13-4-1·13-4-4) — hwpx 병합으로 확인한 공종만.
|
||||
from B09_Estimation.B09_Estimation_ResourceAxis_TwoLevelHeader import (
|
||||
match_two_level_header_table,
|
||||
)
|
||||
|
||||
if match_two_level_header_table(node, table, catalog, result, basis_quantity, unit):
|
||||
return
|
||||
|
||||
from B09_Estimation.B09_Estimation_ResourceAxis_Transposed import match_transposed_table
|
||||
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
"""B09 원가계산 — **머리가 두 단으로 병합된 표** 읽기 (자원 축 보조, 2026-09-13).
|
||||
|
||||
인력 돌쌓기 13-4-1 메쌓기 · 13-4-4 찰쌓기 — hwpx 원본의 병합 칸으로 머리 모양을 확인함.
|
||||
|
||||
뒷길이(㎝) | 견치돌(4칸) | 깬돌(4칸) | 깬잡석(4칸) | 호박돌 및 야면석(2칸·두 줄 병합)
|
||||
| 골쌓기 켜쌓기 | 골쌓기 켜쌓기 | 골쌓기 켜쌓기 |
|
||||
| 석공 | 보통인부 × 7 벌
|
||||
35 | 0.50 | 0.40 | 0.55 | 0.44 | … | 0.16 | 0.14
|
||||
|
||||
마스터는 병합을 풀어 칸만 늘어놓아 **어느 값이 어느 돌·쌓기인지**가 사라졌다 — 행 읽기 길은
|
||||
「값 묶음 0 개가 갈래 6 개와 안 맞습니다」로 표째 버렸다.
|
||||
|
||||
읽는 법 — 자원 줄의 되풀이 폭(석공·보통인부 = 2)으로 **잎 칸 수**(14 ÷ 2 = 7)를 얻고,
|
||||
소분류 줄의 되풀이(골·켜 × 3)가 **앞의 대분류 셋**을 두 잎씩 먹고, 남은 대분류가 한 잎씩 먹는다.
|
||||
⚠ 「앞에서부터」는 hwpx 병합으로 확인한 두 표에만 참이다 — **적어 둔 공종만** 읽고,
|
||||
칸 수가 딱 맞지 않으면 한 줄도 안 세우고 막는다.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from decimal import Decimal
|
||||
from typing import Any
|
||||
|
||||
from B09_Estimation.B09_Estimation_ResourceAxis import (
|
||||
AxisResult,
|
||||
ResourceCatalog,
|
||||
ResourceRow,
|
||||
UnmatchedRow,
|
||||
parse_amount,
|
||||
)
|
||||
|
||||
#: 공종 → 확인 근거. 여기 없는 공종은 이 길로 안 읽는다.
|
||||
TWO_LEVEL_HEADER: dict[str, str] = {
|
||||
"FP-13-04-01": "hwpx 병합 — 견치돌·깬돌·깬잡석 4칸(골·켜) · 호박돌 및 야면석 2칸(행 병합)",
|
||||
"FP-13-04-04": "hwpx 병합 — 견치돌·깬돌·깬잡석 4칸(골·켜) · 호박돌 및 야면석 2칸(행 병합)",
|
||||
}
|
||||
_ABSENT = ("-", "-", "–", "—")
|
||||
|
||||
|
||||
def _label(text: Any) -> str:
|
||||
"""「견 치 돌」처럼 벌려 쓴 한 낱말은 붙이고, 「호박돌 및 야면석」은 그대로."""
|
||||
parts = str(text or "").split()
|
||||
return "".join(parts) if parts and all(len(p) == 1 for p in parts) else " ".join(parts)
|
||||
|
||||
|
||||
def _period(items: list[str]) -> int:
|
||||
"""되풀이 폭 — 딱 나뉘는 가장 짧은 주기. 없으면 전체 길이."""
|
||||
for width in range(1, len(items) + 1):
|
||||
if len(items) % width == 0 and items == items[:width] * (len(items) // width):
|
||||
return width
|
||||
return len(items)
|
||||
|
||||
|
||||
def match_two_level_header_table(
|
||||
node: dict[str, Any],
|
||||
table: dict[str, Any],
|
||||
catalog: ResourceCatalog,
|
||||
result: AxisResult,
|
||||
basis_quantity: Decimal | None,
|
||||
unit: str,
|
||||
) -> bool:
|
||||
"""적어 둔 공종의 두 단 머리 표를 읽는다. 그 공종이 아니면 `False`."""
|
||||
from B09_Estimation.B09_Estimation_CrewOutput import _resolve
|
||||
from B09_Estimation.B09_Estimation_ResourceAxis_ThreeAxis import _axis_label
|
||||
|
||||
code = str(node.get("work_item_code") or "")
|
||||
if code not in TWO_LEVEL_HEADER:
|
||||
return False
|
||||
table_id = str(table.get("pum_table_id", ""))
|
||||
head = list(table.get("condition_note") or [])
|
||||
rows = [[str(c).strip() for c in row] for row in (table.get("raw_row") or [])]
|
||||
|
||||
def block(why: str) -> bool:
|
||||
result.unmatched.append(UnmatchedRow(code, table_id, " | ".join(head), why))
|
||||
result.partial_items[code] = why
|
||||
return True
|
||||
|
||||
names = [c for c in rows[1] if c] if len(rows) >= 3 else []
|
||||
entries = [_resolve(catalog, "".join(name.split())) for name in names]
|
||||
if len(head) < 3 or len(names) < 2 or not all(entries):
|
||||
# 같은 절에 딸린 다른 표(뒷길이 표준·표준경사)다 — 원래 길로 보낸다.
|
||||
return False
|
||||
if basis_quantity in (None, 0):
|
||||
return block("두 단 머리 표에 밑수가 없습니다")
|
||||
groups = [_label(g) for g in head[1:]]
|
||||
subs = [_label(c) for c in rows[0] if c]
|
||||
width = _period([e.code for e in entries])
|
||||
leaves = len(names) // width
|
||||
cycle = _period(subs)
|
||||
split = len(subs) // cycle
|
||||
if split > len(groups) or split * cycle + (len(groups) - split) != leaves:
|
||||
return block(f"대분류 {len(groups)} · 소분류 {len(subs)} · 잎 {leaves} 칸이 딱 안 나뉩니다")
|
||||
leaf_labels = [[g, s] for g in groups[:split] for s in subs[:cycle]]
|
||||
leaf_labels += [[g] for g in groups[split:]]
|
||||
|
||||
staged: list[ResourceRow] = []
|
||||
for index, cells in enumerate(rows[2:], start=2):
|
||||
values = [c for c in cells[1:] if c]
|
||||
if not cells or not cells[0]:
|
||||
continue
|
||||
readable = all(v in _ABSENT or parse_amount(v) is not None for v in values)
|
||||
if len(values) != len(names) or not readable:
|
||||
return block(
|
||||
f"뒷길이 {cells[0]} 줄의 값 {len(values)} 칸이 자원 {len(names)} 칸과 안 맞습니다"
|
||||
)
|
||||
for position, (value, entry) in enumerate(zip(values, entries)):
|
||||
if value in _ABSENT:
|
||||
continue # 그 돌·뒷길이엔 품이 없다
|
||||
labels = leaf_labels[position // width]
|
||||
staged.append(
|
||||
ResourceRow(
|
||||
work_item_code=code,
|
||||
pum_table_id=table_id,
|
||||
pum_form=str(table.get("pum_form", "")),
|
||||
resource_kind=entry.kind,
|
||||
resource_code=entry.code,
|
||||
resource_name=entry.name,
|
||||
resource_spec=entry.spec,
|
||||
amount=parse_amount(value) / basis_quantity,
|
||||
amount_unit=unit,
|
||||
raw_row_index=index,
|
||||
variant=" · ".join([*labels, _axis_label(_label(head[0]), cells[0])]),
|
||||
)
|
||||
)
|
||||
result.rows.extend(staged)
|
||||
return True
|
||||
@@ -50,4 +50,4 @@
|
||||
- 실무 레시피 350개 중 품셈 근거문구 보유는 82개뿐이다. 근거 없는 268개는 현행값으로 임의 확정하지 않는다.
|
||||
- 과거 임도품셈 절 번호가 현행 산림사업 표준품셈에서 크게 바뀌었다. 번호만 같은 다른 절을 자동 연결하지 않는다.
|
||||
- JSON의 `수량문자_확인`은 후보 절 본문에 같은 숫자가 있는지를 세는 1차 검색값이다. `일치` 확정은 위 두 항목처럼 조건과 행을 직접 대조한 경우만 한다.
|
||||
- 후속 판 대응표는 `33_임도품셈_판_대응표.md`와 `30_원자료/임도품셈_판_대응표.csv`에 작성했다. 확정 2·추정 11·미확인 1이며, 추정·미확인은 자동 치환에 쓰지 않는다.
|
||||
- 후속 판 대응표는 `33_임도품셈_판_대응표.md`와 `30_원자료/임도품셈_판_대응표.csv`에 작성했다. 2017·2018·2024 원문 대조 결과 확정 12·미확인 2이며, 미확인은 자동 치환에 쓰지 않는다.
|
||||
|
||||
@@ -1,28 +1,37 @@
|
||||
# 과거 임도품셈 ↔ 2026 현행 산림사업 표준품셈 대응표
|
||||
|
||||
작성일: 2026-09-13
|
||||
|
||||
산출물: `30_원자료/임도품셈_판_대응표.csv`
|
||||
|
||||
현행 기준: 산림청고시 제2025-82호, 2026-01-01 시행
|
||||
|
||||
## 결과
|
||||
|
||||
STmate 레시피에 남은 임도계 품셈 인용 **14개를 전수 등록**했다.
|
||||
STmate 레시피의 임도계 품셈 인용 14개를 2017 임도표준품셈, 2018 통합 초판, 2024 개정판, 2026 현행판 순으로 대조했다.
|
||||
|
||||
| 판정 | 수 | 뜻 |
|
||||
|---|---:|---|
|
||||
| 확정 | 2 | 명칭·적용조건과 관측 수량을 현행 원문에서 직접 대조 |
|
||||
| 추정 | 11 | 명칭·공종 맥락으로 현행 후보를 특정했으나 과거 원문판 또는 수량 대조가 부족 |
|
||||
| 미확인 | 1 | 현행 후보가 작업방식까지 같다는 근거가 없음 |
|
||||
| 확정 | 13 | 절 이동 경로와 표의 장비·계수·수량 또는 현행 원문의 적용 대상을 직접 대조 |
|
||||
| 추정 | 0 | 원문 대조 후 남은 추정 없음 |
|
||||
| 미확인 | 1 | 외부 건설품셈을 참조하여 현행 산림품셈 절로 연결 불가 |
|
||||
|
||||
확정은 `2-3 제근 → 9-21 제근`과, STmate에서 `4-16-2`로 인용한 **절취없는 단끊기** → `5-16-1 단끊기` 두 건이다. 후자는 보통인부 `0.34·0.36·1.17인/100m`가 현행 세 공정과 각각 일치하는 범위에서만 확정했다.
|
||||
2018 통합 초판의 목차에는 2017 임도품셈 번호가 괄호로 직접 병기되어 있다. 이 표기로 `3-3-1→4.3.2`, `3-3-2→4.3.3`, `3-6→4.24`, `3-7→4.25`, `5-1-1→4.27.1`, `5-1-2→4.27.2`, `7-3→4.40`을 확인했다. 2024 개정판과 2026 현행판은 실제 표의 장비 규격, 작업능력, 계수와 수량까지 대조했다.
|
||||
|
||||
## 코드 사용 규칙
|
||||
## 추가 확인 결과
|
||||
|
||||
- 대응표의 현행 절은 `work_item_master_2026-01-01.json`의 `FP-*` 코드와 표 ID를 함께 기록했다.
|
||||
- 과거 한 절이 현행 여러 절로 나뉜 후보는 슬래시로 모두 보존했다. 대표 코드 하나를 임의 선택하지 않는다.
|
||||
- `추정`과 `미확인`은 코드 자동 치환에 사용하지 않는다. 값도 옮기지 않고 확인 대기로 세운다.
|
||||
- 과거 판본 원문이 확보되면 표 제목·주석·수량을 대조해 `추정 → 확정` 또는 `미확인`으로 갱신한다.
|
||||
- `7-3 노면다짐`: 2017·2018 원문 모두 자체 품 없이 건설품셈 기계화 시공을 참조한다. 2024판 목차에는 노면다짐이 없고, 현행 `3-4-3`은 인력식 노면 보수이므로 대응 절을 `미확인`으로 유지한다.
|
||||
- `9-3 임도성토면다짐`: 공종은 `2017 3-6 → 2018 4.24 → 2024 8-18 → 현행 9-17-1 비탈면 다짐`으로 이어진다. 현행 원문도 `임도성토면 다짐` 적용, 굴착기 부착용 유압식 진동 콤펙터와 굴착기 `0.7㎥`, `A=77.7㎡/시간`을 직접 명시하므로 절 대응은 `확정`한다. 다만 STmate의 `9-3`과 `Q=716.8`은 원문과 불일치하므로 해당 번호·값은 복사하지 않는다.
|
||||
|
||||
## 경계
|
||||
## 사용 경계
|
||||
|
||||
저장소에는 2026 현행판만 있고 STmate가 인용한 과거 임도품셈 원문판은 없다. 따라서 같은 이름이라는 이유만으로 확정하지 않았다. 특히 `7-3 노면정리`는 현행 `3-4-3`의 인력식 노면정지·노면굴기와 작업방식이 달라 현행 절을 `미확인`으로 남겼다.
|
||||
- 확정 13건은 **절 번호 대응**이 확정된 것이다. STmate 레시피의 값 전체가 현행에 적합하다는 뜻은 아니다.
|
||||
- 과거 한 절이 현행 여러 절로 분리된 `선떼붙이기공`과 `암절취`는 일대다 대응을 유지한다. 대표 하위 절 하나로 자동 치환하지 않는다.
|
||||
- `5-1-1 나 암절취`의 STmate 장비 규격 `굴삭기 0.4㎥`는 원문 `0.7㎥`와 다르므로 절 대응과 별개로 값 복사를 금지한다.
|
||||
|
||||
## 확인 원문
|
||||
|
||||
- 산림청, `임도표준품셈 최종파일 188264.pdf`(2017): 인쇄면 32, 38, 63~65, 91쪽
|
||||
- 산림청, `2018년도 산림사업 표준품셈-최종.pdf`: 목차의 구절→신절 병기 및 4.16.2·4.16.4·4.39
|
||||
- 산림청, `2024년도 개정판 안전 산림사업 표준품셈.pdf`: 인쇄면 60, 62, 146~148, 156~167, 188쪽
|
||||
- 2026 현행: `resources/knowledge/original/행정규칙/임도 품셈 적용기준 (현 산림사업 표준품셈)/첨부/(산림청고시 제2025-82호) 산림사업 표준품셈.md` 9-17-1 및 `resources/data_work_item_master/work_item_master_2026-01-01.json`
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
과거판,과거_절,과거_인용명,STmate_적용공종,현행판,현행_절,현행_FP코드,현행_명칭,현행_표ID,판정,근거와_경계
|
||||
"판본 미확인(STmate 2024~2025 출력)","번호 미기재","되메우기 및 다짐","구조물 되메우기(사질양토) 기계100%(굴삭기 0.7㎥)","산림청고시 2025-82호(2026-01-01)","9-14-1","FP-09-14-01","되메우기","F0279","추정","공종명과 적용맥락 일치. 과거 절 번호·원문 미확보"
|
||||
"판본 미확인(STmate 2024~2025 출력)","5-1-2 사","암터파기","구조물터파기(육상암 0~1m) 기계100%(굴삭기 0.7㎥)","산림청고시 2025-82호(2026-01-01)","9-13-7","FP-09-13-07","육상 암절취(0~1m)","F0267","추정","구조물·육상암·0~1m 조건 일치. 수량 전수 대조 전"
|
||||
"판본 미확인(STmate 2024~2025 출력)","7-3","노면정리(건설품셈 기계 시공 적용)","노면정리","산림청고시 2025-82호(2026-01-01)","미확인","미확인","미확인","미확인","미확인","현행 3-4-3은 노면정지·노면굴기 인력 보수표라 기계식 노면정리와 동일하다고 볼 수 없음"
|
||||
"판본 미확인(STmate 2024~2025 출력)","4-16-2","선떼붙이기공","단끊기","산림청고시 2025-82호(2026-01-01)","5-16 / 5-16-1 / 5-16-2","FP-05-16 / FP-05-16-01 / FP-05-16-02","선떼붙이기공 / 단끊기 / 선떼붙이기","F0121 / F0122","추정","과거 한 절이 현행 부모와 두 하위 절로 분리된 후보. 단끊기 일부만 별도 확정"
|
||||
"판본 미확인(STmate 2024~2025 출력)","4-16-2","절취없는 단끊기","단끊기 절취없음","산림청고시 2025-82호(2026-01-01)","5-16-1","FP-05-16-01","단끊기","F0121","확정","보통인부 0.34·0.36·1.17인/100m가 현행 세 공정과 각각 일치. 적용범위는 절취없는 구성에 한정"
|
||||
"판본 미확인(STmate 2024~2025 출력)","3-6 가","임도성토면 다짐","성토사면다짐 B/H0.7+콤팩터","산림청고시 2025-82호(2026-01-01)","9-17-1","FP-09-17-01","비탈면 다짐","미확인","추정","성토사면과 현행 비탈면 다짐의 기능상 후보. 현행 마스터에 직접 표가 없어 수량 대조 필요"
|
||||
"판본 미확인(STmate 2024~2025 출력)","9-3","임도성토면다짐","성토사면다짐 굴삭기0.7㎥","산림청고시 2025-82호(2026-01-01)","9-17-1","FP-09-17-01","비탈면 다짐","미확인","추정","같은 STmate 자료 안에서도 과거 절 인용이 3-6과 9-3으로 갈림. 과거 판본부터 확인 필요"
|
||||
"판본 미확인(STmate 2024~2025 출력)","4-16-4","파종공","씨뿌리기(성토면) 줄파종","산림청고시 2025-82호(2026-01-01)","5-18","FP-05-18","씨뿌리기(줄)","F0125","추정","줄파종·씨뿌리기 명칭과 적용맥락 일치. 과거 원문·수량 미대조"
|
||||
"판본 미확인(STmate 2024~2025 출력)","3-3-2","굴삭기 적용 암절취","암절취 굴삭기0.7㎥+대형브레카","산림청고시 2025-82호(2026-01-01)","9-4 / 9-4-1 / 9-4-2","FP-09-04 / FP-09-04-01 / FP-09-04-02","암절취 / 암파쇄 / 집토","F0241 / F0242","추정","현행은 암절취를 암파쇄+집토 단계합산형으로 분리. 과거 한 절과 일대다 후보"
|
||||
"판본 미확인(STmate 2024~2025 출력)","2-3","제근(100㎡당)","제근","산림청고시 2025-82호(2026-01-01)","9-21","FP-09-21","제근","F0294","확정","밀림 보통인부 0.05인이 현행 9-21과 직접 일치"
|
||||
"판본 미확인(STmate 2024~2025 출력)","5-1-1 나","암절취","측구터파기(암) 기계100%(굴삭기 0.4㎥)","산림청고시 2025-82호(2026-01-01)","9-12-2","FP-09-12-02","암절취","F0259","추정","측구터파기·암 조건으로 현행 절 후보 특정. 수량·장비조건 미대조"
|
||||
"판본 미확인(STmate 2024~2025 출력)","3-7 가","층따기","층따기","산림청고시 2025-82호(2026-01-01)","9-18","FP-09-18","층따기","F0287","추정","명칭 직접 일치하지만 과거 원문판이 없어 절 동일성 확정 불가"
|
||||
"판본 미확인(STmate 2024~2025 출력)","3-3-1","토사 굴삭기 적용","토사절취(흙깎기) 굴삭기0.7㎥","산림청고시 2025-82호(2026-01-01)","9-3-2","FP-09-03-02","기계","F0240","추정","현행 9-3 토사깍기의 기계 하위 절 후보. 수량·토질조건 미대조"
|
||||
"판본 미확인(STmate 2024~2025 출력)","4-39","쇄석·혼합석 부설","혼합석부설 T=0.1m","산림청고시 2025-82호(2026-01-01)","11-4","FP-11-04","쇄석․혼합석 부설","F0328","추정","명칭 직접 일치하지만 두께·장비·수량 조건 미대조"
|
||||
"STmate_인용판","과거_절","과거_인용명","STmate_적용공종","2017_임도품셈","2018_통합품셈","2024_개정품셈","현행_절","현행_FP코드","현행_명칭","현행_표ID","판정","근거와_경계"
|
||||
"판본 미확인","번호 미기재","되메우기 및 다짐","구조물 되메우기(사질양토) 기계100%(굴삭기 0.7㎥)","미확인","미확인","8-13 되메우기 및 다짐","9-14-1","FP-09-14-01","되메우기","F0279","확정","2024 8-13과 현행 9-14-1의 굴삭기 0.7㎥·k=0.9·f=0.69·E=0.65·Cm=18(90°)가 동일. 인용 절·판본은 미확인이고 대응은 되메우기 구성에 한정"
|
||||
"2017 임도표준품셈","5-1-2 사","암터파기","구조물터파기(육상암 0~1m) 기계100%(굴삭기 0.7㎥)","5-1-2 사 육상 암절취(0~1m)","4.27.2 구조물터파기","8-12 사 육상 암절취(0~1m)","9-13-7","FP-09-13-07","육상 암절취(0~1m)","F0267","확정","2018 목차에 5-1-2→4.27.2가 직접 병기되고 2024·현행의 인력10%+장비90%, 브레이커 Q=3.5, 치즐 0.006, 굴삭기 0.7㎥ 계수가 동일"
|
||||
"2017 임도표준품셈","7-3","노면정리(건설품셈 기계 시공 적용)","노면정리","7-3 노면다짐","4.40 노면다짐","미확인","미확인","미확인","미확인","미확인","미확인","2017과 2018은 해당 절에서 건설품셈 기계화 시공을 외부 참조할 뿐 자체 표가 없음. 2024 목차에 노면다짐이 없고 현행 3-4-3은 인력식 노면 보수이므로 연결 금지"
|
||||
"2018 통합 산림사업 표준품셈","4-16-2","선떼붙이기공","단끊기","선행 사방품셈 4-2-2","4.16.2 선떼붙이기공","4-16 선떼붙이기공","5-16 / 5-16-1 / 5-16-2","FP-05-16 / FP-05-16-01 / FP-05-16-02","선떼붙이기공 / 단끊기 / 선떼붙이기","F0121 / F0122","확정","2018 절과 2024 절이 직접 이어지고 현행은 단끊기·선떼붙이기로 분리. 일대다 대응으로 확정하며 대표 하위 절 하나로 자동 치환하지 않음"
|
||||
"2018 통합 산림사업 표준품셈","4-16-2","절취없는 단끊기","단끊기 절취없음","선행 사방품셈 4-2-2","4.16.2 선떼붙이기공","4-16 가 단끊기","5-16-1","FP-05-16-01","단끊기","F0121","확정","2024와 현행의 수평잡기·단정리 0.34, 잡석·뿌리정리 0.36, 절·성토면고르기 1.17인/100m가 동일. 절취없는 구성에 한정"
|
||||
"2017 임도표준품셈","3-6 가","임도성토면 다짐","성토사면다짐 B/H0.7+콤팩터","3-6 임도성토면 다짐","4.24 임도성토면 다짐","8-18 임도성토면 다짐","9-17-1","FP-09-17-01","비탈면 다짐","미확인","확정","2018 목차에 3-6→4.24가 직접 병기되고 2017·2024 모두 굴삭기 부착 유압식 진동 콤팩터+굴삭기 0.7㎥, A=77.7㎡/hr로 동일. 현행은 명칭을 비탈면 다짐으로 변경"
|
||||
"판본·인용 오류 미확인","9-3","임도성토면다짐","성토사면다짐 굴삭기0.7㎥","3-6 임도성토면 다짐","4.24 임도성토면 다짐","8-18 임도성토면 다짐","9-17-1","FP-09-17-01","비탈면 다짐","미확인","확정","공종·장비는 2017 3-6→2018 4.24→2024 8-18→현행 9-17-1로 이어짐. 현행 원문이 임도성토면 다짐, 굴착기 부착 유압식 진동 콤펙터+굴착기 0.7㎥, A=77.7㎡/hr를 직접 명시함. STmate의 9-3과 Q=716.8은 원문과 불일치하므로 절 대응만 확정하고 해당 번호·값 복사는 금지"
|
||||
"2018 통합 산림사업 표준품셈","4-16-4","파종공","씨뿌리기(성토면) 줄파종","선행 사방품셈 4-2-4","4.16.4 파종공","4-18 씨뿌리기(줄)","5-18","FP-05-18","씨뿌리기(줄)","F0125","확정","2024·현행의 종자 2g, 비료 29.3g, 특별인부 0.00055, 보통인부 0.00838인/m가 STmate 구성과 일치"
|
||||
"2017 임도표준품셈","3-3-2","굴삭기 적용 암절취","암절취 굴삭기0.7㎥+대형브레카","3-3-2 암절취","4.3.3 암절취","8-3 암절취","9-4 / 9-4-1 / 9-4-2","FP-09-04 / FP-09-04-01 / FP-09-04-02","암절취 / 암파쇄 / 집토","F0241 / F0242","확정","2018 목차에 3-3-2→4.3.3이 직접 병기되고 2024·현행은 암파쇄+집토로 분리. 브레이커 작업능력 5.0·3.4·2.6㎥/hr와 굴삭기 0.7㎥ 계수가 동일한 일대다 대응"
|
||||
"2017 임도표준품셈","2-3","제근(100㎡당)","제근","2-3 제근","4.20.2 제근","8-22 제근","9-21","FP-09-21","제근","F0294","확정","2018 목차에 2-3→4.20.2가 직접 병기되고 2024 8-22를 거쳐 현행 9-21로 이동. 밀림 보통인부 0.05인/100㎡ 일치"
|
||||
"2017 임도표준품셈","5-1-1 나","암절취","측구터파기(암) 기계100%(굴삭기 0.4㎥)","5-1-1 나 암절취","4.27.1 나 암절취","8-11 나 암절취","9-12-2","FP-09-12-02","암절취","F0259","확정","2018 목차에 5-1-1→4.27.1이 직접 병기됨. 2024·현행의 연암 Q=3.5, 치즐 0.006 및 측구터파기 조건이 동일. STmate 장비 규격 0.4㎥ 표기는 원문 0.7㎥와 불일치하므로 값 복사는 금지"
|
||||
"2017 임도표준품셈","3-7 가","층따기","층따기","3-7 층따기","4.25 층따기","8-19 층따기","9-18","FP-09-18","층따기","F0287","확정","2018 목차에 3-7→4.25가 직접 병기되고 2017·2024·현행 모두 굴삭기 0.7㎥, K=0.9, f=1/1.3, E=0.7, Cm=22(180°)가 동일"
|
||||
"2017 임도표준품셈","3-3-1","토사 굴삭기 적용","토사절취(흙깎기) 굴삭기0.7㎥","3-3-1 토사","4.3.2 토사깎기","8-2 토사깎기","9-3-2","FP-09-03-02","기계","F0240","확정","2018 목차에 3-3-1→4.3.2가 직접 병기되고 2017·2024·현행의 굴삭기 0.7㎥, K=0.9, f=1/1.30, E=0.55~0.45, Cm=20(135°)가 동일"
|
||||
"2018 통합 산림사업 표준품셈","4-39","쇄석·혼합석 부설","혼합석부설 T=0.1m","7-2 쇄석·혼합석 부설(선행)","4.39 쇄석·혼합석 부설","10-4 쇄석·혼합석 부설","11-4","FP-11-04","쇄석․혼합석 부설","F0328","확정","2018 목차에 7-2→4.39가 직접 병기됨. 2024·현행의 굴삭기 0.7㎥, q=0.7, k=0.55, f=1, E=0.35, Cm=20(135°)가 동일. T=0.1m 환산은 별도 계산"
|
||||
|
||||
|
@@ -144,3 +144,60 @@ def test_단끊기는_공정_줄을_더하고_작업반장을_20인당_1인_더
|
||||
other = AxisResult()
|
||||
match_table({"work_item_code": "FP-13-12-01"}, _단끊기, catalog, other)
|
||||
assert not other.rows
|
||||
|
||||
|
||||
_STONE = [*MACHINES, CatalogEntry("1033", "석공", "labor"), CatalogEntry("1019", "포장공", "labor")]
|
||||
|
||||
|
||||
def test_인력_찰쌓기_두_단_머리는_hwpx_병합대로_돌과_쌓기를_가른다():
|
||||
"""앞 세 돌은 골·켜 두 잎씩, 호박돌 및 야면석은 한 잎(행 병합) — 7 잎 × 석공·보통인부."""
|
||||
table = {
|
||||
"pum_table_id": "F-찰쌓기",
|
||||
"pum_form": "requirement",
|
||||
"basis_quantity": 1.0,
|
||||
"basis_unit": "㎡",
|
||||
"condition_note": ["뒷길이 (㎝)", "견 치 돌", "깬 돌", "깬 잡 석", "호박돌 및 야면석"],
|
||||
"raw_row": [
|
||||
["골쌓기", "켜쌓기", "골쌓기", "켜쌓기", "골쌓기", "켜쌓기", "", ""],
|
||||
["석 공 (인)", "보통인부 (인)"] * 7 + [""],
|
||||
["25", *["-"] * 8, "0.12", "0.12", "0.10", "0.10", "0.08", "0.10"],
|
||||
["35", "0.40", "0.40", "0.44", "0.44", "0.24", "0.24", "0.22", "0.22"]
|
||||
+ ["0.20", "0.20", "0.18", "0.18", "0.11", "0.14"],
|
||||
],
|
||||
}
|
||||
result = AxisResult()
|
||||
match_table({"work_item_code": "FP-13-04-04"}, table, ResourceCatalog(entries=_STONE), result)
|
||||
assert _codes(result, "견치돌 · 켜쌓기 · 뒷길이 35㎝") == {
|
||||
"1033": Decimal("0.44"),
|
||||
"1002": Decimal("0.44"),
|
||||
}
|
||||
assert _codes(result, "호박돌 및 야면석 · 뒷길이 35㎝") == {
|
||||
"1033": Decimal("0.11"),
|
||||
"1002": Decimal("0.14"),
|
||||
}
|
||||
assert not _codes(result, "견치돌 · 골쌓기 · 뒷길이 25㎝") # 「-」 — 그 뒷길이엔 품이 없음
|
||||
assert "FP-13-04-04" not in result.partial_items
|
||||
|
||||
|
||||
def test_콘크리트_포장_작업조는_두께마다_시공량으로_나눈다():
|
||||
"""12-6 — 두께 칸이 작업조 칸과 엇갈려 병합(hwpx) · 후진 진입 칸은 「50%까지 감」 범위."""
|
||||
table = {
|
||||
"pum_table_id": "F-포장",
|
||||
"pum_form": "reference",
|
||||
"condition_note": ["배치인원(인)", "포장두께", "시공량(㎥)"],
|
||||
"raw_row": [
|
||||
[
|
||||
"콘크리트믹서트럭 직접타설인경우",
|
||||
"콘크리트믹서트럭 후진 진입 또는 경운기 등으로 운반인 경우",
|
||||
],
|
||||
["포장공", "3", "20㎝", "100", "좌측 시공량의 50%까지 감하여 적용한다."],
|
||||
["30㎝", "150", "", "", ""],
|
||||
["보통인부", "3", "", "", ""],
|
||||
["40㎝", "200", "", "", ""],
|
||||
],
|
||||
}
|
||||
result = AxisResult()
|
||||
match_table({"work_item_code": "FP-12-06"}, table, ResourceCatalog(entries=_STONE), result)
|
||||
assert _codes(result, "20㎝") == {"1019": Decimal("0.03"), "1002": Decimal("0.03")}
|
||||
assert _codes(result, "40㎝")["1019"] == Decimal("0.015")
|
||||
assert {r.amount_unit for r in result.rows} == {"㎥"} # 시공량 열 머리의 단위
|
||||
|
||||
Reference in New Issue
Block a user