share.py 3.8 KB

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