feat(801-5): M01 로직 단위 글 건설품셈 원문 꼴 — 시간당 ㎥ · ㎡ → hr · 초 → sec · mm · cm · kg → ㎜ · ㎝ · ㎏ · TON · t → ton · km/hr → ㎞/hr
- 대응표 master_unit_text.RULES(규칙마다 원문 근거 절) · 빌더 build_단위표기_801_5(--check · --list · 셈 지문 전후 같을 때만 씀) - M01 로직 53 개 · 칸 79 개 글만 바꿈(변수 입력 · 중간 단위 · 결과단위) · 계수 · 소요량 표 값칸 · 호표 줄 단위 · 원문이 두 꼴을 다 쓰는 단위(㎞ · km · 분 · min)는 안 건드림 - M02 사본 새로 씀 도구 M02_Copy_Units(M02_Copy_Symbols 의 fill 만 바꿔 끼움) — 사본 16 문서 28 칸 · 금액 전후 같음 - 검토 목록 docs/raw/요구_1104/_목록_801-5_단위표기.xlsx - 옛 시험 기대 고침: test_796_3 굴착기 cm 단위 초 → sec(원문 표 머리 「싸이클시간(Sec)」) - 새 test_801_5_units 6 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -163,7 +163,7 @@ def test_표본_기호_단위_원문_같음():
|
||||
"작업효율",
|
||||
"체적환산계수",
|
||||
)
|
||||
assert (t["cm"]["이름"], t["cm"]["단위"]) == ("1회 싸이클시간", "초")
|
||||
assert (t["cm"]["이름"], t["cm"]["단위"]) == ("1회 싸이클시간", "sec") # 801-5 원문 표 머리 「싸이클시간(Sec)」 꼴
|
||||
|
||||
carry = (BOOK / "제01장_적용기준/1-02_설계_및_수량.md").read_text(encoding="utf-8")
|
||||
for line in (
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
"""801-5 M01 로직 단위 글 = 건설품셈 원문 꼴(요구 663-2) 지킴 — 글만 바꿈 · 금액 그대로.
|
||||
|
||||
① 대응표 근거 — 규칙마다 근거 절 파일이 있고 그 안에 원문 글이 실제로 있음(+ 지금 글은 같은 꼴로 안 쓰임)
|
||||
② 섞임 0 — M01 로직 입력 · 중간 · 결과단위가 원문 꼴로 다 바뀌어 있음(규칙이 더 바꿀 것 없음 · 두 번 돌려도 같음)
|
||||
③ 금액 같음 — 변수 단위 글을 지워도 엔진 셈 · 끝수 지문이 같음(단위 글은 셈에 안 듦)
|
||||
④ M02 사본 도구 — 같은 규칙으로 사본 줄 단위만 바뀌고 `판` 다시 셈
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
import importlib
|
||||
import re
|
||||
|
||||
import pytest
|
||||
|
||||
from M01_MasterData import M01_MasterData_Store as store
|
||||
|
||||
ut = importlib.import_module("master_unit_text")
|
||||
mf = importlib.import_module("master_formula")
|
||||
build = importlib.import_module("build_단위표기_801_5")
|
||||
|
||||
|
||||
def _rows():
|
||||
for data in store.loaded()[0].values():
|
||||
if data.get("그룹") == "로직":
|
||||
yield from data["줄"]
|
||||
|
||||
|
||||
def test_대응표_근거_절에_원문_글이_있음():
|
||||
assert len(ut.RULES) >= 7
|
||||
for name, _, to, token, files in ut.RULES:
|
||||
assert files and to == token, name
|
||||
for rel in files:
|
||||
path = ut.EVIDENCE_ROOT / rel
|
||||
assert path.is_file(), (name, rel)
|
||||
assert token in path.read_text(encoding="utf-8"), (name, rel)
|
||||
|
||||
|
||||
def test_규칙_예():
|
||||
got = {
|
||||
u: ut.canon(u)
|
||||
for u in ("㎥/시간", "㎡/시간", "㎢/시간", "원/시간", "초", "초/m", "mm", "TON/㎡")
|
||||
}
|
||||
assert got == {
|
||||
"㎥/시간": "㎥/hr",
|
||||
"㎡/시간": "㎡/hr",
|
||||
"㎢/시간": "㎢/시간", # 원문 9-5-4 가 쓰는 꼴 — 안 건드림
|
||||
"원/시간": "원/시간",
|
||||
"초": "sec",
|
||||
"초/m": "sec/m",
|
||||
"mm": "㎜",
|
||||
"TON/㎡": "ton/㎡",
|
||||
}
|
||||
for u in got.values():
|
||||
assert ut.canon(u) == u # 두 번 돌려도 같음
|
||||
|
||||
|
||||
def test_섞임_0_원문_꼴로_다_바뀜():
|
||||
left = []
|
||||
for row in _rows():
|
||||
units = [row.get("결과단위")] + [
|
||||
s.get("단위") for k in ("입력", "중간") for s in row.get(k) or []
|
||||
]
|
||||
left += [(row["키"], u) for u in units if u and ut.canon(u) != u]
|
||||
assert not left, left[:5]
|
||||
|
||||
|
||||
def test_굴착기_Cm_sec_Q_hr():
|
||||
row = store.loaded()[1].logic("GF000088") # 토사깍기(굴착기 0.7㎥) 시간당 작업량
|
||||
assert {s["단위"] for s in row["중간"] if s["이름"] == "Cm"} == {"sec"}
|
||||
assert row["결과단위"] == "㎥/hr"
|
||||
|
||||
|
||||
_OLD = ( # 원문 꼴 → 옛 글(되돌려 본 꼴) — 두 꼴로 셈이 같음을 대조
|
||||
(re.compile(r"(?<![가-힣A-Za-z])sec(?![A-Za-z])"), "초"),
|
||||
(re.compile(r"(?<=[㎥㎡])/hr"), "/시간"),
|
||||
(re.compile("㎜"), "mm"),
|
||||
(re.compile("㎝"), "cm"),
|
||||
(re.compile("㎏"), "kg"),
|
||||
(re.compile("㎞/hr"), "km/hr"),
|
||||
)
|
||||
|
||||
|
||||
def _legacy(text: str) -> str:
|
||||
for pat, old in _OLD:
|
||||
text = pat.sub(old, text)
|
||||
return text
|
||||
|
||||
|
||||
def test_금액_같음_옛_글로_되돌려도_셈_지문_같음():
|
||||
files = store.loaded()[0]
|
||||
old = copy.deepcopy(files)
|
||||
for data in old.values():
|
||||
if data.get("그룹") == "로직":
|
||||
for row in data["줄"]:
|
||||
for k in ("입력", "중간"):
|
||||
for s in row.get(k) or []:
|
||||
s["단위"] = _legacy(s.get("단위") or "")
|
||||
row["결과단위"] = _legacy(row.get("결과단위") or "")
|
||||
now, was = mf.Master(files), mf.Master(old)
|
||||
keys = [r["키"] for r in _rows()]
|
||||
hit = {
|
||||
r["키"]
|
||||
for r in _rows()
|
||||
if any(
|
||||
_legacy(s.get("단위") or "") != (s.get("단위") or "")
|
||||
for k in ("입력", "중간")
|
||||
for s in r.get(k) or []
|
||||
)
|
||||
}
|
||||
assert len(hit) >= 40
|
||||
for key in sorted(hit) + keys[::25]:
|
||||
assert build.fingerprint(now, now.logic(key)) == build.fingerprint(was, was.logic(key)), key
|
||||
|
||||
|
||||
def test_M02_사본_도구():
|
||||
cu = importlib.import_module("M02_MasterTemplete.M02_Copy_Units")
|
||||
old = {
|
||||
"로직": [
|
||||
{
|
||||
"키": "GC000001",
|
||||
"결과단위": "㎥/시간",
|
||||
"입력": [{"이름": "a", "단위": "mm"}],
|
||||
"중간": [{"이름": "Cm", "단위": "초"}],
|
||||
}
|
||||
],
|
||||
"판": "x",
|
||||
}
|
||||
new, done, _ = cu.fill(old, None)
|
||||
row = new["로직"][0]
|
||||
assert done == 3 and row["결과단위"] == "㎥/hr" and row["입력"][0]["단위"] == "㎜"
|
||||
assert row["중간"][0]["단위"] == "sec" and new["판"] != "x"
|
||||
assert cu.fill(new, None)[1] == 0 # 두 번째 = 바꿀 것 없음
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pytest.main([__file__, "-q"])
|
||||
Reference in New Issue
Block a user