share.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. '''share all plans in an account and generate a CSV of the construction materials'''
  2. from __future__ import annotations
  3. import collections
  4. import csv
  5. import math
  6. import sys
  7. import typing
  8. import httpx
  9. import cache
  10. def main():
  11. jwt,= sys.argv[1:]
  12. with httpx.Client(headers={'Authorization': 'Bearer ' + jwt}) as client:
  13. plans: typing.Sequence[Plan] = client.get('https://api.prunplanner.org/baseplanner/').raise_for_status().json()
  14. shared: typing.Mapping[str, str] = {s['plan_uuid']: s['shared_uuid']
  15. for s in client.get('https://api.prunplanner.org/shared/list').raise_for_status().json()}
  16. for plan in plans:
  17. if plan['uuid'] not in shared:
  18. print('sharing', plan['uuid'], plan['name'])
  19. client.put('https://api.prunplanner.org/shared/baseplanner/' + plan['uuid']).raise_for_status()
  20. # refresh shared UUIDs
  21. shared: typing.Mapping[str, str] = {s['plan_uuid']: s['shared_uuid']
  22. for s in client.get('https://api.prunplanner.org/shared/list').raise_for_status().json()}
  23. buildings: typing.Mapping[str, BuildingData] = {b['Ticker']: b for b in cache.get('https://api.prunplanner.org/data/buildings')}
  24. 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'])
  25. writer.writeheader()
  26. for plan in plans:
  27. shared_uuid = shared[plan['uuid']]
  28. planet: Planet = cache.get('https://api.prunplanner.org/data/planet/' + plan['baseplanner_data']['planet']['planetid'])
  29. plan_mats = collections.defaultdict(int)
  30. for mat in mats(buildings['CM'], planet):
  31. plan_mats[mat['CommodityTicker']] += mat['Amount']
  32. for plan_building in plan['baseplanner_data']['buildings']:
  33. building_data = buildings[plan_building['name']]
  34. for mat in mats(building_data, planet):
  35. plan_mats[mat['CommodityTicker']] += mat['Amount'] * plan_building['amount']
  36. for infra_building in plan['baseplanner_data']['infrastructure']:
  37. building_data = buildings[infra_building['building']]
  38. for mat in mats(building_data, planet):
  39. plan_mats[mat['CommodityTicker']] += mat['Amount'] * infra_building['amount']
  40. writer.writerow({'plan': plan['name'], 'share': 'https://prunplanner.org/shared/' + shared_uuid, **plan_mats})
  41. def mats(building: BuildingData, planet: Planet) -> typing.Iterator[BuildingMat]:
  42. for mat in building['BuildingCosts']:
  43. yield mat
  44. if planet['Surface']: # rocky
  45. yield {'CommodityTicker': 'MCG', 'Amount': building['AreaCost'] * 4}
  46. else: # gaseous
  47. yield {'CommodityTicker': 'AEF', 'Amount': math.ceil(building['AreaCost'] / 3)}
  48. if planet['Gravity'] > 2.5:
  49. yield {'CommodityTicker': 'BL', 'Amount': 1}
  50. elif planet['Gravity'] < 0.25:
  51. yield {'CommodityTicker': 'MGC', 'Amount': 1}
  52. if planet['Pressure'] > 2:
  53. yield {'CommodityTicker': 'HSE', 'Amount': 1}
  54. elif planet['Pressure'] < 0.25:
  55. yield {'CommodityTicker': 'SEA', 'Amount': building['AreaCost']}
  56. if planet['Temperature'] < -25:
  57. yield {'CommodityTicker': 'INS', 'Amount': building['AreaCost'] * 10}
  58. elif planet['Temperature'] > 75:
  59. yield {'CommodityTicker': 'TSH', 'Amount': 1}
  60. class Plan(typing.TypedDict):
  61. uuid: str
  62. name: str
  63. baseplanner_data: BaseplannerData
  64. class BaseplannerData(typing.TypedDict):
  65. planet: dict
  66. infrastructure: typing.Sequence[InfrastructureBuilding]
  67. buildings: typing.Sequence[PlanBuilding]
  68. class InfrastructureBuilding(typing.TypedDict):
  69. building: str
  70. amount: int
  71. class PlanBuilding(typing.TypedDict):
  72. name: str
  73. amount: int
  74. class Planet(typing.TypedDict):
  75. Surface: bool
  76. Pressure: float
  77. Temperature: float
  78. Gravity: float
  79. class BuildingData(typing.TypedDict):
  80. Ticker: str
  81. AreaCost: int
  82. BuildingCosts: list[BuildingMat]
  83. class BuildingMat(typing.TypedDict):
  84. CommodityTicker: str
  85. Amount: int
  86. if __name__ == '__main__':
  87. main()