"""253-2 운반 사이클시간 짝 — 거창 25 설계서 단가산출 1308~1347행 재현 · Py ↔ TS 거울 · 로직 입력 이름 채움 · B09 셈(hand_sources) 때 거리이정표 거리로 다시 채움.""" import json import re import subprocess import sys from pathlib import Path import pytest ROOT = Path(__file__).resolve().parents[2] sys.path.insert(0, str(ROOT)) from B08_Quantity.B08_Quantity_Haul_Cycle import cycle_time, fill_given # noqa: E402 from B09_Estimation.B09_Estimation_Sangeun import hand_sources # noqa: E402 from B09_Estimation.B09_Estimation_Store import ref_rows # noqa: E402 XLSX = next( (ROOT / "resources/knowledge/original/실무문서").glob( "01.산불거창*/01.내역서/00.25년_산불_거창*내역+수량.xlsx" ), None, ) #: 칸 → 입력 이름(단가산출 시트 · 32.혼합골재 운반(덤프15톤)) CELLS = {"S1318": "L1", "AR1318": "L2", "R1320": "V1", "R1321": "V2", "AQ1320": "V3", "AQ1321": "V4", "K1323": "T", "AB1323": "rt", "Q1325": "f", "L1327": "qs", "Z1327": "k", "AL1327": "Es", "BA1327": "Cms", "L1337": "t3", "X1337": "t4", "AK1337": "t5", "AW1337": "t6"} # fmt: skip @pytest.mark.skipif(XLSX is None, reason="거창 설계서 없음") def test_거창_혼합골재_운반_재현(): import openpyxl ws = openpyxl.load_workbook(XLSX, read_only=False)["단가산출"] inputs = {} for cell, name in CELLS.items(): text = str(ws[cell].value) # =TEXT(25.1,"#,##0.#######") inputs[name] = float(re.match(r"=TEXT\(([\d.]+),", text).group(1)) # 식 줄이 같은 꼴인지(t2 · Cm) assert ( "(S1318)/(R1320)+(S1318)/(R1321)+(AR1318)/(AQ1320)+(AR1318)/(AQ1321)" in ws["BX1334"].value ) assert "BQ1331+BX1334+L1337+X1337+AK1337+AW1337" in ws["CE1339"].value assert (inputs["L1"], inputs["L2"]) == (25.1, 0.8) got = cycle_time(inputs) assert (got["q"], got["n"], got["t1"]) == (8.82, 5.13, 5.33) assert (got["t2"], got["cm"]) == (101.23, 109.78) assert cycle_time({"L1": 25.1, "L2": 0.8}) == got # 기본값 = 거창 값 CASES = [ {"L1": 25.1, "L2": 0.8}, {"L1": 3.333, "L2": 1.257, "V1": 20, "V2": 25, "V3": 7, "V4": 8, "t5": 3.77}, {"L1": 0, "L2": 0, "t1": 2.5, "V3": 0}, {"L1": 12.5, "L2": 4.05, "T": 24, "rt": 1.8, "f": 0.8, "qs": 1.2, "k": 0.9, "Es": 0.75}, ] def test_거울_ts(): calc = ROOT / "B08_Quantity" / "B08_Quantity_Haul_Cycle.ts" body = ( f"\nconst cases = {json.dumps(CASES)};" "\nconsole.log(JSON.stringify(cases.map((c) => cycleTime(c))));" "\nconst ref = {given: {qt: 1, Cm: 9}, cycle: {L1: 99, t1: 7}, own: ['L1']};" "\nconst got = fillGiven(ref, ['Cm', 't2', '운반거리'], {L1: 25.1, L2: 0.8});" "\nconsole.log(JSON.stringify(got));" ) result = subprocess.run( ["node", "--experimental-strip-types", "--no-warnings", "--input-type=module-typescript", "-e", calc.read_text(encoding="utf-8") + body], capture_output=True, text=True, encoding="utf-8", timeout=60, ) # fmt: skip assert result.returncode == 0, result.stderr ts, ts_fill = (json.loads(line) for line in result.stdout.strip().splitlines()) assert ts == [cycle_time(c) for c in CASES] ref = {"given": {"qt": 1, "Cm": 9}, "cycle": {"L1": 99, "t1": 7}, "own": ["L1"]} assert ts_fill == fill_given(ref, ["Cm", "t2", "운반거리"], {"L1": 25.1, "L2": 0.8}) def test_입력_이름_채움(): ref = {"given": {"qt": 15}, "cycle": {}} got = fill_given(ref, ["qt", "Cm", "지역"], {"L1": 25.1, "L2": 0.8}) assert got == {"qt": 15, "Cm": 109.78} assert fill_given(ref, ["운반거리"], {"L1": 25.1, "L2": 0.8}) == {"qt": 15, "운반거리": 25.9} assert fill_given(ref, ["사이클시간", "t2"], {"L1": 25.1, "L2": 0.8}) == { "qt": 15, "사이클시간": 109.78, "t2": 101.23} # fmt: skip # 덮은 칸 = 그 값 · 덮은 L1 = 거리 대신 사이클 값 own = {"given": {"Cm": 50}, "own": ["Cm"]} assert fill_given(own, ["Cm"], {"L1": 25.1, "L2": 0.8}) == {"Cm": 50} mine = {"given": {}, "cycle": {"L1": 10}, "own": ["L1"]} assert fill_given(mine, ["운반거리"], {"L1": 25.1, "L2": 0.8}) == {"운반거리": 10.8} def test_서버_셈_거리로_다시_채움(): ref = {"tab": "logic", "code": "GF000134", "name": "골재운반", "given": {"Cm": 1}, "cycle": {}} user = {"haul_refs": {"haul:r-u1": ref}, "haul_dist": {"haul:r-u1": {"L1": 25.1, "L2": 0.8}}} ((_key, _use, src),) = hand_sources(user) assert src["given"]["Cm"] == 109.78 user["haul_dist"]["haul:r-u1"] = {"L1": 10, "L2": 0} # 거리 바뀌면 따라감 ((_key, _use, src),) = hand_sources(user) assert src["given"]["Cm"] == 45.69 and "운반거리" not in src["given"] # 그 로직 입력만 def test_덮개_ref_사이클_남김(): from B09_Estimation.B09_Estimation_Store import _clean_ref ref = {"tab": "logic", "code": "GF000134", "given": {"Cm": 3}, "cycle": {"V1": 20, "x": "a"}, "own": ["Cm", 3]} # fmt: skip got = _clean_ref(ref) assert got["cycle"] == {"V1": 20} and got["own"] == ["Cm"] rows = ref_rows({"bill": {"rows": [{"key": "haul:r-u1", "ref": got}]}}) assert rows[0]["ref"]["cycle"] == {"V1": 20}