- 새 규칙 `master_doc_unit.fill` — 변환(`master_doc_convert.convert`) 끝에서 부름 · 빌더 · 실행 중 변환(SK 사본) 한 벌 · 보이는 변수 `단위` 칸만(연결 안 단위 · 셈 안 건드림) - 근거: 표 값칸 단위 · 「줄 따름」 류 = 고를 수 있는 행 단위 한 가지 · 기계 칸 = 기계 표 단위(천원 · 10^-7/시간 · ℓ/hr · ㎾h/hr · % · 인/일) · 노임 원/일 · 재료 · 유가 원/단위 · 부른 문서 결과단위 · 식 셈(천원 × 1000 · % ÷ 100 · 2 배 안 보정 계수) · 금액 줄 역산(줄 단위 = 단가 단위일 때 더하기로만 이은 변수) - 저장본 다시 지음: 1,520 문서 중 1,486 문서의 변수 단위 칸만 바뀜(채움 7,816 · 자리표시 「구분 따름」 · 「수」 · 나열 고침 982 · 표기 25) · 금액 대조 기본 1,520 같음 · 옵션 표본 18,873 중 다름 3 = 채택 1 원 셋 그대로 - 짐작은 안 채움(목록 tmp/845_1 · 시간환산 1/8 · 측량 직종 칸 · 식 속 수 상수 등) - 지킴 시험 test_845_1: 다시 채워도 바뀔 단위 0 · 자리표시 0 · 금액 줄 단위 = 단가 단위 · 사용자 그림 문서 · 단위 셈 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
103 lines
3.9 KiB
Python
103 lines
3.9 KiB
Python
"""845-1 수식 문서 변수 단위 채움 지킴 시험 (요구 880).
|
||
|
||
① 저장본 1,520 문서 — 채움 규칙(`master_doc_unit.fill`)을 다시 돌려도 바뀔 단위 0
|
||
(단위 있어야 할 줄에 빈 단위 0 · 남긴 짐작 빼고).
|
||
② 단위 칸에 자리표시 · 「수」 글이 남지 않음 — 행마다 다른 단위는 「줄 따름」 한 표기.
|
||
③ 단가 단위(원/X)를 가진 금액 줄은 줄 단위 X 와 맞음(노임 원/일 = 인 · 「D/M」 글 둘 뺌).
|
||
④ 사용자가 본 문서 — GC000088 Q_시공 ㎥ · GC000267 기계 칸(천원 · 10^-7/시간 · ℓ/hr · % · 인/일)
|
||
· C_손료 원/시간.
|
||
⑤ 단위 셈 — 천원 × 1000 · % ÷ 100 · 보정 계수(0.85) · 단위 품은 수(× 8)는 못 셈.
|
||
"""
|
||
|
||
import copy
|
||
import importlib
|
||
import json
|
||
from fractions import Fraction
|
||
from pathlib import Path
|
||
|
||
import pytest
|
||
|
||
from M01_MasterData import M01_MasterData_Store as m01 # scripts 길을 둠
|
||
|
||
mu = importlib.import_module("master_doc_unit")
|
||
md = importlib.import_module("master_doc")
|
||
FOLDER = Path(__file__).resolve().parents[1] / "master_data/수식문서"
|
||
|
||
|
||
@pytest.fixture(scope="module")
|
||
def saved():
|
||
return {
|
||
d["키"]: d
|
||
for f in sorted(FOLDER.glob("수식_*.json"))
|
||
for d in json.loads(f.read_text(encoding="utf-8"))["줄"]
|
||
}
|
||
|
||
|
||
@pytest.fixture(scope="module")
|
||
def whole():
|
||
return m01.loaded()[1]
|
||
|
||
|
||
def test_다시_채워도_바뀔_단위_없음(saved, whole):
|
||
assert len(saved) == 1520
|
||
left = {k: mu.fill(copy.deepcopy(d), whole) for k, d in saved.items()}
|
||
assert {k: v for k, v in left.items() if v} == {}
|
||
|
||
|
||
def test_자리표시_수_글_안_남음(saved):
|
||
bad = [
|
||
(k, v["열쇠"], v["단위"])
|
||
for k, d in saved.items()
|
||
for v in d["변수"]
|
||
if v.get("단위") in (*mu.ROW_UNIT, *mu.NOT_UNIT) and v["단위"] != mu.ROW
|
||
]
|
||
assert bad == []
|
||
|
||
|
||
def test_금액_줄_단위_단가와_맞음(saved):
|
||
miss = []
|
||
for k, d in saved.items():
|
||
units = mu.known(d)
|
||
for line in d["금액"]:
|
||
price = str(line.get("단가") or "").strip()
|
||
got = units.get(price) if md.good_id(price) else None
|
||
if line.get("단위") in ("식", "D/M") or got in (None, mu._TEXTV):
|
||
continue
|
||
if not mu.line_ok(line, units):
|
||
miss.append((k, line["이름"], line["단위"]))
|
||
assert miss == []
|
||
|
||
|
||
def _units(doc):
|
||
return {md.var_id(v): v.get("단위") for v in doc["변수"]}
|
||
|
||
|
||
def test_사용자_본_문서(saved):
|
||
assert _units(saved["GC000088"])["Q_시공"] == "㎥"
|
||
got = _units(saved["GC000267"])
|
||
assert got["P_기계"] == "천원"
|
||
assert got["k_기계상각비"] == got["k_기계관리비"] == "10^-7/시간"
|
||
assert got["P_기계주연료"] == "ℓ/hr" and got["r_기계잡재료"] == "%"
|
||
assert got["Q_기계조종원"] == "인/일" and got["w_기계운전사"] == "원/일"
|
||
assert got["C_손료"] == "원/시간" and got["r_가산"] == "%"
|
||
assert got["Q_시간환산"] == "" # 1/8 · 16/12 · 25/20 = 원본 칸 단위 빈칸 → 짐작(사용자 판단)
|
||
|
||
|
||
def test_단위_셈():
|
||
u = {
|
||
"Q": (Fraction(1), {"㎥": 1}),
|
||
"r": (Fraction(1, 100), {}),
|
||
"P": (Fraction(1000), {"원": 1}),
|
||
"k": (Fraction(1, 10**7), {"시간": -1}),
|
||
"C": (Fraction(1), {"대": 1}),
|
||
"S": mu._TEXTV,
|
||
}
|
||
assert mu.infer("Q × (1 - 만약(S == 'a', 0, r) ÷ 100)", u)[0] == "㎥"
|
||
assert mu.infer("Q × 만약(S == 'a', 0.85, 1)", u)[0] == "㎥"
|
||
assert mu.infer("P × 1000 × ((k + k) × (1 + r ÷ 100) + k) ÷ 10000000", u)[0] == "원/시간"
|
||
assert mu.infer("만약(S == 'a', 0, r)", u)[0] == "%"
|
||
assert mu.infer("C × 8 ÷ Q", u)[0] is None # 8 = 시간/일 — 지어내지 않음
|
||
assert mu.infer("3.33 × 1.07", u)[0] is None
|
||
assert mu.infer("만약(S == 'a', '가', '나')", u)[0] == "글"
|
||
assert mu.parse("1일 1대당") is None and mu.parse("%(주연료비의)") == (Fraction(1, 100), {})
|