|
@@ -0,0 +1,107 @@
|
|
|
|
|
+'''share all plans in an account and generate a CSV of the construction materials'''
|
|
|
|
|
+
|
|
|
|
|
+from __future__ import annotations
|
|
|
|
|
+import collections
|
|
|
|
|
+import csv
|
|
|
|
|
+import sys
|
|
|
|
|
+import typing
|
|
|
|
|
+
|
|
|
|
|
+import httpx
|
|
|
|
|
+
|
|
|
|
|
+import cache
|
|
|
|
|
+
|
|
|
|
|
+def main():
|
|
|
|
|
+ jwt,= sys.argv[1:]
|
|
|
|
|
+
|
|
|
|
|
+ with httpx.Client(headers={'Authorization': 'Bearer ' + jwt}) as client:
|
|
|
|
|
+ plans: typing.Sequence[Plan] = client.get('https://api.prunplanner.org/baseplanner/').raise_for_status().json()
|
|
|
|
|
+ shared: typing.Mapping[str, str] = {s['plan_uuid']: s['shared_uuid']
|
|
|
|
|
+ for s in client.get('https://api.prunplanner.org/shared/list').raise_for_status().json()}
|
|
|
|
|
+ for plan in plans:
|
|
|
|
|
+ if plan['uuid'] not in shared:
|
|
|
|
|
+ print('sharing', plan['uuid'], plan['name'])
|
|
|
|
|
+ client.put('https://api.prunplanner.org/shared/baseplanner/' + plan['uuid']).raise_for_status()
|
|
|
|
|
+ # refresh shared UUIDs
|
|
|
|
|
+ shared: typing.Mapping[str, str] = {s['plan_uuid']: s['shared_uuid']
|
|
|
|
|
+ for s in client.get('https://api.prunplanner.org/shared/list').raise_for_status().json()}
|
|
|
|
|
+
|
|
|
|
|
+ buildings: typing.Mapping[str, BuildingData] = {b['Ticker']: b for b in cache.get('https://api.prunplanner.org/data/buildings')}
|
|
|
|
|
+
|
|
|
|
|
+ writer = csv.DictWriter(sys.stdout, fieldnames=['plan', 'share', 'PSL', 'TRU', 'MCG', 'BL', 'MGC', 'HSE', 'SEA', 'INS', 'TSH', 'BBH', 'BDE', 'BSE', 'BTA', 'LBH', 'LDE', 'LSE', 'LTA', 'RBH', 'RDE', 'RSE', 'RTA', 'ABH', 'ADE', 'ASE', 'ATA'])
|
|
|
|
|
+ writer.writeheader()
|
|
|
|
|
+ for plan in plans:
|
|
|
|
|
+ shared_uuid = shared[plan['uuid']]
|
|
|
|
|
+
|
|
|
|
|
+ planet: Planet = cache.get('https://api.prunplanner.org/data/planet/' + plan['baseplanner_data']['planet']['planetid'])
|
|
|
|
|
+ plan_mats = collections.defaultdict(int)
|
|
|
|
|
+ for mat in mats(buildings['CM'], planet):
|
|
|
|
|
+ plan_mats[mat['CommodityTicker']] += mat['Amount']
|
|
|
|
|
+ for plan_building in plan['baseplanner_data']['buildings']:
|
|
|
|
|
+ building_data = buildings[plan_building['name']]
|
|
|
|
|
+ for mat in mats(building_data, planet):
|
|
|
|
|
+ plan_mats[mat['CommodityTicker']] += mat['Amount'] * plan_building['amount']
|
|
|
|
|
+ for infra_building in plan['baseplanner_data']['infrastructure']:
|
|
|
|
|
+ building_data = buildings[infra_building['building']]
|
|
|
|
|
+ for mat in mats(building_data, planet):
|
|
|
|
|
+ plan_mats[mat['CommodityTicker']] += mat['Amount'] * infra_building['amount']
|
|
|
|
|
+ writer.writerow({'plan': plan['name'], 'share': 'https://prunplanner.org/shared/' + shared_uuid, **plan_mats})
|
|
|
|
|
+
|
|
|
|
|
+def mats(building: BuildingData, planet: Planet) -> typing.Iterator[BuildingMat]:
|
|
|
|
|
+ for mat in building['BuildingCosts']:
|
|
|
|
|
+ yield mat
|
|
|
|
|
+
|
|
|
|
|
+ if planet['Surface']: # rocky
|
|
|
|
|
+ yield {'CommodityTicker': 'MCG', 'Amount': building['AreaCost'] * 4}
|
|
|
|
|
+ else: # gaseous
|
|
|
|
|
+ yield {'CommodityTicker': 'AEF', 'Amount': math.ceil(building['AreaCost'] / 3)}
|
|
|
|
|
+
|
|
|
|
|
+ if planet['Gravity'] > 2.5:
|
|
|
|
|
+ yield {'CommodityTicker': 'BL', 'Amount': 1}
|
|
|
|
|
+ elif planet['Gravity'] < 0.25:
|
|
|
|
|
+ yield {'CommodityTicker': 'MGC', 'Amount': 1}
|
|
|
|
|
+
|
|
|
|
|
+ if planet['Pressure'] > 2:
|
|
|
|
|
+ yield {'CommodityTicker': 'HSE', 'Amount': 1}
|
|
|
|
|
+ elif planet['Pressure'] < 0.25:
|
|
|
|
|
+ yield {'CommodityTicker': 'SEA', 'Amount': building['AreaCost']}
|
|
|
|
|
+
|
|
|
|
|
+ if planet['Temperature'] < -25:
|
|
|
|
|
+ yield {'CommodityTicker': 'INS', 'Amount': building['AreaCost'] * 10}
|
|
|
|
|
+ elif planet['Temperature'] > 75:
|
|
|
|
|
+ yield {'CommodityTicker': 'TSH', 'Amount': 1}
|
|
|
|
|
+
|
|
|
|
|
+class Plan(typing.TypedDict):
|
|
|
|
|
+ uuid: str
|
|
|
|
|
+ name: str
|
|
|
|
|
+ baseplanner_data: BaseplannerData
|
|
|
|
|
+
|
|
|
|
|
+class BaseplannerData(typing.TypedDict):
|
|
|
|
|
+ planet: dict
|
|
|
|
|
+ infrastructure: typing.Sequence[InfrastructureBuilding]
|
|
|
|
|
+ buildings: typing.Sequence[PlanBuilding]
|
|
|
|
|
+
|
|
|
|
|
+class InfrastructureBuilding(typing.TypedDict):
|
|
|
|
|
+ building: str
|
|
|
|
|
+ amount: int
|
|
|
|
|
+
|
|
|
|
|
+class PlanBuilding(typing.TypedDict):
|
|
|
|
|
+ name: str
|
|
|
|
|
+ amount: int
|
|
|
|
|
+
|
|
|
|
|
+class Planet(typing.TypedDict):
|
|
|
|
|
+ Surface: bool
|
|
|
|
|
+ Pressure: float
|
|
|
|
|
+ Temperature: float
|
|
|
|
|
+ Gravity: float
|
|
|
|
|
+
|
|
|
|
|
+class BuildingData(typing.TypedDict):
|
|
|
|
|
+ Ticker: str
|
|
|
|
|
+ AreaCost: int
|
|
|
|
|
+ BuildingCosts: list[BuildingMat]
|
|
|
|
|
+
|
|
|
|
|
+class BuildingMat(typing.TypedDict):
|
|
|
|
|
+ CommodityTicker: str
|
|
|
|
|
+ Amount: int
|
|
|
|
|
+
|
|
|
|
|
+if __name__ == '__main__':
|
|
|
|
|
+ main()
|