integration.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. from __future__ import annotations
  2. import collections
  3. import re
  4. import sys
  5. import typing
  6. import cache
  7. def main() -> None:
  8. mat = sys.argv[1]
  9. recipes: list[Recipe] = cache.get('https://api.prunplanner.org/data/recipes')
  10. companies = pmmg_monthly_report()
  11. print(mat, '→')
  12. wrought = (recipe for recipe in recipes if mat in (i['Ticker'] for i in recipe['Inputs']) and len(recipe['Outputs']) == 1)
  13. output_mats = {}
  14. for recipe in sorted(wrought, key=lambda r: r['Outputs'][0]['Ticker']):
  15. (output,) = recipe['Outputs']
  16. (input,) = (i for i in recipe['Inputs'] if i['Ticker'] == mat)
  17. ratio = input['Amount'] / output['Amount']
  18. output_mats[output['Ticker']] = ratio
  19. print(f'\t{output["Ticker"]:3}:', ratio)
  20. companies_produced = companies_consumed = companies_consumed_80 = 0
  21. into = dict.fromkeys(output_mats.keys(), 0)
  22. for company in companies.values():
  23. if (co_production := company.get(mat)) is None:
  24. continue
  25. companies_produced += 1
  26. consumed = 0
  27. for output_mat, per_run_consumption in output_mats.items():
  28. if co_consumption := company.get(output_mat):
  29. total_consumption = co_consumption['amount'] * per_run_consumption
  30. consumed += total_consumption
  31. into[output_mat] += total_consumption
  32. if consumed > 0:
  33. companies_consumed += 1
  34. if consumed > 0.8 * co_production['amount']:
  35. companies_consumed_80 += 1
  36. print(f'{companies_produced} companies producing')
  37. print(f'{companies_consumed} companies consuming their own production')
  38. print(f'{companies_consumed_80} companies consuming 80%+ of their own production')
  39. recipes_per_output = collections.defaultdict(int)
  40. for recipe in recipes:
  41. for output in recipe['Outputs']:
  42. if output['Ticker'] in into:
  43. recipes_per_output[output['Ticker']] += 1
  44. for output_mat, total in sorted(into.items(), key=lambda kv: kv[1], reverse=True):
  45. alt = ''
  46. if (recipe_count := recipes_per_output[output_mat]) != 1:
  47. alt = f' ({recipe_count} recipes)'
  48. print(f'{output_mat:3}: {total:8,.0f}{alt}')
  49. def pmmg_monthly_report() -> dict[str, dict[str, CompanyOutput]]:
  50. report_constants = cache.get(
  51. 'https://raw.githubusercontent.com/PMMG-Products/pmmg-products.github.io/main/reports/src/staticData/constants.ts', json=False)
  52. # export const months = ["mar25", "apr25", ..., "dec25", "jan26"];
  53. match = re.search(r'export const months = \[(.*?)\];', report_constants)
  54. assert match
  55. months_str = match.group(1)
  56. months = [m.strip().strip('"') for m in months_str.split(',')]
  57. last_month = months[-1]
  58. print('getting report for', last_month)
  59. return cache.get(f'https://pmmg-products.github.io/reports/data/company-data-{last_month}.json')['individual']
  60. class CompanyOutput(typing.TypedDict):
  61. amount: int
  62. class Recipe(typing.TypedDict):
  63. RecipeName: str
  64. BuildingTicker: str
  65. Inputs: list[RecipeMat]
  66. Outputs: list[RecipeMat]
  67. TimeMs: int
  68. class RecipeMat(typing.TypedDict):
  69. Ticker: str
  70. Amount: int
  71. if __name__ == '__main__':
  72. main()