"""Test vector: screenshots of PRUNplanner's simulator for plans/examples/base_plus_hwp.yaml (2026-09-18). Needs cached/online PRUNplanner data.""" import importlib.util from pathlib import Path import pytest, yaml ROOT = Path(__file__).resolve().parent.parent spec = importlib.util.spec_from_file_location("plan_push", ROOT / "tools" / "plan_push.py") plan_push = importlib.util.module_from_spec(spec) spec.loader.exec_module(plan_push) from puga import prunplanner as pp from puga.simulate import simulate @pytest.fixture(scope="module") def sim(): try: recipes, blds = pp.recipes(), pp.buildings() planet = pp._g("/data/planet/ZV-759c/", 3600) except Exception as e: # offline pytest.skip(f"no PRUNplanner data: {e}") plan = plan_push.build_payload(yaml.safe_load((ROOT / "plans" / "examples" / "base_plus_hwp.yaml").read_text()), recipes, {b["building_ticker"] for b in blds}) plan["plan_corphq"] = False # screenshots 1-3 were taken without HQ; plan files now say hq: true return lambda off=(): _run(plan, recipes, blds, planet, off) def _run(plan, recipes, blds, planet, off): import copy plan = copy.deepcopy(plan) for b in plan["plan_data"]["buildings"]: if b["name"] in off: for ar in b["active_recipes"]: ar["amount"] = 0 return simulate(plan, recipes, blds, planet["resources"], planet["fertility"], lambda t, side='both': 100.0) def test_efficiencies_and_workforce_match_screenshot(sim): r = sim() eff = {b["building"]: b["efficiency"] for b in r["buildings"]} assert eff["EXT"] == pytest.approx(1.0) and eff["SME"] == pytest.approx(1.337, abs=1e-4) and eff["HWP"] == pytest.approx(1.0696, abs=1e-4) wf = r["workforce"] assert (wf["pioneer"]["need"], wf["pioneer"]["supply"], wf["settler"]["supply"], wf["technician"]["open"]) == (370, 400, 100, -10) def test_material_flows_match_screenshot(sim): f = sim()["flows"] exp = {"AL": (42.78, 44.57), "ALO": (66.85, 56.00), "BHP": (0, 14.26), "C": (11.14, 0), "COF": (1.85, 0), "DW": (16.80, 0), "EXO": (0.20, 0), "FLX": (11.14, 0), "HE": (3.57, 0), "KOM": (0.40, 0), "O": (11.14, 0), "OVE": (1.85, 0), "PT": (0.20, 0), "PWO": (0.74, 0), "RAT": (17.20, 0), "REP": (0.08, 0), "STL": (3.57, 0)} for tk, (i, o) in exp.items(): assert f[tk]["inp"] == pytest.approx(i, abs=0.01) and f[tk]["out"] == pytest.approx(o, abs=0.01), tk def test_switched_off_recipes_produce_nothing_but_keep_workforce(sim): r = sim(off=("EXT", "SME")) assert r["flows"]["AL"]["out"] == 0 and "ALO" not in r["flows"] # no ALO row at all, as in the screenshot assert r["flows"]["DW"]["inp"] == pytest.approx(16.80, abs=0.01) # idle pioneers still consume (screenshot 2) assert r["flows"]["AL"]["inp"] == pytest.approx(42.78, abs=0.01) def test_cost_degradation_area_match_screenshots(): """Screenshots: full plan area 237, degradation 2,141.74, plan cost 737,076; HWP-only area 102, degradation 373.60, cost 418,812. Prices drift, so 3% tolerance on money values; area is exact.""" from puga import market try: recipes, blds = pp.recipes(), pp.buildings() planet = pp._g("/data/planet/ZV-759c/", 3600) snap = market.snapshot() except Exception as e: pytest.skip(f"offline: {e}") price = lambda t, side='both': market.uni30(snap, t) for fname, area, degr, cost in (("base_plus_hwp.yaml", 237, 2141.74, 737076.53), ("hwp_only.yaml", 102, 373.60, 418811.91)): plan = plan_push.build_payload(yaml.safe_load((ROOT / "plans" / "examples" / fname).read_text()), recipes, {b["building_ticker"] for b in blds}) plan["plan_corphq"] = False r = simulate(plan, recipes, blds, planet["resources"], planet["fertility"], price) assert r["area"] == area assert r["degradation"] == pytest.approx(degr, rel=0.03) and r["plan_cost"] == pytest.approx(cost, rel=0.03) def test_hq_multiplies_every_building_by_1_1(sim): """Screenshot 6: HWP 117.66% with HQ ticked (0.8 x 1.25 x 1.0696 x 1.1).""" import copy base = sim() assert next(b for b in base["buildings"] if b["building"] == "HWP")["efficiency"] == pytest.approx(1.0696, abs=1e-4) assert 1.0696 * 1.1 == pytest.approx(1.1766, abs=1e-4)