**① 기계 원천 벌 다시 뽑음**(`_build_mach.py`) — 랩탑 서브가 8장 md 를 크게 고친 뒤 · 연료 **214 → 274**(새 기계 60) · 손료 611 · 가격 613 — 값 바뀐 줄 가격 122 · 손료 122 · 연료 35 · 규격 세 줄짜리 표의 셋째 줄(출력 ㎾)이 되살아남 — 9070-0020 도 규격이 빈칸에서 「80ton대선 8ton달기」로 · ⭐ **금액 안 움직임** — 직접공사비 5,983,724 통과 ⬜ 남은 구멍 — 손료표 9020~9090 여덟 덩어리에서 코드를 못 읽음(`parse_audit`) · 연료 코드 수 272↔274 · 3108-0040 연료 갈래(중유↔경유). 장부에 주인(랩탑 메인)과 함께 적어 둠 **② 품셈 원천 벌도 다시 뽑음**(`_build_pum.py`) — 건설 표 둘 바뀜·둘 새로·둘 빠짐 **③ 「인」 밑수 셋 바로잡음**(안티그래비티 PDF 대조 · 브레인 판정) · F0046·F0068 — 비고의 「1인당」을 파서가 밑수로 읽고 있었음. **비워 둠**(사람 판정) · 미확보 목록에 「**원문 부재** — 사람 판정: …」 사유를 달아 다음 바퀴에 또 안 세어지게 함 ⭐ 「인은 밑수가 아니다」 2026-09-09 판정이 **넓게 옳았음** — 「숫자가 붙었을 때만 인정」이라는 예외(2-2-5 천공기)까지 물러남. 그 시험도 뒤집고 까닭을 적음 · F0076 — 목적물 1km 는 **정당한 밑수**였음(반쪽 아님). 뜻이 뒤집혀 있던 `productivity` 를 `requirement` 로 고침(값은 소요인력) ⇒ 사용자 판단이 **8 → 5** 로 줄어듦(남은 다섯: 부록 14-2 표 셋 · F0405 증가율표 성격 · 이형철근 범위) 밑수 확보 251 → 249 · 미확보 80 = 원문 부재 70 + 미판독 10 · 지문·이름표·시험 갱신 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsGw1Dz9HmhuAxGisxmDPF
85 lines
3.8 KiB
Python
85 lines
3.8 KiB
Python
"""마스터 밑수 판독 — 「인」과 「칸 이어붙임」 두 자리 (2026-09-09).
|
||
|
||
⚠⚠ **「인」은 품의 단위이지 공종 밑수가 아니다.** 원문 대조로 넷이 오독으로 드러났다 —
|
||
8-6-2 드론방제·8-6-3 지상방제 「(단위 : 인)」(그 「인」은 **소요인력**) ·
|
||
13-2-4 야면석 채집 「(단위: 인 당)」(표 안이 **㎡당·㎥당** 두 줄).
|
||
⚠ 2026-09-18 **2-2-5 천공기도 뒤집혔다** — 「천공인부 1인당 1대」의 「1인당」도 밑수가 아니었다
|
||
(PDF 대조 · 손료계수표라 애초에 밑수가 없음). ⇒ 「인」은 **숫자가 붙어도** 밑수가 아니다.
|
||
|
||
⚠⚠ **칸을 이어 붙여 읽지 않는다.** 앞 칸의 **값**과 뒤 칸의 **단위**가 붙어 없는 밑수가 생겼다 —
|
||
13-2-4 … 0.28 | **0.36** / **㎥당** | 0.60 … ⇒ 「0.36㎥당」(원문에 없는 값)
|
||
5-19-2 15 | **30**(표토두께 ㎝) / **㎥ 당** | … ⇒ 「30㎥당」(두께를 밑수로 읽음)
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import json
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
ROOT = Path(__file__).resolve().parents[2]
|
||
sys.path.insert(0, str(ROOT))
|
||
|
||
from B08_Quantity.B08_Quantity_Build_WorkItemMaster import ( # noqa: E402
|
||
detect_basis,
|
||
person_basis_ok,
|
||
)
|
||
|
||
MASTER = json.loads(
|
||
(ROOT / "resources" / "data_work_item_master" / "work_item_master_2026-01-01.json").read_text(
|
||
encoding="utf-8"
|
||
)
|
||
)
|
||
|
||
|
||
def 밑수(code: str) -> list[tuple]:
|
||
for item in MASTER["work_items"]:
|
||
if item["work_item_code"] == code:
|
||
return [
|
||
(t.get("basis_unit"), t.get("basis_quantity")) for t in (item.get("tables") or [])
|
||
]
|
||
return []
|
||
|
||
|
||
def test_숫자가_붙어야_인을_인정한다() -> None:
|
||
assert person_basis_ok("1", "인") is True
|
||
assert person_basis_ok("", "인") is False
|
||
assert person_basis_ok(None, "인") is False
|
||
# 「인」이 아닌 단위는 숫자가 없어도 그대로 — 종전 동작을 안 바꾼다.
|
||
assert person_basis_ok("", "㎥") is True
|
||
|
||
|
||
def test_방제_둘은_밑수가_안_선다() -> None:
|
||
"""「(단위 : 인)」은 소요인력이지 밑수가 아니다 — 미확보가 정직하다."""
|
||
assert all(unit != "인" for unit, _ in 밑수("FP-08-06-02"))
|
||
assert all(unit != "인" for unit, _ in 밑수("FP-08-06-03"))
|
||
|
||
|
||
def test_천공기도_인은_밑수가_아니다() -> None:
|
||
"""⚠ 2026-09-18 **뒤집음** — 「천공인부 1인당 1대」의 「1인당」도 밑수가 아니었다.
|
||
|
||
앞서는 「숫자가 붙었으니 인정」으로 두었으나, 안티그래비티 PDF 대조로 그 글이
|
||
**기계 한 대에 붙는 인원** 말임이 드러났다(2-2-5 는 손료계수표라 애초에 밑수가 없다).
|
||
⇒ 「인은 밑수가 아니다」는 2026-09-09 판정이 **넓게 옳았다** — 사람 판정으로 비워 둔다.
|
||
"""
|
||
assert 밑수("FP-02-02-05") == [(None, None)]
|
||
|
||
|
||
def test_칸을_이어_붙여_읽지_않는다() -> None:
|
||
"""앞 칸 값 + 뒤 칸 단위 = 없는 밑수. 두 실례를 그대로 잰다."""
|
||
table = {
|
||
"headers": ["뒷 길 이(㎝)", "25", "35", "45", "55", "60", ""],
|
||
"rows": [["인 부", "㎡당", "0.11", "0.17", "0.22", "0.28", "0.36"], ["㎥당", "0.60"]],
|
||
}
|
||
assert detect_basis(table) == (None, None)
|
||
두께표 = {
|
||
"headers": ["구 분", "직 종", "표 토 두 께(㎝)", "비고", ""],
|
||
"rows": [["15", "30", "", "", ""], ["㎥ 당", "보통인부", "0.14", "0.11", ""]],
|
||
}
|
||
assert 두께표 and detect_basis(두께표) == (None, None)
|
||
|
||
|
||
def test_한_칸_안의_밑수는_그대로_읽는다() -> None:
|
||
"""「100㎥당」처럼 한 칸에 다 있는 것은 종전대로 선다."""
|
||
assert detect_basis({"headers": ["(단위: 100㎥당)"], "rows": []}) == (100.0, "㎥")
|