- 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>
40 lines
1.8 KiB
Python
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}
|