73 lines
2.9 KiB
Python
73 lines
2.9 KiB
Python
"""STMATE 재현 앱 계산 도구 — 노무·장비 수량 계산기(wM_Edit_XRate) · 실적→일식 비목율(wM_Conv_A2W).
|
||
|
||
근거: REA 30 labor_equipment_quantity_rules.json · REA 27 conversion_component_rate_rules.json — 손셈 대조.
|
||
수량 계산기 반올림(MROUNDUD) 방향은 미확정 — 반올림으로 둔 값은 경계가 아닌 수로만 봄.
|
||
"""
|
||
|
||
import json
|
||
import subprocess
|
||
from pathlib import Path
|
||
|
||
HELPER = Path(__file__).with_name("helper_stmate_smt_tools.cjs")
|
||
|
||
|
||
def call(*calls):
|
||
payload = [{"fn": f, "args": list(a)} for f, *a in calls]
|
||
out = subprocess.check_output(
|
||
["node", str(HELPER)], input=json.dumps(payload), text=True, encoding="utf-8"
|
||
)
|
||
return json.loads(out)
|
||
|
||
|
||
def test_xrate_daily_and_applied_quantity():
|
||
lab, eq, zero = call(
|
||
(
|
||
"compute",
|
||
{"qty1": 120, "cond": "0.9*1.1", "hrat": 80, "lqty": 3, "labor": True, "point": 4},
|
||
),
|
||
(
|
||
"compute",
|
||
{"qty1": 120, "cond": "", "hrat": 100, "lqty": 1, "labor": False, "auto": True},
|
||
),
|
||
("compute", {"qty1": 0, "cond": "", "hrat": 100, "lqty": 2, "labor": True, "point": 3}),
|
||
)
|
||
# 120 × 0.99 × 80% = 95.04 · 노무 3 × 1 ÷ 95.04 = 0.031565… → 4 자리 0.0316
|
||
assert lab["qday"] == 95.04 and lab["cqty"] == 0.0316 and abs(lab["cond"] - 0.99) < 1e-12
|
||
# 장비 1 × 8 ÷ 120 = 0.0666… · 자동 자리 = 「120」 3자리 + 1 = 4 → 0.0667
|
||
assert eq["point"] == 4 and eq["cqty"] == 0.0667
|
||
assert zero["qday"] == 0 and zero["cqty"] == 0
|
||
|
||
|
||
def test_xrate_auto_point_and_condition_chars():
|
||
p1, p2, p3, bad, paren, power = call(
|
||
("autoPoint", 5.5),
|
||
("autoPoint", 123456.0),
|
||
("autoPoint", 1234),
|
||
("condFactor", "0.9 * a"),
|
||
("condFactor", "(1+2)"),
|
||
("condFactor", "2^3/4"),
|
||
)
|
||
assert (p1, p2, p3) == (2, 6, 5)
|
||
assert not bad["ok"] and not paren["ok"] and bad["value"] == 1
|
||
assert power == {"ok": True, "value": 2}
|
||
|
||
|
||
def test_a2w_editor_row_and_bulk():
|
||
e1, e2, e3, r1, r2 = call(
|
||
("normalizeEditor", 70, 50, "L"),
|
||
("normalizeEditor", 70, 50, "M"),
|
||
("normalizeEditor", 130, 0, "L"),
|
||
("normalizeRow", 70, 50, 10),
|
||
("normalizeRow", 70, 50, 9),
|
||
)
|
||
assert e1 == {"L": 70, "M": 30, "E": 0} and e2 == {"L": 50, "M": 50, "E": 0}
|
||
assert e3 == {"L": 100, "M": 0, "E": 0}
|
||
assert r1 == {"L": 50, "M": 50, "E": 0} and r2 == {"L": 70, "M": 30, "E": 0}
|
||
rows = [{"sel": True, "rateL": 0}, {"sel": True, "rateL": 80}, {"sel": False, "L": 5}]
|
||
plain, indiv = call(
|
||
("bulkApply", rows, {"L": 40, "M": 30}, {}),
|
||
("bulkApply", rows, {"L": 40, "M": 30}, {"individual": True}),
|
||
)
|
||
assert [(r["L"], r["M"], r["E"]) for r in plain] == [(40, 30, 30), (40, 30, 30), (0, 0, 0)]
|
||
assert [(r["L"], r["M"], r["E"]) for r in indiv] == [(40, 30, 30), (80, 20, 0), (0, 0, 0)]
|