From 2afaa393381cd9e619dd1302aca67646af61dbcd Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Sat, 29 Aug 2020 22:47:06 -0700 Subject: [PATCH 01/31] Improve ML model handling --- .../spa_api/service_layers/ml/ml.py | 46 +++++++++++-------- .../service_layers/replay/predicted_ranks.py | 22 +++++++-- 2 files changed, 46 insertions(+), 22 deletions(-) diff --git a/backend/blueprints/spa_api/service_layers/ml/ml.py b/backend/blueprints/spa_api/service_layers/ml/ml.py index 554d47271..e1e784b37 100644 --- a/backend/blueprints/spa_api/service_layers/ml/ml.py +++ b/backend/blueprints/spa_api/service_layers/ml/ml.py @@ -1,12 +1,12 @@ import glob import os +import pandas as pd import torch import torch.nn as nn -import pandas as pd +from sqlalchemy import inspect from backend.database.objects import PlayerGame -from sqlalchemy import inspect def object_as_dict(obj): @@ -40,18 +40,25 @@ class RankPredictor: # MODEL_DIR = os.path.abspath(os.path.join('..', '..', '..', '..', '..', 'data', 'models')) MODEL_DIR = os.path.abspath(os.path.join('data', 'models')) models = {} - maxs = None - mins = None + maxs = {} + mins = {} def __init__(self): - # Load models - for model in sorted(glob.glob(os.path.join(self.MODEL_DIR, '*.mdl'))): - state = torch.load(model, map_location='cpu') - m = RankPredictorEnsemble() - m.load_state_dict(state) - self.models[os.path.basename(model).split('.')[0]] = m - self.maxs = pd.read_csv(os.path.join(self.MODEL_DIR, 'maxs.csv'), index_col=0, squeeze=True, header=None) - self.mins = pd.read_csv(os.path.join(self.MODEL_DIR, 'mins.csv'), index_col=0, squeeze=True, header=None) + possible_playlists = [playlist for playlist in os.listdir(self.MODEL_DIR) if + os.path.isdir(os.path.join(self.MODEL_DIR, playlist))] + for playlist_dir in possible_playlists: + self.models[playlist_dir] = {} + playlist_loc = os.path.join(self.MODEL_DIR, playlist_dir) + # Load models + for model in sorted(glob.glob(os.path.join(playlist_loc, '*.mdl'))): + state = torch.load(model, map_location='cpu') + m = RankPredictorEnsemble() + m.load_state_dict(state) + self.models[playlist_dir][os.path.basename(model).split('.')[0]] = m + self.maxs[playlist_dir] = pd.read_csv(os.path.join(playlist_loc, 'maxs.csv'), index_col=0, squeeze=True, + header=None) + self.mins[playlist_dir] = pd.read_csv(os.path.join(playlist_loc, 'mins.csv'), index_col=0, squeeze=True, + header=None) @staticmethod def process_input_data(input_, maxs, mins): @@ -76,17 +83,21 @@ def process_input_data(input_, maxs, mins): output = nonzero['rank'] return input, output, maxs, mins - def convert_sql_object_to_numpy(self, obj: PlayerGame): + def convert_sql_object_to_numpy(self, obj: PlayerGame, playlist: int): + playlist = str(playlist) obj = object_as_dict(obj) a = pd.Series(obj) - input, _, __, ___ = self.process_input_data(a, self.maxs, self.mins) + input, _, __, ___ = self.process_input_data(a, self.maxs[playlist], self.mins[playlist]) obj = input.values return obj - def predict_rank(self, x: PlayerGame) -> int: - x = self.convert_sql_object_to_numpy(x) + def predict_rank(self, x: PlayerGame, playlist: int) -> int: + x = self.convert_sql_object_to_numpy(x, playlist) result = pd.DataFrame(index=list(range(len(x)))) - for rank, m in self.models.items(): + if str(playlist) not in self.models: + return None + models = self.models[str(playlist)] + for rank, m in models.items(): result = result.merge( pd.Series(100 * m(x.astype(float)).detach().cpu().numpy(), name=str(rank)).to_frame(), left_index=True, right_index=True) @@ -97,7 +108,6 @@ def predict_rank(self, x: PlayerGame) -> int: model_holder = RankPredictor() - if __name__ == '__main__': from backend.database.startup import lazy_startup diff --git a/backend/blueprints/spa_api/service_layers/replay/predicted_ranks.py b/backend/blueprints/spa_api/service_layers/replay/predicted_ranks.py index fbf0962ec..227270fb1 100644 --- a/backend/blueprints/spa_api/service_layers/replay/predicted_ranks.py +++ b/backend/blueprints/spa_api/service_layers/replay/predicted_ranks.py @@ -9,7 +9,8 @@ from backend.blueprints.spa_api.service_layers.ml.ml import model_holder except ModuleNotFoundError: model_holder = None - print("Not using ML because required packages are not installed. Run `pip install -r requirements-ml.txt` to use ML.") + print( + "Not using ML because required packages are not installed. Run `pip install -r requirements-ml.txt` to use ML.") class PredictedRank: @@ -33,13 +34,26 @@ def create_from_id(id_: str, session=None) -> List['PredictedRank']: accepted_playlists = [ 13, # standard 3, # unranked standard - 6, # custom + 6, # custom, + 11, # doubles + 2, # unranked doubles ] if game.playlist not in accepted_playlists: raise UnsupportedPlaylist playergames = session.query(PlayerGame).filter(PlayerGame.game == id_).all() - + adjusted_playlist_map = { + 2: 11, + 11: 11, + 3: 13, + 6: 13, + 13: 13 + } + playlist = adjusted_playlist_map[game.playlist] + if game.playlist == 6 and len(game.players) == 4: + playlist = 11 + elif game.playlist == 6 and len(game.players) == 2: + playlist = 10 if is_local_dev(): import random ranks = [ @@ -48,7 +62,7 @@ def create_from_id(id_: str, session=None) -> List['PredictedRank']: ] else: ranks = [ - PredictedRank(pg.player, model_holder.predict_rank(pg)) + PredictedRank(pg.player, model_holder.predict_rank(pg, playlist=playlist)) for pg in playergames ] return ranks From e7e5dfdd847cbe653253b73b3c213a344c5a10aa Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Sat, 29 Aug 2020 23:35:16 -0700 Subject: [PATCH 02/31] Improve ML model handling --- backend/blueprints/spa_api/service_layers/ml/ml.py | 3 ++- .../spa_api/service_layers/replay/predicted_ranks.py | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/backend/blueprints/spa_api/service_layers/ml/ml.py b/backend/blueprints/spa_api/service_layers/ml/ml.py index e1e784b37..845e946a7 100644 --- a/backend/blueprints/spa_api/service_layers/ml/ml.py +++ b/backend/blueprints/spa_api/service_layers/ml/ml.py @@ -80,6 +80,7 @@ def process_input_data(input_, maxs, mins): # mins = input.min() # maxs = input.max() input = (input - mins) / (maxs - mins) + input = input.fillna(0) output = nonzero['rank'] return input, output, maxs, mins @@ -101,7 +102,7 @@ def predict_rank(self, x: PlayerGame, playlist: int) -> int: result = result.merge( pd.Series(100 * m(x.astype(float)).detach().cpu().numpy(), name=str(rank)).to_frame(), left_index=True, right_index=True) - # print(result) + print(result) result = (result > 50).apply(lambda x: int(x.idxmin()), axis=1).values return int(result[0]) diff --git a/backend/blueprints/spa_api/service_layers/replay/predicted_ranks.py b/backend/blueprints/spa_api/service_layers/replay/predicted_ranks.py index 227270fb1..f544a7bd7 100644 --- a/backend/blueprints/spa_api/service_layers/replay/predicted_ranks.py +++ b/backend/blueprints/spa_api/service_layers/replay/predicted_ranks.py @@ -37,6 +37,8 @@ def create_from_id(id_: str, session=None) -> List['PredictedRank']: 6, # custom, 11, # doubles 2, # unranked doubles + 10, + 1 ] if game.playlist not in accepted_playlists: raise UnsupportedPlaylist @@ -47,7 +49,9 @@ def create_from_id(id_: str, session=None) -> List['PredictedRank']: 11: 11, 3: 13, 6: 13, - 13: 13 + 13: 13, + 10: 10, + 1: 10 } playlist = adjusted_playlist_map[game.playlist] if game.playlist == 6 and len(game.players) == 4: From afc04edb19e48d99d9d3d7461da2c799d20f4cdb Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Sat, 29 Aug 2020 23:53:52 -0700 Subject: [PATCH 03/31] Fix for private 2s --- backend/blueprints/spa_api/service_layers/ml/ml.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/backend/blueprints/spa_api/service_layers/ml/ml.py b/backend/blueprints/spa_api/service_layers/ml/ml.py index 845e946a7..07caae416 100644 --- a/backend/blueprints/spa_api/service_layers/ml/ml.py +++ b/backend/blueprints/spa_api/service_layers/ml/ml.py @@ -1,6 +1,7 @@ import glob import os +import numpy as np import pandas as pd import torch import torch.nn as nn @@ -80,7 +81,8 @@ def process_input_data(input_, maxs, mins): # mins = input.min() # maxs = input.max() input = (input - mins) / (maxs - mins) - input = input.fillna(0) + input = input.fillna(0.0) + input = input.replace([np.inf, -np.inf], 0.0) output = nonzero['rank'] return input, output, maxs, mins @@ -93,6 +95,7 @@ def convert_sql_object_to_numpy(self, obj: PlayerGame, playlist: int): return obj def predict_rank(self, x: PlayerGame, playlist: int) -> int: + print(playlist) x = self.convert_sql_object_to_numpy(x, playlist) result = pd.DataFrame(index=list(range(len(x)))) if str(playlist) not in self.models: From b59abe4e47ccf4355c90f15f99b209d763724aae Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Sun, 30 Aug 2020 00:14:08 -0700 Subject: [PATCH 04/31] Add rumble --- .../spa_api/service_layers/replay/predicted_ranks.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/backend/blueprints/spa_api/service_layers/replay/predicted_ranks.py b/backend/blueprints/spa_api/service_layers/replay/predicted_ranks.py index f544a7bd7..a2ca9bba3 100644 --- a/backend/blueprints/spa_api/service_layers/replay/predicted_ranks.py +++ b/backend/blueprints/spa_api/service_layers/replay/predicted_ranks.py @@ -37,8 +37,9 @@ def create_from_id(id_: str, session=None) -> List['PredictedRank']: 6, # custom, 11, # doubles 2, # unranked doubles - 10, - 1 + 10, # ranked duels + 1, # unranked duels + 28, # rumble ] if game.playlist not in accepted_playlists: raise UnsupportedPlaylist @@ -51,7 +52,8 @@ def create_from_id(id_: str, session=None) -> List['PredictedRank']: 6: 13, 13: 13, 10: 10, - 1: 10 + 1: 10, + 28: 28 } playlist = adjusted_playlist_map[game.playlist] if game.playlist == 6 and len(game.players) == 4: From 7e26547086351c59487a6dedf6b477cc3aafa26f Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Mon, 31 Aug 2020 20:43:12 -0700 Subject: [PATCH 05/31] Add extra modes --- .../spa_api/service_layers/replay/predicted_ranks.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/backend/blueprints/spa_api/service_layers/replay/predicted_ranks.py b/backend/blueprints/spa_api/service_layers/replay/predicted_ranks.py index a2ca9bba3..2c0148788 100644 --- a/backend/blueprints/spa_api/service_layers/replay/predicted_ranks.py +++ b/backend/blueprints/spa_api/service_layers/replay/predicted_ranks.py @@ -39,7 +39,10 @@ def create_from_id(id_: str, session=None) -> List['PredictedRank']: 2, # unranked doubles 10, # ranked duels 1, # unranked duels + 27, # hoops 28, # rumble + 29, # dropshot + 30, # snow day ] if game.playlist not in accepted_playlists: raise UnsupportedPlaylist From fc1d8874eded2d42541967adbbdce841d671051f Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Mon, 31 Aug 2020 20:43:17 -0700 Subject: [PATCH 06/31] DB changes --- backend/database/objects.py | 2 +- backend/database/startup.py | 15 +-------------- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/backend/database/objects.py b/backend/database/objects.py index ad12b3a6a..1b727b552 100644 --- a/backend/database/objects.py +++ b/backend/database/objects.py @@ -315,7 +315,7 @@ def validate_code(self, key, value): class Player(DBObjectBase): __tablename__ = 'players' - platformid = Column(String(40), primary_key=True) + platformid = Column(String(40), primary_key=True, unique=True) platformname = Column(String(50)) avatar = Column(String(150)) ranks = Column(postgresql.ARRAY(Integer, dimensions=1)) # foreign key diff --git a/backend/database/startup.py b/backend/database/startup.py index 8481ac7c7..6ab080770 100644 --- a/backend/database/startup.py +++ b/backend/database/startup.py @@ -32,20 +32,6 @@ def login(connection_string, recreate_database=False) -> Tuple[create_engine, se return engine, session -def startup() -> sessionmaker: - try: - # Sql Stuff - connection_string = 'postgresql:///saltie' - engine, session = login(connection_string) - except OperationalError as e: - print('trying backup info', e) - try: - engine, session = login('postgresql://postgres:postgres@localhost/saltie') - except Exception as e: - engine, session = login('postgresql://postgres:postgres@localhost', recreate_database=True) - return session - - def get_current_session(): return EngineStartup.get_current_session() @@ -90,6 +76,7 @@ def login_db() -> Tuple[any, sessionmaker]: try: engine, session = login('postgresql://postgres:postgres@localhost/saltie') except Exception as e: + print(e) engine, session = login('postgresql://postgres:postgres@localhost', recreate_database=True) return engine, session From 7e20d01817a2fa16d227326bfc1576c2b46c6be0 Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Mon, 31 Aug 2020 20:43:34 -0700 Subject: [PATCH 07/31] Extra modes --- .../spa_api/service_layers/replay/predicted_ranks.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/backend/blueprints/spa_api/service_layers/replay/predicted_ranks.py b/backend/blueprints/spa_api/service_layers/replay/predicted_ranks.py index 2c0148788..675bb3b23 100644 --- a/backend/blueprints/spa_api/service_layers/replay/predicted_ranks.py +++ b/backend/blueprints/spa_api/service_layers/replay/predicted_ranks.py @@ -56,7 +56,10 @@ def create_from_id(id_: str, session=None) -> List['PredictedRank']: 13: 13, 10: 10, 1: 10, - 28: 28 + 27: 27, + 28: 28, + 29: 29, + 30: 30 } playlist = adjusted_playlist_map[game.playlist] if game.playlist == 6 and len(game.players) == 4: From d0bf7277a17b11da9cdd95d0c3b566c14c86f878 Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Mon, 31 Aug 2020 21:25:18 -0700 Subject: [PATCH 08/31] Optimize player profile stats --- .../service_layers/player/player_profile_stats.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/backend/blueprints/spa_api/service_layers/player/player_profile_stats.py b/backend/blueprints/spa_api/service_layers/player/player_profile_stats.py index 03a731aaa..c3a11111c 100644 --- a/backend/blueprints/spa_api/service_layers/player/player_profile_stats.py +++ b/backend/blueprints/spa_api/service_layers/player/player_profile_stats.py @@ -1,14 +1,14 @@ from typing import List -from sqlalchemy import func, desc, cast, String, literal_column +from sqlalchemy import func, desc, cast, String from sqlalchemy.dialects import postgresql from backend.blueprints.spa_api.service_layers.replay.replay_player import Loadout from backend.blueprints.spa_api.service_layers.utils import with_session +from backend.data.constants.car import get_car from backend.database.objects import PlayerGame, Game, Player from backend.database.wrapper.player_wrapper import PlayerWrapper from backend.database.wrapper.stats.player_stat_wrapper import PlayerStatWrapper -from backend.data.constants.car import get_car player_wrapper = PlayerWrapper(limit=10) player_stat_wrapper = PlayerStatWrapper(player_wrapper) @@ -48,15 +48,13 @@ def _get_most_played_with(id_: str, session): result = session.query(p, func.count(Game.players).label('count')).filter( Game.players.contains(cast([id_], - postgresql.ARRAY(String)))).group_by('player').order_by(desc('count')).subquery( - 't') - result = session.query(result, Player.platformname).join(Player, - Player.platformid == result.c.player).filter( - Player.platformid != id_).filter(literal_column('count') > 1)[:3] + postgresql.ARRAY(String)))).group_by('player').order_by(desc('count')) + result = result[:3] for p in result: player = session.query(Player).filter(Player.platformid == p[0]).first() if player is None or player.platformname == "": - players_in_common.append(PlayerInCommonStats(name=p[2], count=p[1], id=p[0], avatar=player.avatar)) + print("unknown player") + players_in_common.append(PlayerInCommonStats(name="Unknown", count=p[1], id=p[0], avatar=player.avatar)) else: players_in_common.append( PlayerInCommonStats(name=player.platformname, count=p[1], id=p[0], avatar=player.avatar)) From b8dd5c2af4d73162b83acf98c399dbeacf95d036 Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Mon, 31 Aug 2020 21:25:25 -0700 Subject: [PATCH 09/31] Fix db debug issues --- backend/database/utils/debug_db.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/backend/database/utils/debug_db.py b/backend/database/utils/debug_db.py index 65ed2c047..d569cc24d 100644 --- a/backend/database/utils/debug_db.py +++ b/backend/database/utils/debug_db.py @@ -1,4 +1,4 @@ -from sqlalchemy.engine.default import DefaultDialect +from sqlalchemy.dialects.postgresql import dialect as DefaultDialect, ARRAY from sqlalchemy.sql.sqltypes import String, DateTime, NullType # python2/3 compatible. @@ -18,7 +18,11 @@ def process(value): return text(value) if not isinstance(value, str_type): value = text(value) + + if isinstance(value, list): + return text("{" + ", ".join(value) + "}") result = super_processor(value) + if isinstance(result, bytes): result = result.decode(dialect.encoding) return result @@ -33,6 +37,7 @@ class LiteralDialect(DefaultDialect): DateTime: StringLiteral, # don't format py2 long integers to NULL NullType: StringLiteral, + ARRAY: StringLiteral } From bddf8083e1a75e3125946340d5d32aa03f85a348 Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Mon, 31 Aug 2020 21:32:25 -0700 Subject: [PATCH 10/31] Optimize profile stats --- .../spa_api/service_layers/player/player_profile_stats.py | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/blueprints/spa_api/service_layers/player/player_profile_stats.py b/backend/blueprints/spa_api/service_layers/player/player_profile_stats.py index c3a11111c..4af31491e 100644 --- a/backend/blueprints/spa_api/service_layers/player/player_profile_stats.py +++ b/backend/blueprints/spa_api/service_layers/player/player_profile_stats.py @@ -84,7 +84,6 @@ def _get_favourite_car(id_: str, session): def _get_most_recent_loadout(id_: str, session): pg = session.query(PlayerGame) \ .join(Game, PlayerGame.game == Game.hash) \ - .distinct(PlayerGame.player) \ .filter(PlayerGame.player == id_) \ .order_by(desc(PlayerGame.player), desc(Game.match_date)) \ .first() From c919081fb1e9661884cfd475a47ce8231abf0c1a Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Mon, 31 Aug 2020 21:36:20 -0700 Subject: [PATCH 11/31] Open up beta tabs --- webapp/src/Components/Replay/ReplayTabs.tsx | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/webapp/src/Components/Replay/ReplayTabs.tsx b/webapp/src/Components/Replay/ReplayTabs.tsx index 4a194c52a..d2a633ecc 100644 --- a/webapp/src/Components/Replay/ReplayTabs.tsx +++ b/webapp/src/Components/Replay/ReplayTabs.tsx @@ -93,16 +93,8 @@ class ReplayTabsComponent extends React.PureComponent { - {this.props.loggedInUser && this.props.loggedInUser.beta ? ( - - ) : ( - - )} - {this.props.loggedInUser && this.props.loggedInUser.beta ? ( - - ) : ( - - )} + + {this.props.loggedInUser && this.props.loggedInUser.beta ? ( ) : ( From 445b5b2e0934a931e218c5ba6610bf7bc2b944ea Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Mon, 31 Aug 2020 21:58:44 -0700 Subject: [PATCH 12/31] Fix profile stats --- .../spa_api/service_layers/player/player_profile_stats.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/blueprints/spa_api/service_layers/player/player_profile_stats.py b/backend/blueprints/spa_api/service_layers/player/player_profile_stats.py index 4af31491e..b6a0fb0ee 100644 --- a/backend/blueprints/spa_api/service_layers/player/player_profile_stats.py +++ b/backend/blueprints/spa_api/service_layers/player/player_profile_stats.py @@ -49,7 +49,7 @@ def _get_most_played_with(id_: str, session): func.count(Game.players).label('count')).filter( Game.players.contains(cast([id_], postgresql.ARRAY(String)))).group_by('player').order_by(desc('count')) - result = result[:3] + result = result[1:4] for p in result: player = session.query(Player).filter(Player.platformid == p[0]).first() if player is None or player.platformname == "": From f8d311341040221b7983c921d5eb0cfeed12a94b Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Mon, 31 Aug 2020 22:02:04 -0700 Subject: [PATCH 13/31] Remove favorite car? --- .../spa_api/service_layers/player/player_profile_stats.py | 4 +++- .../Player/Overview/SideBar/PlayerStats/PlayerStatsCard.tsx | 3 +-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/backend/blueprints/spa_api/service_layers/player/player_profile_stats.py b/backend/blueprints/spa_api/service_layers/player/player_profile_stats.py index b6a0fb0ee..27ed2dea7 100644 --- a/backend/blueprints/spa_api/service_layers/player/player_profile_stats.py +++ b/backend/blueprints/spa_api/service_layers/player/player_profile_stats.py @@ -35,7 +35,9 @@ def __init__(self, favourite_car: str, car_percentage: float, players_in_common: @staticmethod @with_session def create_from_id(id_: str, session=None) -> 'PlayerProfileStats': - favourite_car, car_percentage = PlayerProfileStats._get_favourite_car(id_, session) + # favourite_car, car_percentage = PlayerProfileStats._get_favourite_car(id_, session) + favourite_car = "Unknown" + car_percentage = 0.0 players_in_common = PlayerProfileStats._get_most_played_with(id_, session) loadout = PlayerProfileStats._get_most_recent_loadout(id_, session) return PlayerProfileStats(favourite_car=favourite_car, car_percentage=car_percentage, diff --git a/webapp/src/Components/Player/Overview/SideBar/PlayerStats/PlayerStatsCard.tsx b/webapp/src/Components/Player/Overview/SideBar/PlayerStats/PlayerStatsCard.tsx index 0012422a6..7ceecffbc 100644 --- a/webapp/src/Components/Player/Overview/SideBar/PlayerStats/PlayerStatsCard.tsx +++ b/webapp/src/Components/Player/Overview/SideBar/PlayerStats/PlayerStatsCard.tsx @@ -2,7 +2,6 @@ import {Card, CardContent, CardHeader, Divider} from "@material-ui/core" import * as React from "react" import {getStats} from "../../../../../Requests/Player/getStats" import {LoadableWrapper} from "../../../../Shared/LoadableWrapper" -import {FavouriteCar} from "./FavouriteCar" import {LoadoutDialogWrapper} from "./LoadoutDialogWrapper" import {PlaysWith} from "./PlaysWith" @@ -37,7 +36,7 @@ export class PlayerStatsCard extends React.PureComponent { {this.state.playerStats && ( <> - + {/**/} Date: Mon, 31 Aug 2020 22:04:00 -0700 Subject: [PATCH 14/31] Revert revert --- .../spa_api/service_layers/player/player_profile_stats.py | 4 +--- .../Player/Overview/SideBar/PlayerStats/PlayerStatsCard.tsx | 3 ++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/backend/blueprints/spa_api/service_layers/player/player_profile_stats.py b/backend/blueprints/spa_api/service_layers/player/player_profile_stats.py index 27ed2dea7..b6a0fb0ee 100644 --- a/backend/blueprints/spa_api/service_layers/player/player_profile_stats.py +++ b/backend/blueprints/spa_api/service_layers/player/player_profile_stats.py @@ -35,9 +35,7 @@ def __init__(self, favourite_car: str, car_percentage: float, players_in_common: @staticmethod @with_session def create_from_id(id_: str, session=None) -> 'PlayerProfileStats': - # favourite_car, car_percentage = PlayerProfileStats._get_favourite_car(id_, session) - favourite_car = "Unknown" - car_percentage = 0.0 + favourite_car, car_percentage = PlayerProfileStats._get_favourite_car(id_, session) players_in_common = PlayerProfileStats._get_most_played_with(id_, session) loadout = PlayerProfileStats._get_most_recent_loadout(id_, session) return PlayerProfileStats(favourite_car=favourite_car, car_percentage=car_percentage, diff --git a/webapp/src/Components/Player/Overview/SideBar/PlayerStats/PlayerStatsCard.tsx b/webapp/src/Components/Player/Overview/SideBar/PlayerStats/PlayerStatsCard.tsx index 7ceecffbc..0012422a6 100644 --- a/webapp/src/Components/Player/Overview/SideBar/PlayerStats/PlayerStatsCard.tsx +++ b/webapp/src/Components/Player/Overview/SideBar/PlayerStats/PlayerStatsCard.tsx @@ -2,6 +2,7 @@ import {Card, CardContent, CardHeader, Divider} from "@material-ui/core" import * as React from "react" import {getStats} from "../../../../../Requests/Player/getStats" import {LoadableWrapper} from "../../../../Shared/LoadableWrapper" +import {FavouriteCar} from "./FavouriteCar" import {LoadoutDialogWrapper} from "./LoadoutDialogWrapper" import {PlaysWith} from "./PlaysWith" @@ -36,7 +37,7 @@ export class PlayerStatsCard extends React.PureComponent { {this.state.playerStats && ( <> - {/**/} + Date: Tue, 1 Sep 2020 14:12:26 -0700 Subject: [PATCH 15/31] Support external DB --- backend/database/startup.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/backend/database/startup.py b/backend/database/startup.py index 6ab080770..e14e64a95 100644 --- a/backend/database/startup.py +++ b/backend/database/startup.py @@ -10,6 +10,16 @@ from backend.database.objects import DBObjectBase +try: + import config + DB_IP = config.DB_IP + DB_USER = config.DB_USER + DB_PASSWORD = config.DB_PASSWORD +except: + DB_IP = None + DB_USER = None + DB_PASSWORD = None + logger = logging.getLogger(__name__) @@ -67,6 +77,10 @@ def get_strict_redis(): class EngineStartup: @staticmethod def login_db() -> Tuple[any, sessionmaker]: + if DB_IP is not None: + connection_string = f'postgresql://{DB_USER}:{DB_PASSWORD}@{DB_IP}/saltie' + engine, session = login(connection_string) + return engine, session try: # Sql Stuff connection_string = 'postgresql:///saltie' From 7ebba010475d8ac326e8a920c599e640334e6f42 Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Wed, 2 Sep 2020 11:56:01 -0700 Subject: [PATCH 16/31] Item stats error logging --- backend/tasks/celery_tasks.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/backend/tasks/celery_tasks.py b/backend/tasks/celery_tasks.py index 701002491..2b70b05f3 100644 --- a/backend/tasks/celery_tasks.py +++ b/backend/tasks/celery_tasks.py @@ -1,17 +1,16 @@ # Celery workers -import json -import time import base64 +import json import os -import requests +import time from enum import Enum, auto from typing import Dict -from requests import ReadTimeout - +import requests from celery import Celery from celery.result import AsyncResult from celery.task import periodic_task +from requests import ReadTimeout from backend.blueprints.spa_api.service_layers.leaderboards import Leaderboards from backend.database.startup import lazy_get_redis, lazy_startup @@ -22,9 +21,9 @@ from backend.tasks.add_replay import parse_replay from backend.tasks.middleware import DBTask from backend.tasks.periodic_stats import calculate_global_stats_by_playlist -from backend.utils.rlgarage_handler import RLGarageAPI from backend.tasks.utils import get_queue_length from backend.utils.cloud_handler import GCPManager +from backend.utils.rlgarage_handler import RLGarageAPI try: from backend.tasks.training_packs.task import TrainingPackCreation @@ -213,8 +212,8 @@ def cache_item_stats(self, session=None): print("Item", item) try: ItemStatsWrapper.get_item_usage_over_time(id_, session=session, override=True) - except: - print("Error") + except Exception as e: + print("Error", e) class ResultState(Enum): From 5dd76860b574046ae0a45bf3e94ca79085b72a54 Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Wed, 2 Sep 2020 13:31:30 -0700 Subject: [PATCH 17/31] Cache replay count --- backend/blueprints/spa_api/spa_api.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/backend/blueprints/spa_api/spa_api.py b/backend/blueprints/spa_api/spa_api.py index c64e20795..a2895e092 100644 --- a/backend/blueprints/spa_api/spa_api.py +++ b/backend/blueprints/spa_api/spa_api.py @@ -131,7 +131,12 @@ def encode_bot_name(w): @bp.route('/global/replay_count') @with_session def api_get_replay_count(session=None): + r = lazy_get_redis() + if r is not None and r.get('replay_count') is not None: + return jsonify(r.get('replay_count')) count = session.query(Game.hash).count() + if r is not None: + r.set('replay_count', ex=60 * 60) return jsonify(count) From bdcfc35fbd605f694d3f8e8230fd2a40daa6d32e Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Wed, 2 Sep 2020 13:34:15 -0700 Subject: [PATCH 18/31] Cache recent replays --- .../spa_api/service_layers/homepage/recent.py | 13 +++++++++++-- backend/blueprints/spa_api/spa_api.py | 4 ++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/backend/blueprints/spa_api/service_layers/homepage/recent.py b/backend/blueprints/spa_api/service_layers/homepage/recent.py index 8c7d71388..dd689e466 100644 --- a/backend/blueprints/spa_api/service_layers/homepage/recent.py +++ b/backend/blueprints/spa_api/service_layers/homepage/recent.py @@ -1,8 +1,11 @@ +import json + from sqlalchemy import desc from backend.blueprints.spa_api.service_layers.replay.replay import CompactReplay from backend.blueprints.spa_api.service_layers.utils import with_session from backend.database.objects import Game +from backend.database.startup import lazy_get_redis class RecentReplays: @@ -17,8 +20,14 @@ def create(cls): @staticmethod @with_session def get_recent_replays(session=None): - replays = session.query(Game).order_by(desc(Game.upload_date))[:5][::-1] - return [CompactReplay.create_from_game(r).__dict__ for r in replays] + r = lazy_get_redis() + if r is not None and r.get('recent_replays') is not None: + return json.loads(r.get('recent_replays')) + replays = session.query(Game).order_by(desc(Game.upload_date))[:5] + replays = [CompactReplay.create_from_game(r).__dict__ for r in replays] + if r is not None: + r.set('recent_replays', json.dumps(replays), ex=60 * 60) + return replays if __name__ == '__main__': diff --git a/backend/blueprints/spa_api/spa_api.py b/backend/blueprints/spa_api/spa_api.py index a2895e092..df43dc313 100644 --- a/backend/blueprints/spa_api/spa_api.py +++ b/backend/blueprints/spa_api/spa_api.py @@ -133,10 +133,10 @@ def encode_bot_name(w): def api_get_replay_count(session=None): r = lazy_get_redis() if r is not None and r.get('replay_count') is not None: - return jsonify(r.get('replay_count')) + return jsonify(int(r.get('replay_count'))) count = session.query(Game.hash).count() if r is not None: - r.set('replay_count', ex=60 * 60) + r.set('replay_count', str(count), ex=60 * 60) return jsonify(count) From b8ae8bcbb86f22f777a4832b7f82376db7b9f4a7 Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Wed, 2 Sep 2020 14:17:42 -0700 Subject: [PATCH 19/31] Recycle connections --- backend/database/startup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/database/startup.py b/backend/database/startup.py index e14e64a95..78c262bcc 100644 --- a/backend/database/startup.py +++ b/backend/database/startup.py @@ -25,7 +25,7 @@ def login(connection_string, recreate_database=False) -> Tuple[create_engine, sessionmaker]: print(connection_string) - engine = create_engine(connection_string, echo=False) + engine = create_engine(connection_string, echo=False, pool_recycle=1800) if recreate_database: conn = engine.connect() conn.execute("commit") From cac59fe15edde7c3aef18f4f76e0f8fb1ae4085e Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Wed, 2 Sep 2020 20:28:19 -0700 Subject: [PATCH 20/31] Session fixers --- backend/utils/psyonix_api_handler.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/backend/utils/psyonix_api_handler.py b/backend/utils/psyonix_api_handler.py index 2c37735a7..bb772c994 100644 --- a/backend/utils/psyonix_api_handler.py +++ b/backend/utils/psyonix_api_handler.py @@ -5,8 +5,9 @@ import redis import requests + from backend.database.objects import Player -from backend.database.startup import lazy_startup +from backend.database.startup import get_current_session from backend.utils.braacket_connection import Braacket from backend.utils.safe_flask_globals import get_redis @@ -26,8 +27,10 @@ def get_bot_by_steam_id(steam_id): if len(steam_id) < 6: return "Allstar" else: - session = lazy_startup() - bot = session().query(Player).filter(Player.platformid == steam_id).first() + Session = get_current_session() + session = Session() + bot = session.query(Player).filter(Player.platformid == steam_id).first() + session.close() if bot is None: return None return bot.platformname From fa9345e9f994885c6d775f1925645824c828b54a Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Wed, 2 Sep 2020 20:29:08 -0700 Subject: [PATCH 21/31] Error logging --- backend/database/startup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/database/startup.py b/backend/database/startup.py index 78c262bcc..2a8310ded 100644 --- a/backend/database/startup.py +++ b/backend/database/startup.py @@ -119,6 +119,7 @@ def get_strict_redis(): def get_current_session(): try: return current_app.config['db']() - except: + except Exception as e: + print("Error getting session", e) _session = lazy_startup() return _session() From 300e367402b5eef015faec3b6f2225469f4f28d1 Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Wed, 2 Sep 2020 23:24:34 -0700 Subject: [PATCH 22/31] Remove playstyle/stats temporarily --- .../Player/Overview/SideBar/PlayerSideBar.tsx | 3 +- .../src/Components/Player/PlayerOverview.tsx | 36 +++++++++---------- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/webapp/src/Components/Player/Overview/SideBar/PlayerSideBar.tsx b/webapp/src/Components/Player/Overview/SideBar/PlayerSideBar.tsx index b7a3d8193..034fc885f 100644 --- a/webapp/src/Components/Player/Overview/SideBar/PlayerSideBar.tsx +++ b/webapp/src/Components/Player/Overview/SideBar/PlayerSideBar.tsx @@ -2,7 +2,6 @@ import {Grid} from "@material-ui/core" import * as React from "react" import {PlayerProfile} from "./PlayerProfile" import {PlayerRanksCard} from "./PlayerRanksCard" -import {PlayerStatsCard} from "./PlayerStats/PlayerStatsCard" interface Props { player: Player @@ -16,7 +15,7 @@ export class PlayerSideBar extends React.PureComponent { - + {/**/} diff --git a/webapp/src/Components/Player/PlayerOverview.tsx b/webapp/src/Components/Player/PlayerOverview.tsx index e96014923..db8f401d1 100644 --- a/webapp/src/Components/Player/PlayerOverview.tsx +++ b/webapp/src/Components/Player/PlayerOverview.tsx @@ -5,8 +5,6 @@ import {isWidthDown, isWidthUp, WithWidth} from "@material-ui/core/withWidth" import * as React from "react" import {OverviewMatchHistory} from "./Overview/MatchHistory/OverviewMatchHistory" import {PlayerMatchHistoryCard} from "./Overview/MatchHistory/PlayerMatchHistoryCard" -import {PlayerPlayStyle} from "./Overview/PlayStyle/PlayerPlayStyle" -import {PlayerPlayStyleCard} from "./Overview/PlayStyle/PlayerPlayStyleCard" import {PlayStyleActions} from "./Overview/PlayStyle/PlayStyleActions" import {PlayerSideBar} from "./Overview/SideBar/PlayerSideBar" @@ -39,13 +37,13 @@ class PlayerOverviewComponent extends React.PureComponent { } const playerSideBar = - const playerPlayStyle = ( - - ) + // const playerPlayStyle = ( + // + // ) const playerMatchHistory = ( ) @@ -59,15 +57,15 @@ class PlayerOverviewComponent extends React.PureComponent { - - {playerPlayStyle} - + {/**/} + {/* {playerPlayStyle}*/} + {/**/} @@ -103,7 +101,7 @@ class PlayerOverviewComponent extends React.PureComponent { handleWinsLossesChange={this.handleWinsLossesChange} /> - {playerPlayStyle} + {/*{playerPlayStyle}*/} )} {this.state.selectedMobileTab === "Match History" && playerMatchHistory} From ac3b2a8731e3a24e7dbddbc1f56baf025d0558f1 Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Thu, 3 Sep 2020 09:28:58 -0700 Subject: [PATCH 23/31] Remove leaderboards --- webapp/src/Components/Pages/HomePage.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/webapp/src/Components/Pages/HomePage.tsx b/webapp/src/Components/Pages/HomePage.tsx index f70690e77..60f8f45fe 100644 --- a/webapp/src/Components/Pages/HomePage.tsx +++ b/webapp/src/Components/Pages/HomePage.tsx @@ -22,7 +22,6 @@ import {LoggedInUserActions, StoreState} from "../../Redux" import {getLoggedInUser, getReplayCount} from "../../Requests/Global" import {HomePageAppBar} from "../Home/HomePageAppBar" import {HomePageFooter} from "../Home/HomePageFooter" -import {Leaderboards} from "../Home/Widgets/Leaderboards" import {Recent} from "../Home/Widgets/Recent" import {Twitch} from "../Home/Widgets/Twitch" import {LinkButton} from "../Shared/LinkButton" @@ -177,7 +176,7 @@ class HomePageComponent extends React.PureComponent { - + {/**/} ) : ( @@ -186,7 +185,7 @@ class HomePageComponent extends React.PureComponent { - + {/**/} From 101ec893ceee17c25124c03b2560c2bee9f0138e Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Thu, 3 Sep 2020 12:15:24 -0700 Subject: [PATCH 24/31] Remove leaderboard link --- webapp/src/Components/Shared/SideBar.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/webapp/src/Components/Shared/SideBar.tsx b/webapp/src/Components/Shared/SideBar.tsx index 231441c70..c90fe6101 100644 --- a/webapp/src/Components/Shared/SideBar.tsx +++ b/webapp/src/Components/Shared/SideBar.tsx @@ -11,7 +11,6 @@ import Info from "@material-ui/icons/Info" import Search from "@material-ui/icons/Search" import ShowChart from "@material-ui/icons/ShowChart" import SportsSoccer from "@material-ui/icons/SportsSoccer" -import TableChart from "@material-ui/icons/TableChart" import * as React from "react" import {connect} from "react-redux" import {Link, LinkProps} from "react-router-dom" @@ -21,7 +20,6 @@ import { EXPLANATIONS_LINK, GITHUB_LINK, GLOBAL_STATS_LINK, - LEADERBOARDS_LINK, PATREON_LINK, PLAYER_COMPARE_PAGE_LINK, REPLAYS_GROUP_PAGE_LINK, @@ -76,12 +74,12 @@ class SideBarComponent extends React.PureComponent { Player - + {/* Leaderboards - + */} From 910d6040153750152f270c690951babadeb015f0 Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Thu, 3 Sep 2020 16:31:14 -0700 Subject: [PATCH 25/31] Slim down --- webapp/src/Components/Pages/HomePage.tsx | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/webapp/src/Components/Pages/HomePage.tsx b/webapp/src/Components/Pages/HomePage.tsx index 60f8f45fe..63d4f5f2c 100644 --- a/webapp/src/Components/Pages/HomePage.tsx +++ b/webapp/src/Components/Pages/HomePage.tsx @@ -22,8 +22,6 @@ import {LoggedInUserActions, StoreState} from "../../Redux" import {getLoggedInUser, getReplayCount} from "../../Requests/Global" import {HomePageAppBar} from "../Home/HomePageAppBar" import {HomePageFooter} from "../Home/HomePageFooter" -import {Recent} from "../Home/Widgets/Recent" -import {Twitch} from "../Home/Widgets/Twitch" import {LinkButton} from "../Shared/LinkButton" import {Logo} from "../Shared/Logo/Logo" import {Search} from "../Shared/Search" @@ -48,8 +46,8 @@ const styles = (theme: Theme) => minHeight: "100vh", display: "flex", backgroundSize: "cover", - backgroundAttachment: "fixed", - backgroundImage: theme.palette.type === "dark" ? 'url("/splash_black.png")' : 'url("/splash.png")' + backgroundAttachment: "fixed" + // backgroundImage: theme.palette.type === "dark" ? 'url("/splash_black.png")' : 'url("/splash.png")' } }) @@ -169,11 +167,11 @@ class HomePageComponent extends React.PureComponent { {isWidthUp("md", this.props.width) ? ( <> - + {/**/} - + {/**/} {/**/} @@ -182,13 +180,13 @@ class HomePageComponent extends React.PureComponent { ) : ( <> - + {/**/} {/**/} - + {/**/} )} From 348215d304e37f5a11bc2e45d701054c8eb03e05 Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Thu, 3 Sep 2020 16:34:58 -0700 Subject: [PATCH 26/31] Bring back background --- webapp/src/Components/Pages/HomePage.tsx | 36 ++++++++++++------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/webapp/src/Components/Pages/HomePage.tsx b/webapp/src/Components/Pages/HomePage.tsx index 63d4f5f2c..1816fdb01 100644 --- a/webapp/src/Components/Pages/HomePage.tsx +++ b/webapp/src/Components/Pages/HomePage.tsx @@ -1,4 +1,4 @@ -import {faSteam} from "@fortawesome/free-brands-svg-icons" +import { faSteam } from "@fortawesome/free-brands-svg-icons" import { Button, createStyles, @@ -10,23 +10,23 @@ import { withStyles, withWidth } from "@material-ui/core" -import {GridProps} from "@material-ui/core/Grid" -import {isWidthUp, WithWidth} from "@material-ui/core/withWidth" +import { GridProps } from "@material-ui/core/Grid" +import { isWidthUp, WithWidth } from "@material-ui/core/withWidth" import CloudUpload from "@material-ui/icons/CloudUpload" import * as React from "react" -import {connect} from "react-redux" -import {Link} from "react-router-dom" -import {Dispatch} from "redux" -import {PLAYER_PAGE_LINK, STEAM_LOGIN_LINK, UPLOAD_LINK} from "../../Globals" -import {LoggedInUserActions, StoreState} from "../../Redux" -import {getLoggedInUser, getReplayCount} from "../../Requests/Global" -import {HomePageAppBar} from "../Home/HomePageAppBar" -import {HomePageFooter} from "../Home/HomePageFooter" -import {LinkButton} from "../Shared/LinkButton" -import {Logo} from "../Shared/Logo/Logo" -import {Search} from "../Shared/Search" -import {SideBar} from "../Shared/SideBar" -import {UploadDialogWrapper} from "../Shared/Upload/UploadDialogWrapper" +import { connect } from "react-redux" +import { Link } from "react-router-dom" +import { Dispatch } from "redux" +import { PLAYER_PAGE_LINK, STEAM_LOGIN_LINK, UPLOAD_LINK } from "../../Globals" +import { LoggedInUserActions, StoreState } from "../../Redux" +import { getLoggedInUser, getReplayCount } from "../../Requests/Global" +import { HomePageAppBar } from "../Home/HomePageAppBar" +import { HomePageFooter } from "../Home/HomePageFooter" +import { LinkButton } from "../Shared/LinkButton" +import { Logo } from "../Shared/Logo/Logo" +import { Search } from "../Shared/Search" +import { SideBar } from "../Shared/SideBar" +import { UploadDialogWrapper } from "../Shared/Upload/UploadDialogWrapper" const styles = (theme: Theme) => createStyles({ @@ -46,8 +46,8 @@ const styles = (theme: Theme) => minHeight: "100vh", display: "flex", backgroundSize: "cover", - backgroundAttachment: "fixed" - // backgroundImage: theme.palette.type === "dark" ? 'url("/splash_black.png")' : 'url("/splash.png")' + backgroundAttachment: "fixed", + backgroundImage: theme.palette.type === "dark" ? 'url("/splash_black.png")' : 'url("/splash.png")' } }) From 703bcf695502b11734bcbd3c9be55a8755c93073 Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Thu, 3 Sep 2020 16:45:57 -0700 Subject: [PATCH 27/31] Task changes --- backend/tasks/celery_tasks.py | 13 +++++++--- webapp/src/Components/Pages/HomePage.tsx | 32 ++++++++++++------------ 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/backend/tasks/celery_tasks.py b/backend/tasks/celery_tasks.py index 2b70b05f3..d4b14704d 100644 --- a/backend/tasks/celery_tasks.py +++ b/backend/tasks/celery_tasks.py @@ -126,9 +126,12 @@ def calc_leaderboards(self): @periodic_task(run_every=60 * 10, base=DBTask, bind=True, priority=0) -def calc_global_dists(self): - sess = self.session() - calculate_global_stats_by_playlist() +def calc_global_dists(self, session=None): + if session is None: + sess = self.session() + else: + sess = session + calculate_global_stats_by_playlist(session) sess.close() @@ -139,6 +142,7 @@ def calc_item_stats(self, session=None): else: sess = session results = ItemStatsWrapper.create_stats(sess) + sess.close() if lazy_get_redis() is not None: lazy_get_redis().set('item_stats', json.dumps(results)) @@ -160,6 +164,7 @@ def auto_create_training_pack(self, requester_id, pack_player_id, name=None, n=1 METRICS_TRAINING_PACK_CREATION_TIME.observe( start - end ) + sess.close() return url @@ -178,6 +183,7 @@ def create_manual_training_pack(self, requester_id, players, replays, frames, na METRICS_TRAINING_PACK_CREATION_TIME.observe( start - end ) + sess.close() return url @@ -214,6 +220,7 @@ def cache_item_stats(self, session=None): ItemStatsWrapper.get_item_usage_over_time(id_, session=session, override=True) except Exception as e: print("Error", e) + session.close() class ResultState(Enum): diff --git a/webapp/src/Components/Pages/HomePage.tsx b/webapp/src/Components/Pages/HomePage.tsx index 1816fdb01..86c087e67 100644 --- a/webapp/src/Components/Pages/HomePage.tsx +++ b/webapp/src/Components/Pages/HomePage.tsx @@ -1,4 +1,4 @@ -import { faSteam } from "@fortawesome/free-brands-svg-icons" +import {faSteam} from "@fortawesome/free-brands-svg-icons" import { Button, createStyles, @@ -10,23 +10,23 @@ import { withStyles, withWidth } from "@material-ui/core" -import { GridProps } from "@material-ui/core/Grid" -import { isWidthUp, WithWidth } from "@material-ui/core/withWidth" +import {GridProps} from "@material-ui/core/Grid" +import {isWidthUp, WithWidth} from "@material-ui/core/withWidth" import CloudUpload from "@material-ui/icons/CloudUpload" import * as React from "react" -import { connect } from "react-redux" -import { Link } from "react-router-dom" -import { Dispatch } from "redux" -import { PLAYER_PAGE_LINK, STEAM_LOGIN_LINK, UPLOAD_LINK } from "../../Globals" -import { LoggedInUserActions, StoreState } from "../../Redux" -import { getLoggedInUser, getReplayCount } from "../../Requests/Global" -import { HomePageAppBar } from "../Home/HomePageAppBar" -import { HomePageFooter } from "../Home/HomePageFooter" -import { LinkButton } from "../Shared/LinkButton" -import { Logo } from "../Shared/Logo/Logo" -import { Search } from "../Shared/Search" -import { SideBar } from "../Shared/SideBar" -import { UploadDialogWrapper } from "../Shared/Upload/UploadDialogWrapper" +import {connect} from "react-redux" +import {Link} from "react-router-dom" +import {Dispatch} from "redux" +import {PLAYER_PAGE_LINK, STEAM_LOGIN_LINK, UPLOAD_LINK} from "../../Globals" +import {LoggedInUserActions, StoreState} from "../../Redux" +import {getLoggedInUser, getReplayCount} from "../../Requests/Global" +import {HomePageAppBar} from "../Home/HomePageAppBar" +import {HomePageFooter} from "../Home/HomePageFooter" +import {LinkButton} from "../Shared/LinkButton" +import {Logo} from "../Shared/Logo/Logo" +import {Search} from "../Shared/Search" +import {SideBar} from "../Shared/SideBar" +import {UploadDialogWrapper} from "../Shared/Upload/UploadDialogWrapper" const styles = (theme: Theme) => createStyles({ From c1ce03b2bcbaa52d4be567b5d19b075d9746bee5 Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Thu, 3 Sep 2020 16:57:50 -0700 Subject: [PATCH 28/31] Limit training packs again --- backend/tasks/training_packs/task.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/tasks/training_packs/task.py b/backend/tasks/training_packs/task.py index b8244e6f9..e929ea1d8 100644 --- a/backend/tasks/training_packs/task.py +++ b/backend/tasks/training_packs/task.py @@ -1,6 +1,7 @@ import datetime import logging import os +import random from sqlalchemy import desc @@ -103,7 +104,7 @@ def create_from_player(task_id, requester_id, pack_player_id, n=10, date_start=N if query.count() == 0: raise UserHasNoReplays() if date_start is not None: - last_n_games = last_n_games.all()[:100] # we don't want to overdo it, but we want to max the pack + last_n_games = random.sample(last_n_games.all(), 25) # we don't want to overdo it else: last_n_games = last_n_games[:n] # use default of last n games last_n_games = [game[0] for game in last_n_games] # gets rid of tuples From d3e27a407b05aacb3566f661b0fd7983be462ebd Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Thu, 3 Sep 2020 20:13:32 -0700 Subject: [PATCH 29/31] Add groups to replay page --- .../spa_api/service_layers/replay/replay.py | 19 ++++++++++++------- .../Player/Overview/SideBar/PlayerProfile.tsx | 4 ++-- .../Replay/ReplayTeamCard/ReplayTeamCard.tsx | 2 +- .../Replay/ReplayTeamCard/TeamCardPlayer.tsx | 5 ++++- webapp/src/Models/Replay/Replay.ts | 1 + webapp/src/Requests/Mock.ts | 6 ++++-- 6 files changed, 24 insertions(+), 13 deletions(-) diff --git a/backend/blueprints/spa_api/service_layers/replay/replay.py b/backend/blueprints/spa_api/service_layers/replay/replay.py index 711e10940..c6415cb8c 100644 --- a/backend/blueprints/spa_api/service_layers/replay/replay.py +++ b/backend/blueprints/spa_api/service_layers/replay/replay.py @@ -1,11 +1,11 @@ -from typing import List, cast +from typing import List, cast, Dict from backend.blueprints.spa_api.errors.errors import ReplayNotFound, Redirect from backend.blueprints.spa_api.service_layers.replay.json_tag import JsonTag from backend.blueprints.spa_api.service_layers.replay.replay_player import ReplayPlayer from backend.blueprints.spa_api.service_layers.utils import sort_player_games_by_team_then_id, with_session from backend.data.constants.playlist import get_playlist -from backend.database.objects import Game, PlayerGame, GameVisibilitySetting +from backend.database.objects import Game, PlayerGame, GameVisibilitySetting, Player from backend.utils.safe_flask_globals import get_current_user_id @@ -23,7 +23,7 @@ class Replay: def __init__(self, id_: str, name: str, date: str, map: str, game_mode: str, game_score: GameScore, players: List[ReplayPlayer], tags: List[JsonTag], visibility: GameVisibilitySetting, - ranks: List[int], mmrs: List[int]): + ranks: List[int], mmrs: List[int], group_map: Dict[str, List[int]]): self.id = id_ self.name = name self.date = date @@ -35,6 +35,7 @@ def __init__(self, id_: str, name: str, date: str, map: str, self.visibility = visibility.value self.ranks = ranks self.mmrs = mmrs + self.groupMap = group_map @staticmethod @with_session @@ -45,11 +46,15 @@ def create_from_id(id_: str, session=None) -> 'Replay': if game is None: raise ReplayNotFound() raise Redirect("/replays/" + game.hash) - replay = Replay.create_from_game(game) + replay = Replay.create_from_game(game, session=session, groups=True) return replay @staticmethod - def create_from_game(game: Game, full=True) -> 'Replay': + def create_from_game(game: Game, full=True, groups=False, session=None) -> 'Replay': + group_map = None + if groups and session is not None: + players = session.query(Player).filter(Player.platformid.in_(game.players)).all() + group_map = {player.platformid: player.groups for player in players} return Replay( id_=game.hash, name=game.name, @@ -68,8 +73,8 @@ def create_from_game(game: Game, full=True) -> 'Replay': ], visibility=game.visibility, ranks=game.ranks, - mmrs=game.mmrs - + mmrs=game.mmrs, + group_map=group_map ) diff --git a/webapp/src/Components/Player/Overview/SideBar/PlayerProfile.tsx b/webapp/src/Components/Player/Overview/SideBar/PlayerProfile.tsx index e5274489e..ac11bd372 100644 --- a/webapp/src/Components/Player/Overview/SideBar/PlayerProfile.tsx +++ b/webapp/src/Components/Player/Overview/SideBar/PlayerProfile.tsx @@ -1,6 +1,5 @@ -import * as React from "react" - import {Button, Card, CardContent, createStyles, Grid, Typography, WithStyles, withStyles} from "@material-ui/core" +import * as React from "react" import {connect} from "react-redux" import {StoreState} from "../../../../Redux" import {GroupIndicator} from "./GroupIndicator" @@ -49,6 +48,7 @@ class PlayerProfileComponent extends React.PureComponent { {player.name} {player.pastNames.length > 0 && } + diff --git a/webapp/src/Components/Replay/ReplayTeamCard/ReplayTeamCard.tsx b/webapp/src/Components/Replay/ReplayTeamCard/ReplayTeamCard.tsx index 9714a893f..ba32aa163 100644 --- a/webapp/src/Components/Replay/ReplayTeamCard/ReplayTeamCard.tsx +++ b/webapp/src/Components/Replay/ReplayTeamCard/ReplayTeamCard.tsx @@ -46,7 +46,7 @@ class ReplayTeamCardComponent extends React.PureComponent { {replay.players .filter((player) => player.isOrange === isOrange) .map((player) => ( - + ))} diff --git a/webapp/src/Components/Replay/ReplayTeamCard/TeamCardPlayer.tsx b/webapp/src/Components/Replay/ReplayTeamCard/TeamCardPlayer.tsx index a8e7eda41..8d36fddb5 100644 --- a/webapp/src/Components/Replay/ReplayTeamCard/TeamCardPlayer.tsx +++ b/webapp/src/Components/Replay/ReplayTeamCard/TeamCardPlayer.tsx @@ -12,10 +12,12 @@ import { import * as React from "react" import {Link, LinkProps} from "react-router-dom" import {PLAYER_PAGE_LINK} from "../../../Globals" +import {GroupIndicator} from "../../Player/Overview/SideBar/GroupIndicator" import {CameraSettingsDisplay} from "./CameraSettingsDisplay" import {LoadoutDisplay} from "./LoadoutDisplay" interface Props { + groupMap: any player: ReplayPlayer } @@ -37,7 +39,7 @@ export class TeamCardPlayer extends React.PureComponent { } public render() { - const {player} = this.props + const {player, groupMap} = this.props const carButton = ( @@ -64,6 +66,7 @@ export class TeamCardPlayer extends React.PureComponent { style={{padding: "0 64px 0 0"}} /> + {groupMap && } {carButton} {cameraButton} diff --git a/webapp/src/Models/Replay/Replay.ts b/webapp/src/Models/Replay/Replay.ts index e0cc083fd..11d0388c7 100644 --- a/webapp/src/Models/Replay/Replay.ts +++ b/webapp/src/Models/Replay/Replay.ts @@ -25,6 +25,7 @@ export interface Replay { visibility: GameVisibility ranks: number[] mmrs: number[] + groupMap: any } export interface CompactReplay { diff --git a/webapp/src/Requests/Mock.ts b/webapp/src/Requests/Mock.ts index 156bf3f09..43c534ac6 100644 --- a/webapp/src/Requests/Mock.ts +++ b/webapp/src/Requests/Mock.ts @@ -535,7 +535,8 @@ export const MOCK_REPLAY_1: Replay = { tags: [], visibility: GameVisibility.PUBLIC, ranks: [14, 15, 14, 14], - mmrs: [1000, 1100, 1050, 1025] + mmrs: [1000, 1100, 1050, 1025], + groupMap: {} } export const MOCK_REPLAY_2 = { @@ -709,5 +710,6 @@ export const MOCK_REPLAY_2 = { } } ], - tags: [] + tags: [], + groupMap: {} } From ff1cafc7d6dd3701e506a26b31e0007a5e899cf5 Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Fri, 4 Sep 2020 11:48:35 -0700 Subject: [PATCH 30/31] Fix bot handling --- backend/utils/psyonix_api_handler.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/utils/psyonix_api_handler.py b/backend/utils/psyonix_api_handler.py index bb772c994..ab598aa06 100644 --- a/backend/utils/psyonix_api_handler.py +++ b/backend/utils/psyonix_api_handler.py @@ -27,8 +27,7 @@ def get_bot_by_steam_id(steam_id): if len(steam_id) < 6: return "Allstar" else: - Session = get_current_session() - session = Session() + session = get_current_session() bot = session.query(Player).filter(Player.platformid == steam_id).first() session.close() if bot is None: From 0226787b46be2a6bb21c6b318b737def29619ff6 Mon Sep 17 00:00:00 2001 From: Sciguymjm Date: Fri, 4 Sep 2020 13:51:35 -0700 Subject: [PATCH 31/31] Switch ordering of playlists --- .../spa_api/service_layers/replay/predicted_ranks.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/backend/blueprints/spa_api/service_layers/replay/predicted_ranks.py b/backend/blueprints/spa_api/service_layers/replay/predicted_ranks.py index 675bb3b23..81e84ec61 100644 --- a/backend/blueprints/spa_api/service_layers/replay/predicted_ranks.py +++ b/backend/blueprints/spa_api/service_layers/replay/predicted_ranks.py @@ -32,13 +32,13 @@ def create_from_id(id_: str, session=None) -> List['PredictedRank']: game: Game = session.query(Game).filter(Game.hash == id_).first() accepted_playlists = [ - 13, # standard + 1, # unranked duels + 2, # unranked doubles 3, # unranked standard 6, # custom, - 11, # doubles - 2, # unranked doubles 10, # ranked duels - 1, # unranked duels + 11, # doubles + 13, # standard 27, # hoops 28, # rumble 29, # dropshot @@ -49,13 +49,13 @@ def create_from_id(id_: str, session=None) -> List['PredictedRank']: playergames = session.query(PlayerGame).filter(PlayerGame.game == id_).all() adjusted_playlist_map = { + 1: 10, + 10: 10, 2: 11, 11: 11, 3: 13, 6: 13, 13: 13, - 10: 10, - 1: 10, 27: 27, 28: 28, 29: 29,