def download_replay(id_): if PROTO_BUCKET is None: raise ReplayNotFound() # PROTO replay_url = f'https://storage.googleapis.com/{REPLAY_BUCKET}/{id_}.replay' r = requests.get(replay_url) if r.status_code == 404: raise ReplayNotFound() with io.BytesIO(r.content) as f: return f
def download_proto(id_): if PROTO_BUCKET is None: raise ReplayNotFound() # PROTO pts_url = f'https://storage.googleapis.com/{PROTO_BUCKET}/{id_}.replay.pts' r = requests.get(pts_url) if r.status_code == 404: raise ReplayNotFound() with io.BytesIO(r.content) as f: protobuf_game = proto_manager.ProtobufManager.read_proto_out_from_file( f) return protobuf_game
def get_replay_url(id_): if REPLAY_BUCKET is None: raise ReplayNotFound() # REPLAY bucket_name = REPLAY_BUCKET if is_archived(id_): bucket_name += "-cold" replay_url = f'https://storage.googleapis.com/{bucket_name}/{id_}.replay' r = requests.head(replay_url) if r.status_code == 404: replay_url = f'https://storage.googleapis.com/{bucket_name + "-cold"}/{id_}.replay' r = requests.head(replay_url) if r.status_code == 404: raise ReplayNotFound() return replay_url
def get_chart_stats_for_player(self, id_: str, session=None ) -> List[DatabaseObjectDataPoint]: game: Game = session.query(Game).filter(Game.hash == id_).first() if game is None: raise ReplayNotFound() # this is weird because we need to do aggregate playergames: List = session.query( func.max(PlayerGame.id), func.bool_and(PlayerGame.is_orange), func.max(PlayerGame.name), *self.player_stats.individual_query).filter( PlayerGame.game == id_).group_by(PlayerGame.player).all() wrapped_playergames: List[DatabaseObjectDataPoint] = [ DatabaseObjectDataPoint(id=playergame[0], is_orange=playergame[1], name=playergame[2], stats=self.get_wrapped_stats( playergame[3:], self.player_stats)) for playergame in playergames ] wrapped_playergames = sorted(sorted(wrapped_playergames, key=lambda x: x.id), key=lambda x: x.is_orange) return wrapped_playergames
def get_chart_stats_for_team(self, id_: str, session=None ) -> List[DatabaseObjectDataPoint]: game: Game = session.query(Game).filter(Game.hash == id_).first() if game is None: raise ReplayNotFound() # this is weird because we need to do aggregate team_game: List = session.query(func.bool_and( TeamStat.is_orange), *self.team_stats.individual_query).filter( TeamStat.game == id_).group_by(TeamStat.is_orange).all() wrapped_team: List[DatabaseObjectDataPoint] = [ DatabaseObjectDataPoint( id=0, is_orange=team_game[0], name=('Orange' if team_game[0] == 1 else 'Blue'), stats=self.get_wrapped_stats(team_game[1:], self.team_stats)) for team_game in team_game ] wrapped_team = sorted(sorted(wrapped_team, key=lambda x: x.id), key=lambda x: x.is_orange) return wrapped_team
def download_replay(id_): replay_url = get_replay_url(id_) r = requests.get(replay_url) if r.status_code == 404: raise ReplayNotFound() with io.BytesIO(r.content) as f: return f
def add_tag_to_game(session, game_id: str, tag: Tag) -> None: game = session.query(Game).filter(Game.hash == game_id).first() if game is None: raise ReplayNotFound() if tag not in game.tags: game.tags.append(tag) session.commit()
def create_from_id(id_: str, session=None) -> 'Replay': game = session.query(Game).filter(Game.hash == id_).first() if game is None: game = session.query(Game).filter(Game.replay_id == id_).first() if game is None: raise ReplayNotFound() raise Redirect("/replays/" + game.hash) replay = Replay.create_from_game(game) return replay
def download_df(id_): if PARSED_BUCKET is None: raise ReplayNotFound() gzip_url = f'https://storage.googleapis.com/{PARSED_BUCKET}/{id_}.replay.gzip' r = requests.get(gzip_url) if r.status_code == 404: raise ReplayNotFound() try: with gzip.GzipFile(fileobj=io.BytesIO(r.content)) as f: data_frame = pandas_manager.PandasManager.read_numpy_from_memory(f) except: try: with io.BytesIO(r.content) as f: data_frame = pandas_manager.PandasManager.read_numpy_from_memory( f) except: raise ReplayNotFound() return data_frame
def remove_tag_from_game(session, game_id: str, user_id: str, tag_name: str) -> None: tag = TagWrapper.get_tag_by_name(session, user_id, tag_name) game = session.query(Game).filter(Game.hash == game_id).first() if game is None: raise ReplayNotFound() if tag is not None: try: game.tags.remove(tag) session.commit() except ValueError: raise DBTagNotFound()
def get_tagged_games(session, user_id: str, names): game_tags = session.query(GameTag.game_id) \ .join(Tag) \ .filter(Tag.owner == user_id) \ .filter(Tag.name.in_(names)) \ .group_by(GameTag.game_id) \ .having(func.count(GameTag.game_id) == len(names)).all() if len(game_tags) == 0: raise ReplayNotFound() return [game_tag.game_id for game_tag in game_tags]
def add_tag_to_game(session, game_id: str, user_id: str, tag_name: str) -> None: tag: Tag = session.query(Tag).filter(Tag.owner == user_id, Tag.name == tag_name).first() if tag is None: raise DBTagNotFound() game = session.query(Game).filter(Game.hash == game_id).first() if game is None: raise ReplayNotFound() if tag not in game.tags: game.tags.append(tag) session.commit()
def have_permission_to_change_game(game_hash: str, user_id, session=None) -> bool: entry = session.query(GameVisibility).filter(GameVisibility.player == user_id, GameVisibility.game == game_hash).first() if entry is None: # Check if user has right to change visibility: builder = QueryFilterBuilder().as_game().set_replay_id(game_hash).with_players([user_id]) if builder.build_query(session).first() is not None: return True else: # Replay might actually exist, but user should not know. raise ReplayNotFound() else: return True
def update_game_visibility(game_id, session, visibility: GameVisibilitySetting, retry=False): game = session.query(Game).filter(Game.hash == game_id).first() if game is None: if not retry: time.sleep(1) return update_game_visibility(game_id=game_id, session=session, visibility=visibility, retry=True) raise ReplayNotFound() if game.visibility == visibility: return game.visibility = visibility session.commit() return
def create_from_id(id_: str) -> 'ReplayHeatmaps': pickle_path = os.path.join(current_app.config['PARSED_DIR'], id_ + '.replay.pts') gzip_path = os.path.join(current_app.config['PARSED_DIR'], id_ + '.replay.gzip') replay_path = os.path.join(current_app.config['REPLAY_DIR'], id_ + '.replay') if os.path.isfile(replay_path) and not os.path.isfile(pickle_path): raise ReplayNotFound() if not os.path.isfile(gzip_path): df = download_df(id_) protobuf_game = download_proto(id_) else: try: with gzip.open(gzip_path, 'rb') as gz: df = pandas_manager.PandasManager.safe_read_pandas_to_memory( gz) with open(pickle_path, 'rb') as f: protobuf_game = proto_manager.ProtobufManager.read_proto_out_from_file( f) except Exception as e: raise ErrorOpeningGame(str(e)) id_to_name_map = {p.id.id: p.name for p in protobuf_game.players} if protobuf_game.teams[0].is_orange: orange_team = protobuf_game.teams[0] else: orange_team = protobuf_game.teams[1] orange = [id_to_name_map[pl.id] for pl in orange_team.player_ids] counts = [[] for a in range(FULL_BOOST_POSITIONS.shape[0])] players = list(df.columns.levels[0]) players.remove("ball") players.remove("game") for player in players: player_df = df[player] boost_pickup_frames = player_df[player_df.boost_collect == True].index.values for frame in boost_pickup_frames: try: position = player_df.iloc[frame].loc[['pos_x', 'pos_y']] except: continue distances_from_boosts = np.sqrt( np.square(FULL_BOOST_POSITIONS - position.values).sum( axis=1, dtype=np.float32)) idx: int = np.argmin(distances_from_boosts) counts[idx].append( BoostPickup(player, int(player in orange), int(frame)).__dict__) return counts
def get_or_download(item_path, download_lambda, open_lambda): if not os.path.isfile(item_path): try: return download_lambda() except ReplayNotFound as e: ErrorLogger.log_error(e) raise e except Exception as e: ErrorLogger.log_error(e) raise ReplayNotFound() try: return open_lambda(item_path) except Exception as e: ErrorLogger.log_error(e) raise ErrorOpeningGame(str(e), game_data=item_path)
def add_game(parent_uuid, game, name=None, session=None): current_user = UserManager.get_current_user().platformid parent = session.query(GroupEntry).filter( GroupEntry.uuid == parent_uuid).first() if parent is None: raise ReplayNotFound() if parent.owner != current_user: raise AuthorizationException() game_obj = session.query(Game).filter(Game.hash == game).first() if game_obj is None: game_obj: Game = session.query(Game).filter( Game.replay_id == game).first() if game_obj is not None: game = game_obj.hash entry = GroupEntry(engine=session.get_bind(), name=name, game=game, owner=parent.owner, type=GroupEntryType.game, parent=parent) session.add(entry) session.commit() return entry.uuid
def create_from_id(id_: str, type_="positioning") -> 'ReplayHeatmaps': pickle_path = os.path.join(current_app.config['PARSED_DIR'], id_ + '.replay.pts') gzip_path = os.path.join(current_app.config['PARSED_DIR'], id_ + '.replay.gzip') replay_path = os.path.join(current_app.config['REPLAY_DIR'], id_ + '.replay') if os.path.isfile(replay_path) and not os.path.isfile(pickle_path): raise ReplayNotFound() if not os.path.isfile(gzip_path): if GCP_BUCKET_GZIP_URL != "": gz = gzip.GzipFile(fileobj=io.BytesIO( requests.get(GCP_BUCKET_GZIP_URL + id_ + '.replay.gzip').content), mode='rb') else: raise ReplayNotFound() else: gz = gzip.open(gzip_path, 'rb') try: data_frame = pandas_manager.PandasManager.safe_read_pandas_to_memory( gz) with open(pickle_path, 'rb') as f: protobuf_game = proto_manager.ProtobufManager.read_proto_out_from_file( f) except Exception as e: raise ErrorOpeningGame(str(e)) finally: gz.close() # output = generate_heatmaps(data_frame, protobuf_game, type="hits") output = generate_heatmaps(data_frame, protobuf_game, type=type_) data = {} maxs = {} max_ = 0 # for player in output: # arr = output[player] # player_data = [] # for x in range(len(arr[0])): # for y in range(len(arr[0][x])): # player_data.append({ # 'x': math.floor(arr[1][x] * 200 / 6000 + 250), # 'y': math.floor(arr[2][y] * 200 / 6000 + 250), # 'value': max(0, math.log(arr[0][x, y] + 1e-3)) # }) # max_ = max(math.log(arr[0][x, y] + 1e-3), max_) # data[player] = player_data # maxs[player] = max_ if type_ == 'hits': return {'data': output, 'maxs': maxs} if type_ in ['hits']: log_scale = False else: log_scale = True width = 400 / 500 for player in output: arr = output[player] player_data = [] for x in range(len(arr[0])): for y in range(len(arr[0][x])): if log_scale: value = math.log(arr[0][x, y] + 1e-3) else: value = arr[0][x, y] if value == 0: continue player_data.append({ 'x': math.floor(arr[1][x] * width * 200 / 6000 + 125), 'y': math.floor(arr[2][y] * width * 200 / 6000 + 175), 'value': max(0, value) }) max_ = max(value, max_) data[player] = player_data maxs[player] = max_ return {'data': data, 'maxs': maxs}
def get_group_stats(self, replay_ids, session=None): return_obj = {} # Players player_tuples: List[Tuple[str, str, int]] = session.query( PlayerGame.player, func.min(PlayerGame.name), func.count(PlayerGame.player)).filter( PlayerGame.game.in_(replay_ids)).group_by( PlayerGame.player).all() return_obj['playerStats'] = [] # ensemble are the players that do not have enough replays to make an individual analysis for them ensemble = [] for player_tuple in player_tuples: player, name, count = player_tuple if count > 1: player_stats = self._create_group_stats(session, player_filter=player, replay_ids=replay_ids) player_stats['name'] = name player_stats['player'] = player return_obj['playerStats'].append(player_stats) else: ensemble.append(player) if len(ensemble) > 0: # create stats that only includes the ensemble ensemble_stats = self._create_group_stats(session, player_filter=ensemble, replay_ids=replay_ids) return_obj['ensembleStats'] = ensemble_stats # STATS # Global # create stats that include all the players in the game # global_stats = self._create_group_stats(session, ids=replay_ids) # return_obj['globalStats'] = global_stats num_replays = len(replay_ids) if num_replays > 1 and all( [player_tuple[2] == num_replays for player_tuple in player_tuples]): assert 'ensembleStats' not in return_obj # all players have played every game is_orange = {player_tuple[0]: [] for player_tuple in player_tuples} for replay_id in replay_ids: game: Game = session.query(Game).filter( Game.hash == replay_id).first() if game is None: raise ReplayNotFound() playergames: List = session.query( func.max(PlayerGame.player), func.bool_and(PlayerGame.is_orange)).filter( PlayerGame.game == replay_id).group_by( PlayerGame.player).all() for playergame in playergames: assert len(playergame) == 2 player, is_orange_game = playergame assert player in is_orange is_orange[player].append(is_orange_game) # if the player is always in the same team if all([ len(set(player_is_orange)) == 1 for player_is_orange in is_orange.values() ]): for i in range(len(return_obj['playerStats'])): player = return_obj['playerStats'][i]['player'] return_obj['playerStats'][i]['is_orange'] = is_orange[ player][0] return_obj['playerStats'] = sorted( sorted(return_obj['playerStats'], key=lambda x: x['name'].lower()), key=lambda x: x['is_orange']) return return_obj