/game_stats/controller.py
Python | 197 lines | 143 code | 41 blank | 13 comment | 16 complexity | 31de7568621a57ffdf8fa4613049a283 MD5 | raw file
- import logging
- import pandas as pd
- from game_stats.config import config
- from game_stats.store import StoreFactory
- # Version for the data store. Must be increased if there is a non-backward compatible change of
- # how the data is persisted. Can be any string
- STORE_VERSION = '1'
- LOGGER = logging.getLogger(__name__)
- from game_stats.statistics.ultimate_score import UltimateScore
- from game_stats.statistics.game_result_stats import GameResultStats
- from game_stats.statistics.game_stats import GameStats
- from game_stats.statistics.player_stats import PlayerStats
- from game_stats.constants import *
- class Controller(object):
- def __init__(self):
- self.ultimate_score = UltimateScore()
- self.game_result_stats = GameResultStats()
- self.game_stats = GameStats()
- self.player_stats = PlayerStats()
- self.store = StoreFactory.get_store(config['store']['provider'])
- def save_game_result(self, time, league_id, game_id, result_id, player_scores):
- """
- :param time: datetime
- :param league_id: string
- :param game_id: [string|int]
- :param game_weight: float
- :param result_id: string
- :param player_scores: [(string, float)]
- """
- # load the game weight
- try:
- # TODO: Just check for key and throw custom error of not present
- self.get_game_weights()[game_id]
- except KeyError as err:
- LOGGER.error('No weight found for game id %s', game_id)
- raise err
- # update the ultimate scores
- weights = self.get_game_weights()
- metadata = self.get_metadata(league_id)
- panel = self.get_scores_panel(league_id)
- timeseries = self.get_timeseries(league_id)
- panel, timeseries, metadata = self.ultimate_score.update_ultimate_score_timeseries(
- panel,
- timeseries,
- metadata,
- weights,
- time,
- game_id,
- result_id,
- player_scores
- )
- self.save_scores_panel(league_id, panel)
- self.save_time_series(league_id, timeseries)
- self.save_metadata(league_id, metadata)
- return panel, timeseries
- def get_game_result(self, league_id, result_id):
- panel = self.get_scores_panel(league_id)
- weights = self.get_game_weights('test-game')
- self.ultimate_score.compute_single_game_result(panel, weights, result_id)
- def get_game_weights(self, game_id=None):
- filename = 'weights.hd5'
- if self.store.exists(filename):
- weights = self.store.load(filename)
- return weights[game_id] if game_id else weights
- return None if game_id else pd.Series()
- def set_game_weight(self, game_id, weight):
- filename = self._get_weights_filename()
- if not self.store.exists(filename):
- weights = pd.Series()
- else:
- weights = self.store.load(filename)
- weights[game_id] = weight
- self.store.save(filename, weights)
- return weights
- def save_scores_panel(self, league_id, panel):
- self.store.save(self._get_panel_filename(league_id), panel)
- def save_time_series(self, league_id, timeseries):
- self.store.save(self._get_timeseries_filename(league_id), timeseries)
- def _get_panel_filename(self, league_id):
- return 'v{}__{}-score-panel.hd5'.format(STORE_VERSION, league_id)
- def _get_timeseries_filename(self, league_id):
- return 'v{}__{}-time-series.hd5'.format(STORE_VERSION, league_id)
- def _get_metadata_filename(self, league_id):
- return 'v{}__{}-meta-data.hd5'.format(STORE_VERSION, league_id)
- def save_metadata(self, league_id, metadata):
- self.store.save(self._get_metadata_filename(league_id), metadata)
- return metadata
- def get_metadata(self, league_id, result_id=None, key=None):
- filename = self._get_metadata_filename(league_id)
- if not self.store.exists(filename):
- return pd.DataFrame()
- metadata = self.store.load(filename)
- if result_id and key:
- return metadata.loc[result_id, key]
- elif result_id:
- return metadata.loc[result_id]
- return metadata
- def _get_weights_filename(self):
- return 'weights.hd5'
- def get_timeseries(self, league_id, reload=False) -> pd.DataFrame:
- if reload:
- return self.ultimate_score.recompute_ultimate_score_time_series(
- self.get_scores_panel(league_id),
- self.get_game_weights()
- )
- filename = self._get_timeseries_filename(league_id)
- if not self.store.exists(filename):
- return pd.DataFrame()
- return self.store.load(filename)
- def get_scores_panel(self, league_id):
- filename = self._get_panel_filename(league_id)
- if not self.store.exists(filename):
- return pd.Series(
- [],
- index=pd.MultiIndex(
- levels=[[], [], []], codes=[[], [], []], names=[GAME_LEVEL, RESULT_LEVEL, PLAYER_LEVEL]
- )
- )
- return self.store.load(filename)
- def get_leagues(self):
- return [n.replace('-score-panel.hd5', '').replace('v{}__'.format(STORE_VERSION), '')
- for n in self.store.list() if '-score-panel.hd5' in n]
- def delete_gameresult(self, league_id, result_id):
- panel = self.get_scores_panel(league_id)
- weights = self.get_game_weights()
- # delete result from scores panel
- panel = self.ultimate_score.delete_gameresult(panel, result_id)
- # recompute ultimate score
- if panel.size == 0:
- # edge case: the only game result was deleted
- timeseries = pd.DataFrame()
- else:
- timeseries = self.ultimate_score.recompute_ultimate_score_time_series(panel, weights)
- # remove from metadata
- metadata = self.get_metadata(league_id).drop(result_id)
- self.save_metadata(league_id, metadata)
- self.save_scores_panel(league_id, panel)
- self.save_time_series(league_id, timeseries)
- def get_game_result_stats(self, league_id, result_id):
- panel = self.get_scores_panel(league_id)
- weights = self.get_game_weights()
- return self.game_result_stats.get_game_result_stats(panel, weights, result_id)
- def get_game_stats(self, league_id):
- panel = self.get_scores_panel(league_id)
- return self.game_stats.game_stats(panel)
- def get_player_stats(self, league_id):
- panel = self.get_scores_panel(league_id)
- return self.player_stats.player_stats(panel)