PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/game_stats/controller.py

https://gitlab.com/shpeely/game-stats
Python | 197 lines | 143 code | 41 blank | 13 comment | 16 complexity | 31de7568621a57ffdf8fa4613049a283 MD5 | raw file
  1. import logging
  2. import pandas as pd
  3. from game_stats.config import config
  4. from game_stats.store import StoreFactory
  5. # Version for the data store. Must be increased if there is a non-backward compatible change of
  6. # how the data is persisted. Can be any string
  7. STORE_VERSION = '1'
  8. LOGGER = logging.getLogger(__name__)
  9. from game_stats.statistics.ultimate_score import UltimateScore
  10. from game_stats.statistics.game_result_stats import GameResultStats
  11. from game_stats.statistics.game_stats import GameStats
  12. from game_stats.statistics.player_stats import PlayerStats
  13. from game_stats.constants import *
  14. class Controller(object):
  15. def __init__(self):
  16. self.ultimate_score = UltimateScore()
  17. self.game_result_stats = GameResultStats()
  18. self.game_stats = GameStats()
  19. self.player_stats = PlayerStats()
  20. self.store = StoreFactory.get_store(config['store']['provider'])
  21. def save_game_result(self, time, league_id, game_id, result_id, player_scores):
  22. """
  23. :param time: datetime
  24. :param league_id: string
  25. :param game_id: [string|int]
  26. :param game_weight: float
  27. :param result_id: string
  28. :param player_scores: [(string, float)]
  29. """
  30. # load the game weight
  31. try:
  32. # TODO: Just check for key and throw custom error of not present
  33. self.get_game_weights()[game_id]
  34. except KeyError as err:
  35. LOGGER.error('No weight found for game id %s', game_id)
  36. raise err
  37. # update the ultimate scores
  38. weights = self.get_game_weights()
  39. metadata = self.get_metadata(league_id)
  40. panel = self.get_scores_panel(league_id)
  41. timeseries = self.get_timeseries(league_id)
  42. panel, timeseries, metadata = self.ultimate_score.update_ultimate_score_timeseries(
  43. panel,
  44. timeseries,
  45. metadata,
  46. weights,
  47. time,
  48. game_id,
  49. result_id,
  50. player_scores
  51. )
  52. self.save_scores_panel(league_id, panel)
  53. self.save_time_series(league_id, timeseries)
  54. self.save_metadata(league_id, metadata)
  55. return panel, timeseries
  56. def get_game_result(self, league_id, result_id):
  57. panel = self.get_scores_panel(league_id)
  58. weights = self.get_game_weights('test-game')
  59. self.ultimate_score.compute_single_game_result(panel, weights, result_id)
  60. def get_game_weights(self, game_id=None):
  61. filename = 'weights.hd5'
  62. if self.store.exists(filename):
  63. weights = self.store.load(filename)
  64. return weights[game_id] if game_id else weights
  65. return None if game_id else pd.Series()
  66. def set_game_weight(self, game_id, weight):
  67. filename = self._get_weights_filename()
  68. if not self.store.exists(filename):
  69. weights = pd.Series()
  70. else:
  71. weights = self.store.load(filename)
  72. weights[game_id] = weight
  73. self.store.save(filename, weights)
  74. return weights
  75. def save_scores_panel(self, league_id, panel):
  76. self.store.save(self._get_panel_filename(league_id), panel)
  77. def save_time_series(self, league_id, timeseries):
  78. self.store.save(self._get_timeseries_filename(league_id), timeseries)
  79. def _get_panel_filename(self, league_id):
  80. return 'v{}__{}-score-panel.hd5'.format(STORE_VERSION, league_id)
  81. def _get_timeseries_filename(self, league_id):
  82. return 'v{}__{}-time-series.hd5'.format(STORE_VERSION, league_id)
  83. def _get_metadata_filename(self, league_id):
  84. return 'v{}__{}-meta-data.hd5'.format(STORE_VERSION, league_id)
  85. def save_metadata(self, league_id, metadata):
  86. self.store.save(self._get_metadata_filename(league_id), metadata)
  87. return metadata
  88. def get_metadata(self, league_id, result_id=None, key=None):
  89. filename = self._get_metadata_filename(league_id)
  90. if not self.store.exists(filename):
  91. return pd.DataFrame()
  92. metadata = self.store.load(filename)
  93. if result_id and key:
  94. return metadata.loc[result_id, key]
  95. elif result_id:
  96. return metadata.loc[result_id]
  97. return metadata
  98. def _get_weights_filename(self):
  99. return 'weights.hd5'
  100. def get_timeseries(self, league_id, reload=False) -> pd.DataFrame:
  101. if reload:
  102. return self.ultimate_score.recompute_ultimate_score_time_series(
  103. self.get_scores_panel(league_id),
  104. self.get_game_weights()
  105. )
  106. filename = self._get_timeseries_filename(league_id)
  107. if not self.store.exists(filename):
  108. return pd.DataFrame()
  109. return self.store.load(filename)
  110. def get_scores_panel(self, league_id):
  111. filename = self._get_panel_filename(league_id)
  112. if not self.store.exists(filename):
  113. return pd.Series(
  114. [],
  115. index=pd.MultiIndex(
  116. levels=[[], [], []], codes=[[], [], []], names=[GAME_LEVEL, RESULT_LEVEL, PLAYER_LEVEL]
  117. )
  118. )
  119. return self.store.load(filename)
  120. def get_leagues(self):
  121. return [n.replace('-score-panel.hd5', '').replace('v{}__'.format(STORE_VERSION), '')
  122. for n in self.store.list() if '-score-panel.hd5' in n]
  123. def delete_gameresult(self, league_id, result_id):
  124. panel = self.get_scores_panel(league_id)
  125. weights = self.get_game_weights()
  126. # delete result from scores panel
  127. panel = self.ultimate_score.delete_gameresult(panel, result_id)
  128. # recompute ultimate score
  129. if panel.size == 0:
  130. # edge case: the only game result was deleted
  131. timeseries = pd.DataFrame()
  132. else:
  133. timeseries = self.ultimate_score.recompute_ultimate_score_time_series(panel, weights)
  134. # remove from metadata
  135. metadata = self.get_metadata(league_id).drop(result_id)
  136. self.save_metadata(league_id, metadata)
  137. self.save_scores_panel(league_id, panel)
  138. self.save_time_series(league_id, timeseries)
  139. def get_game_result_stats(self, league_id, result_id):
  140. panel = self.get_scores_panel(league_id)
  141. weights = self.get_game_weights()
  142. return self.game_result_stats.get_game_result_stats(panel, weights, result_id)
  143. def get_game_stats(self, league_id):
  144. panel = self.get_scores_panel(league_id)
  145. return self.game_stats.game_stats(panel)
  146. def get_player_stats(self, league_id):
  147. panel = self.get_scores_panel(league_id)
  148. return self.player_stats.player_stats(panel)