mat_competitors.py 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. from __future__ import annotations
  2. import collections
  3. import dataclasses
  4. import json
  5. import sys
  6. import typing
  7. import cache
  8. import company
  9. import integration
  10. import planet_bases
  11. def main() -> None:
  12. cx, ticker = sys.argv[1:]
  13. (expertise,) = frozenset(iter_expertise(ticker))
  14. planets: dict[str, str] = {}
  15. for planet, cogc in company.iter_planet_cogc():
  16. if cogc == expertise:
  17. planets[planet['PlanetId']] = planet['PlanetName']
  18. print(len(planets), 'with', expertise, 'CoGC')
  19. with open('www/closest.json') as f:
  20. close_planet_ids = {planet_id for planet_id, closest_cx in json.load(f).items() if closest_cx == cx}
  21. if cx == 'CI1':
  22. close_planet_ids.add('7ef6caa148aa38c0e3966fdf47ee1a6b') # griffonstone
  23. elif cx == 'AI1':
  24. close_planet_ids.remove('7ef6caa148aa38c0e3966fdf47ee1a6b')
  25. coid_code_name: dict[str, tuple[str, str]] = {}
  26. coid_bases = collections.defaultdict(list)
  27. for planet_id, planet_name in planets.items():
  28. if planet_id in close_planet_ids:
  29. print(f'\t\033[32m{planet_name}\033[0m')
  30. else:
  31. print(f'\t\033[31m{planet_name}\033[0m')
  32. bases = planet_bases.get_bases(planet_name)
  33. for base in bases:
  34. if (code := base['OwnerCode']) is None:
  35. continue
  36. coid_code_name[base['OwnerId']] = code, base['OwnerName']
  37. coid_bases[base['OwnerId']].append(planet_id)
  38. coid_users: dict[str, str] = {company_id: d['Username']
  39. for company_id, d in cache.get('https://pmmg-products.github.io/reports/data/knownCompanies.json', expiry=cache.ONE_DAY).items()}
  40. competitors: list[Competitor] = []
  41. for company_id, co_production in integration.pmmg_monthly_report().items():
  42. if (mat_production := co_production.get(ticker)) is None:
  43. continue
  44. if planet_ids := coid_bases.get(company_id):
  45. code, co_name = coid_code_name[company_id]
  46. username = coid_users.get(company_id, '[unknown]')
  47. competitors.append(Competitor(code, co_name, username, mat_production['amount'], planet_ids))
  48. competitors.sort(reverse=True)
  49. total = 0.0
  50. for c in competitors:
  51. close_planet_num = 0
  52. player_planets = []
  53. for planet_id in c.planet_ids:
  54. if planet_id in close_planet_ids:
  55. player_planets.append(f'\033[32m{planets[planet_id]}\033[0m')
  56. close_planet_num += 1
  57. else:
  58. player_planets.append(f'\033[31m{planets[planet_id]}\033[0m')
  59. if close_planet_num > 0:
  60. local_production = c.production * close_planet_num / len(c.planet_ids)
  61. total += local_production
  62. print(f'{c.code:4} {c.company_name:30} {c.username:20} {local_production:9,.1f} ', ' '.join(player_planets))
  63. print(f'total: {total:,.1f}')
  64. def iter_expertise(ticker: str) -> typing.Iterator[str]:
  65. buildings: typing.Sequence[company.Building] = cache.get('https://rest.fnar.net/building/allbuildings', expiry=cache.ONE_DAY)
  66. for building in buildings:
  67. for recipe in building['Recipes']:
  68. for output in recipe['Outputs']:
  69. if output['CommodityTicker'] == ticker:
  70. print(ticker, 'requires', building['Expertise'])
  71. yield building['Expertise']
  72. @dataclasses.dataclass(eq=False, frozen=True, slots=True)
  73. class Competitor:
  74. code: str
  75. company_name: str
  76. username: str
  77. production: float
  78. planet_ids: typing.Sequence[str]
  79. def __lt__(self, other: Competitor) -> bool:
  80. return self.production < other.production
  81. if __name__ == '__main__':
  82. main()