diff --git a/model/__init__.py b/model/__init__.py index e3aa162..6e63bce 100644 --- a/model/__init__.py +++ b/model/__init__.py @@ -11,3 +11,5 @@ model: AbstractModel = PostgresModel() if config.log_level == 'DEBUG': model.get_diff_action_id = utils.measure(model.get_diff_action_id, 'model.get_diff_action_id') model.get_activity_changes = utils.measure(model.get_activity_changes, 'model.get_activity_changes') + model.get_leaderboard_sum_history = utils.measure(model.get_leaderboard_sum_history, + 'model.get_leaderboard_sum_history') diff --git a/model/abstract_model.py b/model/abstract_model.py index 066e8e9..fc15254 100644 --- a/model/abstract_model.py +++ b/model/abstract_model.py @@ -23,3 +23,7 @@ class AbstractModel(abc.ABC): @abc.abstractmethod def get_diff_action_id(self, action_id: int) -> list: raise NotImplemented + + @abc.abstractmethod + def get_leaderboard_sum_history(self, platform: str, leaderboard_type: str) -> list[dict]: + raise NotImplemented diff --git a/model/postgres_model.py b/model/postgres_model.py index c389610..cee9eda 100644 --- a/model/postgres_model.py +++ b/model/postgres_model.py @@ -143,3 +143,26 @@ class PostgresModel(AbstractModel): cache.set(cache_key, json.dumps(result)) return result + + @errors_catcher + def get_leaderboard_sum_history(self, platform: str, leaderboard_type: str) -> list[dict]: + cache_key = f'sum_history_{platform}_{leaderboard_type}' + cached_result: typing.Union[str, None] = cache.get(cache_key) + + if cached_result is not None: + logger.debug(f'Cached result for {cache_key}') + return json.loads(cached_result) + + with self.db.cursor(cursor_factory=psycopg2.extras.RealDictCursor) as cursor: + cursor.execute( + postgres_sql_requests.select_leaderboard_sum_history, + { + 'LB_type': utils.LeaderboardTypes(leaderboard_type.lower()).value, + 'platform': utils.Platform(platform.upper()).value} + ) + result: list = cursor.fetchall() + + if not cache.disabled: + cache.set(cache_key, json.dumps(result)) + + return result diff --git a/model/postgres_sql_requests.py b/model/postgres_sql_requests.py index a7040c8..c129bca 100644 --- a/model/postgres_sql_requests.py +++ b/model/postgres_sql_requests.py @@ -84,4 +84,14 @@ full join limit 1)) old_stats on new_stats.squadron_id = old_stats.squadron_id where coalesce(new_stats.score, 0) - coalesce(old_stats.score, 0) <> 0 -order by coalesce(new_stats.score, 0) - coalesce(old_stats.score, 0) desc;""" \ No newline at end of file +order by coalesce(new_stats.score, 0) - coalesce(old_stats.score, 0) desc;""" + +select_leaderboard_sum_history = """select + sum(score)::bigint as "Score Sum", + to_char(max(timestamp), 'YYYY-MM-DD HH24:MI:SS') as "Timestamp UTC" +from squads_stats_states +where leaderboard_type = %(LB_type)s and platform = %(platform)s +group by action_id +order by "Timestamp UTC" desc +limit 1000; +""" \ No newline at end of file diff --git a/templates/graph_template.html b/templates/graph_template.html new file mode 100644 index 0000000..1b190f6 --- /dev/null +++ b/templates/graph_template.html @@ -0,0 +1,58 @@ + + + + + + + + +
+ +
+ {{ @footer.html }} + + \ No newline at end of file diff --git a/web.py b/web.py index dcda109..f6db016 100644 --- a/web.py +++ b/web.py @@ -95,6 +95,33 @@ class ActivityDiffHtml: ) +class SumLeaderboardHistory: + def on_get(self, req: falcon.request.Request, resp: falcon.response.Response, leaderboard: str, platform: str)\ + -> None: + resp.content_type = falcon.MEDIA_JSON + + try: + resp.text = json.dumps(model.get_leaderboard_sum_history(platform, leaderboard)) + + except Exception as e: + logger.warning( + f'Exception occurred during executing history request, LB: {leaderboard!r}; platform: {platform!r}', + exc_info=e + ) + raise falcon.HTTPInternalServerError(description=str(e)) + + +class SumLeaderboardHistoryHtml: + def on_get(self, req: falcon.request.Request, resp: falcon.response.Response, leaderboard: str, platform: str)\ + -> None: + resp.content_type = falcon.MEDIA_HTML + resp.text = render( + 'graph_template.html', + { + 'dataset_title': f'{leaderboard} {platform} points sum' + }) + + class MainPage: def on_get(self, req: falcon.request.Request, resp: falcon.response.Response) -> None: raise falcon.HTTPMovedPermanently('/index.html') @@ -113,9 +140,12 @@ class Cache: app = falcon.App() app.add_route('/api/leaderboard/{leaderboard}/platform/{platform}', Activity()) app.add_route('/api/diff/{action_id}', ActivityDiff()) +app.add_route('/leaderboard-history/leaderboard/{leaderboard}/platform/{platform}', SumLeaderboardHistoryHtml()) app.add_route('/leaderboard/{leaderboard}/platform/{platform}', ActivityHtml()) app.add_route('/diff/{action_id}', ActivityDiffHtml()) +app.add_route('/api/leaderboard-history/leaderboard/{leaderboard}/platform/{platform}', SumLeaderboardHistory()) + app.add_route('/api/cache/{action}', Cache())