| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- from __future__ import annotations
- import sys
- import tomllib
- import typing
- import cache
- def main() -> None:
- planet = sys.argv[1].casefold()
- burn, raw_materials = fio_data(planet)
- inventory = {item['MaterialTicker']: item['MaterialAmount'] for item in burn['Inventory']}
- materials = {mat['Ticker']: mat for mat in raw_materials}
- producing = frozenset(item['MaterialTicker'] for item in burn['OrderProduction'])
- consumables = [c for c in burn['OrderConsumption'] + burn['WorkforceConsumption']
- if c['MaterialTicker'] not in producing]
- vol_per_day = 0.0
- weight_per_day = 0.0
- target_days = float('inf')
- for consumption in consumables:
- ticker = consumption['MaterialTicker']
- vol_per_day += materials[ticker]['Volume'] * consumption['DailyAmount']
- weight_per_day += materials[ticker]['Weight'] * consumption['DailyAmount']
- days = inventory.get(ticker, 0) / consumption['DailyAmount']
- if days < target_days:
- target_days = days
- print(f'consuming {vol_per_day:.1f}㎥/d')
- print(f'consuming {weight_per_day:.1f}t/d')
- limiting = 'Volume'
- if weight_per_day > vol_per_day:
- limiting = 'Weight'
- target_days = round(target_days + 0.05, 1)
- while True:
- space_used = 0
- buy: dict[str, float] = {}
- for consumption in consumables:
- ticker = consumption['MaterialTicker']
- avail = inventory.get(ticker, 0)
- daily_consumption = consumption['DailyAmount']
- days = avail / daily_consumption
- if days < target_days:
- buy[ticker] = (target_days - days) * daily_consumption
- space_used += buy[ticker] * materials[ticker][limiting]
- if space_used > 500:
- break
- optimal = buy
- target_days += 0.1
- print('supply for', round(target_days, 1), 'days')
- for consumption in consumables:
- ticker = consumption['MaterialTicker']
- avail = inventory.get(ticker, 0)
- daily_consumption = consumption['DailyAmount']
- days = avail / daily_consumption
- print(f'{ticker:>3}: {avail:5d} ({daily_consumption:8.2f}/d) {days:4.1f} d', end='')
- if need := optimal.get(ticker): # pyright: ignore[reportPossiblyUnboundVariable]
- print(f' | {need:8.1f}')
- else:
- print()
- def fio_data(planet: str) -> tuple[PlanetData, typing.Sequence[Material]]:
- with open('config.toml', 'rb') as f:
- config = tomllib.load(f)
- planets: list[PlanetData] = cache.get('https://rest.fnar.net/fioweb/burn/user/' + config['username'],
- headers={'Authorization': config['fio_api_key']})
- for planet_data in planets:
- name = planet_data['PlanetName']
- if name.casefold() == planet:
- assert planet_data['Error'] is None
- break
- else:
- raise ValueError(planet + ' not found')
- materials: list[Material] = cache.get('https://rest.fnar.net/material/allmaterials')
- return planet_data, materials
- class PlanetData(typing.TypedDict):
- PlanetName: str
- Error: typing.Any
- OrderConsumption: list[Amount]
- WorkforceConsumption: list[Amount]
- Inventory: list[Inventory]
- OrderProduction: list[Amount]
- class Amount(typing.TypedDict):
- MaterialTicker: str
- DailyAmount: float
- class Inventory(typing.TypedDict):
- MaterialTicker: str
- MaterialAmount: int
- class Material(typing.TypedDict):
- Ticker: str
- Weight: float
- Volume: float
- if __name__ == '__main__':
- main()
|