示例#1
0
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
示例#2
0
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
示例#7
0
 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()
示例#8
0
 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
示例#9
0
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()
示例#11
0
    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]
示例#12
0
 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()
示例#13
0
 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
示例#14
0
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
示例#16
0
 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)
示例#17
0
 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
示例#18
0
    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