| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- 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 = {item['MaterialTicker']: item for item in burn['OrderProduction']}
- net_consumption = []
- for c in burn['OrderConsumption'] + burn['WorkforceConsumption']:
- net = c['DailyAmount']
- if production := producing.get(c['MaterialTicker']):
- net -= production['DailyAmount']
- if net < 0:
- continue
- c['net_consumption'] = net
- net_consumption.append(c)
- vol_per_day = 0.0
- weight_per_day = 0.0
- target_days = float('inf')
- for consumption in net_consumption:
- ticker = consumption['MaterialTicker']
- vol_per_day += materials[ticker]['Volume'] * consumption['net_consumption']
- weight_per_day += materials[ticker]['Weight'] * consumption['net_consumption']
- days = inventory.get(ticker, 0) / consumption['net_consumption']
- if days < target_days:
- target_days = days
- print(f'consuming {vol_per_day:.1f}㎥/d')
- print(f'consuming {weight_per_day:.1f}t/d')
- target_days = round(target_days + 0.05, 1)
- while True:
- weight_used = volume_used = 0
- buy: dict[str, float] = {}
- for consumption in net_consumption:
- ticker = consumption['MaterialTicker']
- avail = inventory.get(ticker, 0)
- daily_consumption = consumption['net_consumption']
- days = avail / daily_consumption
- if days < target_days:
- buy[ticker] = (target_days - days) * daily_consumption
- weight_used += buy[ticker] * materials[ticker]['Weight']
- volume_used += buy[ticker] * materials[ticker]['Volume']
- if weight_used > 500 or volume_used > 500:
- break
- optimal = buy
- target_days += 0.1
- print('supply for', round(target_days, 1), 'days')
- for consumption in net_consumption:
- ticker = consumption['MaterialTicker']
- avail = inventory.get(ticker, 0)
- daily_consumption = consumption['net_consumption']
- 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
- net_consumption: float
- class Inventory(typing.TypedDict):
- MaterialTicker: str
- MaterialAmount: int
- class Material(typing.TypedDict):
- Ticker: str
- Weight: float
- Volume: float
- if __name__ == '__main__':
- main()
|