def save_replay(proto_game, replay_to_parse_path, parsed_data_path) -> str:
    """
    :param proto_game: Representing the parsed data.
    :param replay_to_parse_path: The file path to the replay we want to parse.
    :param parsed_data_path: The path to parsed data with the initial unparsed filename.
    :return: The replay ID.
    """
    replay_id = proto_game.game_metadata.match_guid
    if replay_id == '':
        replay_id = proto_game.game_metadata.id

    replay_path = FileManager.get_replay_path(replay_id)
    proto_path = FileManager.get_proto_path(replay_id)
    pandas_path = FileManager.get_pandas_path(replay_id)
    shutil.move(replay_to_parse_path, replay_path)
    shutil.move(parsed_data_path + '.pts', proto_path)
    shutil.move(parsed_data_path + '.gzip', pandas_path)

    result = upload_replay(replay_path)
    if result is not None:
        upload_proto(proto_path)
        upload_df(pandas_path)

        os.remove(replay_path)
        os.remove(proto_path)
        os.remove(pandas_path)

    return replay_id
Example #2
0
    def create_from_id(id_: str) -> 'ReplayHeatmaps':
        df = FileManager.get_pandas(id_)
        protobuf_game = FileManager.get_proto(id_)

        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 load_replay(replay):
    try:
        protobuf_game = FileManager.get_proto(replay)
        data_frame = FileManager.get_pandas(replay)
        return protobuf_game, data_frame
    except:
        return None, None
    def create_from_id(id_: str, query_params=None) -> 'ReplayPositions':
        filter_frames = None
        filter_frame_start = None
        filter_frame_count = None
        if query_params is not None and 'frame' in query_params:
            filter_frames = query_params['frame']
        if query_params is not None and 'frame_start' in query_params and 'frame_count' in query_params:
            filter_frame_start = query_params['frame_start']
            filter_frame_count = query_params['frame_count']

        data_frame = FileManager.get_pandas(id_)
        if filter_frames is not None:
            data_frame = ReplayPositions.filter_frames(filter_frames, data_frame)
        if filter_frame_start is not None and filter_frame_count is not None:
            data_frame = ReplayPositions.filter_frames_range(filter_frame_start, filter_frame_count, data_frame)
        protobuf_game = FileManager.get_proto(id_)

        cs = ['pos_x', 'pos_y', 'pos_z']
        rot_cs = ['rot_x', 'rot_y', 'rot_z']

        ball = data_frame['ball']
        ball_df = ball[cs].fillna(-100)

        players = protobuf_game.players
        names = [player.name for player in players]

        def process_player_df(game) -> List[ReplayPlayer]:
            player_data = []
            for player in names:
                data_frame[player].loc[:, rot_cs] = data_frame[player][rot_cs] / 65536.0 * 2 * 3.14159265
                data_frame[player].loc[:, 'pos_x'] = data_frame[player]['pos_x']
                data_frame[player].loc[:, 'pos_y'] = data_frame[player]['pos_y']
                data_frame[player].loc[:, 'pos_z'] = data_frame[player]['pos_z']
                player_positions = data_frame[player][cs + rot_cs + ['boost_active']].fillna(-100)
                player_data.append(player_positions.values.tolist())
            return player_data

        players_data = process_player_df(protobuf_game)
        game_frames = data_frame['game'][['delta', 'seconds_remaining', 'time']].fillna(-100)

        return ReplayPositions(
            id_=id_,
            ball=ball_df.values.tolist(),
            players=players_data,
            colors=[player.is_orange for player in players],
            names=[player.name for player in players],
            frames=game_frames.values.tolist()
        )
Example #5
0
def api_v1_get_replay_info(id_):
    proto = FileManager.get_proto(id_)

    response = Response(response=convert_proto_to_json(proto),
                        status=200,
                        mimetype='application/json')

    return response

    game = session.query(Game).filter(Game.hash == id_).first()
    data = {
        'datetime': proto.datetime,
        'map': proto.map,
        'mmrs': game.mmrs,
        'ranks': game.ranks,
        'name': proto.name,
        'hash': game.hash,
        'version': proto.replay_version,
        'id': proto.id,
        'frames': len(proto.frames)
    }
    data = player_interface(data, proto, game.mmrs, game.ranks)
    data = team_interface(data, proto)
    data = score_interface(data, proto)
    data = goals_interface(data, proto)
    return jsonify(data)
Example #6
0
def parse_replay(
        self,
        replay_to_parse_path,
        preserve_upload_date: bool = False,
        # url parameters
        query_params: Dict[str, any] = None,
        # test parameters
        force_reparse: bool = False) -> str:
    """
    :param self:
    :param replay_to_parse_path: the path to the replay that is being parsed.
    :param query_params: The arguments from the url
    :param preserve_upload_date: If true the upload date is retained
    :param force_reparse: if true parsing will happen even if a file already exists.
    :return: The replay ID
    """

    parsed_data_path = os.path.join(FileManager.get_default_parse_folder(),
                                    os.path.basename(replay_to_parse_path))

    failed_dir = os.path.join(
        os.path.dirname(FileManager.get_default_parse_folder()), 'failed')

    # Todo preparse replay ID here to save on extra parsing and on locks.  (remember to delete locks older than 1 day)
    if os.path.isfile(parsed_data_path) and not force_reparse:
        return

    analysis_manager = parse_replay_wrapper(replay_to_parse_path,
                                            parsed_data_path, failed_dir,
                                            force_reparse, logger,
                                            query_params)

    if analysis_manager is None:
        return

    # success!
    proto_game = analysis_manager.protobuf_game

    if proto_game.game_metadata.match_guid is None or proto_game.game_metadata.match_guid == '':
        proto_game.game_metadata.match_guid = proto_game.game_metadata.id

    parsed_replay_processing(proto_game,
                             query_params,
                             preserve_upload_date=preserve_upload_date)

    return save_replay(proto_game, replay_to_parse_path, parsed_data_path,
                       parsed_data_path)
