|
|
@@ -15,16 +15,29 @@ def main() -> None:
|
|
|
p['MaterialTicker']: Price(p['VWAP7D'], p['AverageTraded7D']) for p in raw_prices # pyright: ignore[reportArgumentType]
|
|
|
if p['ExchangeCode'] == 'IC1' and p['VWAP7D'] is not None
|
|
|
}
|
|
|
+ habitation: typing.Mapping[Worker, str] = {
|
|
|
+ 'Pioneers': 'HB1',
|
|
|
+ 'Settlers': 'HB2',
|
|
|
+ 'Technicians': 'HB3',
|
|
|
+ 'Engineers': 'HB4',
|
|
|
+ 'Scientists': 'HB5',
|
|
|
+ }
|
|
|
+ hab_area_cost: dict[Worker, float] = {}
|
|
|
+ hab_capex: dict[Worker, float] = {}
|
|
|
+ for worker, hab in habitation.items():
|
|
|
+ hab_area_cost[worker] = buildings[hab]['AreaCost'] / 100
|
|
|
+ hab_capex[worker] = building_construction_cost(buildings[hab], prices) / 100
|
|
|
|
|
|
profits: list[Profit] = []
|
|
|
for recipe in recipes:
|
|
|
- if profit := calc_profit(recipe, buildings, materials, prices):
|
|
|
+ if profit := calc_profit(recipe, buildings, hab_area_cost, hab_capex, materials, prices):
|
|
|
profits.append(profit)
|
|
|
profits.sort()
|
|
|
with open('www/roi.json', 'w') as f:
|
|
|
json.dump([dataclasses.asdict(p) for p in profits], f, indent='\t')
|
|
|
|
|
|
-def calc_profit(recipe: Recipe, buildings: typing.Mapping[str, Building], materials: typing.Mapping[str, Material],
|
|
|
+def calc_profit(recipe: Recipe, buildings: typing.Mapping[str, Building], hab_area_cost: typing.Mapping[Worker, float],
|
|
|
+ hab_capex: typing.Mapping[Worker, float], materials: typing.Mapping[str, Material],
|
|
|
prices: typing.Mapping[str, Price]) -> Profit | None:
|
|
|
try:
|
|
|
(output,) = recipe['Outputs']
|
|
|
@@ -37,8 +50,9 @@ def calc_profit(recipe: Recipe, buildings: typing.Mapping[str, Building], materi
|
|
|
return
|
|
|
revenue = output_price.vwap * output['Amount']
|
|
|
building = buildings[recipe['BuildingTicker']]
|
|
|
- capex = sum(bm['Amount'] * prices[bm['CommodityTicker']].vwap
|
|
|
- for bm in building['BuildingCosts'])
|
|
|
+ area = building['AreaCost'] + sum(hab_area_cost[worker] * building[worker] for worker in hab_area_cost)
|
|
|
+ capex = building_construction_cost(building, prices) + \
|
|
|
+ sum(hab_capex[worker] * building[worker] for worker in hab_capex)
|
|
|
profit_per_run = revenue - cost
|
|
|
runs_per_day = 24 * 60 * 60 * 1000 / recipe['TimeMs']
|
|
|
if building['Ticker'] in ('FRM', 'ORC'):
|
|
|
@@ -51,17 +65,20 @@ def calc_profit(recipe: Recipe, buildings: typing.Mapping[str, Building], materi
|
|
|
sum(materials[input['Ticker']]['Volume'] * input['Amount'] for input in recipe['Inputs']),
|
|
|
materials[output['Ticker']]['Weight'] * output['Amount'],
|
|
|
materials[output['Ticker']]['Volume'] * output['Amount'],
|
|
|
- ) * runs_per_day / building['AreaCost']
|
|
|
+ ) * runs_per_day / area
|
|
|
return Profit(output['Ticker'], recipe['RecipeName'],
|
|
|
expertise=building['Expertise'].replace('_', ' ').lower(),
|
|
|
profit_per_day=(profit_per_run * runs_per_day - worker_consumable_daily_cost),
|
|
|
- area=building['AreaCost'],
|
|
|
+ area=area,
|
|
|
capex=capex,
|
|
|
cost_per_day=cost_per_day,
|
|
|
logistics_per_area=logistics_per_area,
|
|
|
output_per_day=output_per_day,
|
|
|
average_traded_7d=output_price.average_traded_7d)
|
|
|
|
|
|
+def building_construction_cost(building: Building, prices: typing.Mapping[str, Price]) -> float:
|
|
|
+ return sum(bc['Amount'] * prices[bc['CommodityTicker']].vwap for bc in building['BuildingCosts'])
|
|
|
+
|
|
|
def building_daily_cost(building: Building, prices: typing.Mapping[str, Price]) -> float:
|
|
|
consumption = {
|
|
|
'Pioneers': [('COF', 0.5), ('DW', 4), ('RAT', 4), ('OVE', 0.5), ('PWO', 0.2)],
|
|
|
@@ -77,6 +94,8 @@ def building_daily_cost(building: Building, prices: typing.Mapping[str, Price])
|
|
|
cost += prices[mat].vwap * workers * per_100 / 100
|
|
|
return cost
|
|
|
|
|
|
+Worker = typing.Literal['Pioneers', 'Settlers', 'Technicians', 'Engineers', 'Scientists']
|
|
|
+
|
|
|
class Recipe(typing.TypedDict):
|
|
|
RecipeName: str
|
|
|
BuildingTicker: str
|