Add runway tool with auto-detected inbound ships; fix multi-base state tagging
- tools/runway.py: days of runway per material before a base stalls, from simulate()'s real net consumption, base storage, plus (by default) any ship currently flying to that planet - tools/state.py: tag each STORE entry with its planet (FIO AddressableId -> site SiteId) and each ship with its live flight origin/destination (keyed by ShipId, not StlFuelStoreId). Needed now that a 2nd base exists - storage/ship data was previously unscoped, which would have silently mixed bases' inventories together - tests, docs updated (docs/library.md notes the multi-base tagging as a reusable pattern) Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
import importlib.util
|
||||
from pathlib import Path
|
||||
|
||||
spec = importlib.util.spec_from_file_location("runway", Path(__file__).resolve().parent.parent / "tools" / "runway.py")
|
||||
runway = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(runway)
|
||||
|
||||
STATE = {
|
||||
"storage": [
|
||||
{"type": "STORE", "planet": "ZV-759c", "items": {"C": 6, "STL": 0}},
|
||||
{"type": "STORE", "planet": "ZV-194a", "items": {"RAT": 30}}, # Nike's, must not leak into Deimos
|
||||
{"type": "SHIP_STORE", "name": "AVI-07JFB", "items": {"C": 39, "STL": 15}},
|
||||
{"type": "SHIP_STORE", "name": "AVI-07JFC", "items": {"MCG": 205}}, # not inbound to Deimos in this fixture
|
||||
],
|
||||
"ships": [
|
||||
{"reg": "AVI-07JFB", "flight": {"destination": "Antares II (ZV-759) - Deimos (ZV-759c)"}},
|
||||
{"reg": "AVI-07JFC", "flight": {"destination": "Antares III (ZV-194) - Nike (ZV-194a)"}},
|
||||
{"reg": "AVI-IDLE", "flight": None},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def test_inbound_ships_matches_destination_planet():
|
||||
assert runway.inbound_ships(STATE, "ZV-759c") == ["AVI-07JFB"]
|
||||
assert runway.inbound_ships(STATE, "ZV-194a") == ["AVI-07JFC"]
|
||||
|
||||
|
||||
def test_inbound_ships_ignores_ships_with_no_flight():
|
||||
assert "AVI-IDLE" not in runway.inbound_ships(STATE, "ZV-759c")
|
||||
|
||||
|
||||
def test_on_hand_scopes_store_to_the_right_planet():
|
||||
have = runway.on_hand(STATE, "ZV-759c", ships=[])
|
||||
assert have == {"C": 6, "STL": 0} # Nike's RAT must not appear here
|
||||
|
||||
|
||||
def test_on_hand_adds_named_ship_cargo():
|
||||
have = runway.on_hand(STATE, "ZV-759c", ships=["AVI-07JFB"])
|
||||
assert have == {"C": 45, "STL": 15} # 6+39, 0+15
|
||||
|
||||
|
||||
def test_on_hand_with_inbound_ships_end_to_end():
|
||||
ships = runway.inbound_ships(STATE, "ZV-759c")
|
||||
have = runway.on_hand(STATE, "ZV-759c", ships)
|
||||
assert have == {"C": 45, "STL": 15} # only JFB counted, not JFC (heading to Nike)
|
||||
Reference in New Issue
Block a user