Example #7
0
def download_replay(id_):
    filename = id_ + ".replay"
    path = FileManager.get_replay_path(id_)
    if os.path.isfile(path):
        return send_from_directory(current_app.config['REPLAY_DIR'], filename, as_attachment=True)
    elif config is not None and hasattr(config, 'GCP_BUCKET_URL'):
        return redirect(config.GCP_BUCKET_URL + filename)
    return "Replay not found", 404
Example #8
0
def api_v1_get_stats(session=None):
    # TODO: stats?
    ct = session.query(Game).count()
    dct = len([
        f for f in os.listdir(FileManager.get_default_parse_folder())
        if f.endswith('pts')
    ])
    return jsonify({'db_count': ct, 'count': dct})
Example #9
0
def download_replay(id_):
    filename = id_ + ".replay"
    path = FileManager.get_replay_path(id_)
    if os.path.isfile(path):
        return send_from_directory(current_app.config['REPLAY_DIR'],
                                   filename,
                                   as_attachment=True)
    return redirect(get_replay_url(id_))
 def get_protobuf_stats(self, id_: str) -> List[DatabaseObjectDataPoint]:
     game_proto = FileManager.get_proto(id_)
     players = game_proto.players
     stat_output = []
     for player in players:
         player_stats = get_proto_values(player.stats,
                                         self.soccer_player_stats)
         stat_output.append(
             DatabaseObjectDataPoint(
                 player.id.id, player.name, player.is_orange,
                 dict(zip(self.soccer_field_names, player_stats))))
     return stat_output
Example #11
0
    def create_from_id(self):
        protobuf_game = FileManager.get_proto(self.replay_id)
        kickoffs = protobuf_game.game_stats.kickoff_stats
        player_map = create_player_map(protobuf_game)
        kickoff_list = [
            self.get_stats_from_kickoff(kickoff, player_map)
            for kickoff in kickoffs
        ]

        player_list = {
            player.id.id: {
                "name": player.name,
                "is_orange": player.is_orange
            }
            for player in protobuf_game.players
        }

        kickoff_data = {"players": player_list, "kickoffs": kickoff_list}
        return kickoff_data
Example #12
0
    def get_stats_from_player(self, player, start_frame, player_name):
        if player.start_position is None or player.start_position.pos_y == 0:
            if self.pandas is None:
                self.pandas = FileManager.get_pandas(self.replay_id)
            start_x = self.pandas[player_name]['pos_x'][start_frame]
            start_y = self.pandas[player_name]['pos_y'][start_frame]
        else:
            start_x = player.start_position.pos_x
            start_y = player.start_position.pos_y

        end_x = player.player_position.pos_x
        end_y = player.player_position.pos_y

        return {
            'player_id':
            player.player.id,
            'jump_times': [jump for jump in player.jumps],
            'jumps':
            len(player.jumps),
            'boost_level':
            round((player.boost / 255.0) * 100.0, 1),
            'time_to_boost':
            round(player.boost_time, 3),
            'ball_distance':
            round(player.ball_dist, 2),
            'location':
            TouchPosition.Name(player.touch_position)
            if player.touch_position != UNKNOWN_TOUCH_POS else "UNKNOWN",
            'start': {
                'x': start_x,
                'y': start_y
            },
            'end': {
                'x': end_x,
                'y': end_y
            }
        }
Example #13
0
def api_v1_download_parsed(fn):
    return send_from_directory(FileManager.get_default_parse_folder(),
                               fn,
                               as_attachment=True)
Example #14
0
def api_v1_list_parsed_replays():
    fs = os.listdir(FileManager.get_default_parse_folder())
    return jsonify(fs)
Example #15
0
    def create_from_id(id_: str,
                       type_=HeatMapType.POSITIONING) -> 'ReplayHeatmaps':
        data_frame = FileManager.get_pandas(id_)
        protobuf_game = FileManager.get_proto(id_)
        # output = generate_heatmaps(data_frame, protobuf_game, type="hits")
        width = 400 / 500
        step = 350.0
        # x_range = 4.05*10**3
        # y_range = 5.1*10**3
        x_range = 4.05 * 10**3
        y_range = 6.1 * 10**3
        x_bins = np.arange(-x_range, x_range, step)
        y_bins = np.arange(-y_range, y_range, step)

        output = generate_heatmaps(data_frame,
                                   protobuf_game,
                                   type_=type_,
                                   bins=[x_bins, y_bins])
        data = {}
        maxs = {}
        # 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_ == HeatMapType.HITS:
            return {'data': output, 'maxs': maxs}

        if type_ in [HeatMapType.HITS]:
            log_scale = False
        else:
            log_scale = True

        for player in output:
            max_ = 0
            arr = output[player]
            player_data = []
            for x in range(len(arr[0])):
                for y in range(len(arr[0][x])):
                    if arr[0][x, y] == 0:
                        continue
                    if log_scale:
                        value = math.log(arr[0][x, y] + 1e-3)**1.8
                    else:
                        value = arr[0][x, y]
                    player_data.append({
                        'x':
                        math.floor(arr[1][x] * width * 200 / 6000 + 130),
                        'y':
                        math.floor(arr[2][y] * width * 200 / 6000 + 180),
                        'value':
                        max(0, value)
                    })
                    max_ = max(value, max_)
            data[player] = player_data
            maxs[player] = max_

        return {'data': data, 'maxs': maxs}