integration.py 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. from __future__ import annotations
  2. import collections
  3. import re
  4. import sys
  5. import typing
  6. import cache
  7. if typing.TYPE_CHECKING:
  8. import roi
  9. def main() -> None:
  10. mat = sys.argv[1]
  11. recipes: list[roi.Recipe] = cache.get('https://api.prunplanner.org/data/recipes/')
  12. companies = pmmg_monthly_report()['individual']
  13. print(mat, '→')
  14. wrought = (recipe for recipe in recipes
  15. if mat in (i['material_ticker'] for i in recipe['inputs']) and len(recipe['outputs']) == 1)
  16. output_mats = {}
  17. for recipe in sorted(wrought, key=lambda r: r['outputs'][0]['material_ticker']):
  18. if recipe['recipe_name'] in ['3xSIO 1xAL=>1xSI', '4xTS 1xO 1xAL=>1xSI', '6xAL 1xHE=>1xDRF']:
  19. continue
  20. (output,) = recipe['outputs']
  21. (input,) = (i for i in recipe['inputs'] if i['material_ticker'] == mat)
  22. ratio = input['material_amount'] / output['material_amount']
  23. output_mats[output['material_ticker']] = ratio
  24. print(f'\t{output["material_ticker"]:3}:', ratio)
  25. companies_produced = companies_consumed = companies_consumed_only = companies_consumed_own = companies_consumed_80_own = 0
  26. into = dict.fromkeys(output_mats.keys(), 0)
  27. for company in companies.values():
  28. if (co_production := company.get(mat)) is not None:
  29. companies_produced += 1
  30. consumed = 0
  31. for output_mat, per_run_consumption in output_mats.items():
  32. if co_production := company.get(output_mat):
  33. co_consumption = co_production['amount'] * per_run_consumption
  34. consumed += co_consumption
  35. into[output_mat] += co_consumption
  36. if consumed > 0:
  37. companies_consumed += 1
  38. if co_production is None:
  39. companies_consumed_only += 1
  40. else:
  41. companies_consumed_own += 1
  42. if consumed > 0.8 * co_production['amount']:
  43. companies_consumed_80_own += 1
  44. print(f'{companies_produced} companies producing')
  45. print(f'{companies_consumed} companies consuming')
  46. print(f'{companies_consumed_only} companies consuming without producing any')
  47. print(f'{companies_consumed_own} companies consuming their own production')
  48. print(f'{companies_consumed_80_own} companies consuming 80%+ of their own production')
  49. recipes_per_output = collections.defaultdict(int)
  50. for recipe in recipes:
  51. for output in recipe['outputs']:
  52. if output['material_ticker'] in into:
  53. recipes_per_output[output['material_ticker']] += 1
  54. total_consumed = 0
  55. for output_mat, consumed in sorted(into.items(), key=lambda kv: kv[1], reverse=True):
  56. alt = ''
  57. if (recipe_count := recipes_per_output[output_mat]) != 1:
  58. alt = f' ({recipe_count} recipes)'
  59. print(f'{output_mat:3}: {consumed:8,.0f}{alt}')
  60. total_consumed += consumed
  61. print('total consumed:', total_consumed)
  62. def pmmg_monthly_report() -> CompanyData:
  63. last_month = pmmg_month()
  64. print('getting report for', last_month)
  65. return cache.get(f'https://prun.raylu.net/stats/data/company-data-{last_month}.json', expiry=cache.ONE_DAY)
  66. def pmmg_month() -> str:
  67. report_constants = cache.get('https://git.raylu.net/raylu/prunstats/raw/main/src/staticData/constants.ts',
  68. json=False, expiry=cache.ONE_DAY)
  69. # export const months = ["mar25", "apr25", ..., "dec25", "jan26"];
  70. match = re.search(r'export const months = \[(.*?)\];', report_constants)
  71. assert match
  72. months_str = match.group(1)
  73. months = [m.strip().strip('"') for m in months_str.split(',')]
  74. return months[-1]
  75. class CompanyData(typing.TypedDict):
  76. totals: dict[str, CompanyTotal]
  77. individual: dict[str, dict[str, CompanyOutput]]
  78. class CompanyTotal(typing.TypedDict):
  79. volume: float
  80. class CompanyOutput(typing.TypedDict):
  81. amount: int
  82. if __name__ == '__main__':
  83. main()