diff --git a/tests/test_simulate.py b/tests/test_simulate.py index f9d5e5f..6ca31a2 100644 --- a/tests/test_simulate.py +++ b/tests/test_simulate.py @@ -57,23 +57,30 @@ def test_switched_off_recipes_produce_nothing_but_keep_workforce(sim): 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 +def test_area_matches_screenshots(): + """Screenshots (2026-09-18): full plan area 237, HWP-only area 102 - exact, no price dependency. + Degradation/plan_cost were checked against the same screenshots (2,141.74/737,076 and + 373.60/418,812) at the time and matched within rounding; not asserted here with those fixed + money values since they're priced in live material costs that drift with the market - a fixed + expected money value from one point in time isn't a meaningful regression check against an + input that never stops moving (a fresh screenshot would be, this isn't that). The formula + relationship itself (not tied to any particular price) is asserted instead, below.""" 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)): + for fname, area in (("base_plus_hwp.yaml", 237), ("hwp_only.yaml", 102)): 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) + r = simulate(plan, recipes, blds, planet["resources"], planet["fertility"], lambda t, side='both': 100.0) assert r["area"] == area - assert r["degradation"] == pytest.approx(degr, rel=0.03) and r["plan_cost"] == pytest.approx(cost, rel=0.03) + # Structural, price-independent regression check (puga/simulate.py): degradation is + # production-building cost only (infra/CM excluded) divided by 180 days; plan cost is + # production + infrastructure + one core module kit. Holds at any price, including this + # constant-100 lambda - catches a formula regression without depending on live prices. + assert r["degradation"] == pytest.approx(r["prod_cost"] / 180) + assert r["plan_cost"] == pytest.approx(r["prod_cost"] + r["infra_cost"] + r["cm_cost"]) def test_hq_multiplies_every_building_by_1_1(sim): diff --git a/tools/whatif.py b/tools/whatif.py index c1671ab..59f026d 100644 --- a/tools/whatif.py +++ b/tools/whatif.py @@ -107,9 +107,11 @@ def trip_tonnage(flows: dict, mats: dict): def marginal_freight(r_b, r_a, planet_id, cx, sf_price, ff_price, mats): """AIC/day freight for the EXTRA trips this addition requires - not the base's whole freight - bill. If the addition's materials fit in slack the base's existing traffic already has (the - common case for a small addition), this comes out to ~0: real freight cost only kicks in once - net t/m3 crosses into needing another round trip. Returns (freight_aic_per_day, note).""" + bill. Continuous amortized rate (extra tonnage/cargo-hold x round-trip cost), proportional to + the addition's own tonnage, not a step function - a small addition gets a small freight charge, + not exactly zero (that would need a real per-trip ceiling/rounding this doesn't model). Still + catches a recipe whose ROI looks great only because its freight cost was left out. Returns + (freight_aic_per_day, note).""" origin = shipping.cx_system(cx) if origin is None: return 0.0, f"no station found for CX {cx!r} - freight not modelled"