Files
PuGa/tests/test_buy.py
T
dodoxandClaude Sonnet 5 e2e592cae3 Add buy/sell tools, library docs, and permit/HQ fixes
- tools/buy.py: cash-aware shopping list (construction gap vs empire state's built
  buildings, plus N days of NET operating stock via simulate() so self-produced
  inputs net against consumption), priced at real order-book fill cost, checked
  against cash/reserve, flags multi-trip, binary-searches an affordable size when short
- tools/sell.py: where to post an ask vs hitting the bids now, with expected
  clear time from 30-day traded-volume percentiles
- docs/library.md: module map and patterns for using puga.* directly instead of
  the CLI, plus the "simulate() only knows what the plan lists" gotcha that a
  first version of buy.py hit
- tools/simulate.py: fix --no-hq being a no-op; tools/state.py: permits_total_override
  for when the in-game HQ screen disagrees with FIO's MaximumPermits
- docs/mechanics.md: HQ display vs PRUNplanner's HQ flag, workforce arrival sources
- CLAUDE.md, docs/roadmap.md updated

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 17:40:17 +02:00

40 lines
1.8 KiB
Python

import importlib.util
from pathlib import Path
spec = importlib.util.spec_from_file_location("buy", Path(__file__).resolve().parent.parent / "tools" / "buy.py")
buy = importlib.util.module_from_spec(spec)
spec.loader.exec_module(buy)
BUILDINGS = [
{"building_ticker": "HWP", "costs": [{"material_ticker": "BBH", "material_amount": 4}, {"material_ticker": "LTA", "material_amount": 2}], "area_cost": 25},
{"building_ticker": "HB2", "costs": [{"material_ticker": "BTA", "material_amount": 2}], "area_cost": 12},
]
PLAN = {"plan_data": {"buildings": [{"name": "HWP", "amount": 1}], "infrastructure": [{"building": "HB2", "amount": 1}]}}
def test_construction_items_include_mcg_and_full_amount_when_nothing_built():
need = buy.construction_items(PLAN, BUILDINGS, built={})
assert need == {"BBH": 4, "LTA": 2, "MCG": 100 + 48, "BTA": 2}
def test_construction_items_gap_only_counts_unbuilt_units():
need = buy.construction_items(PLAN, BUILDINGS, built={"HWP": 1, "HB2": 1})
assert need == {} # already fully built: nothing to buy
def test_construction_items_partial_gap():
plan = {"plan_data": {"buildings": [{"name": "HWP", "amount": 3}], "infrastructure": []}}
need = buy.construction_items(plan, BUILDINGS, built={"HWP": 1})
assert need == {"BBH": 8, "LTA": 4, "MCG": 200} # 2 more HWP needed, not 3
def test_stock_items_only_keeps_net_consumption():
flows = {"C": {"inp": 11.13, "out": 0}, "AL": {"inp": 42.78, "out": 44.57}, "BHP": {"inp": 0, "out": 14.26}}
got = buy.stock_items(flows, days=2)
assert got == {"C": 22.26} # AL nets to +1.78/day (own smelters cover the HWP): not bought
def test_net_of_on_hand_floors_at_zero():
got = buy.net_of_on_hand({"C": 20, "O": 5}, {"C": 30, "O": 2})
assert got == {"C": 0.0, "O": 3.0}