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
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() )
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)
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)
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
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})
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
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
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 } }
def api_v1_download_parsed(fn): return send_from_directory(FileManager.get_default_parse_folder(), fn, as_attachment=True)
def api_v1_list_parsed_replays(): fs = os.listdir(FileManager.get_default_parse_folder()) return jsonify(fs)
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}