def test_debug_bits_with_labels(self): parser = ReplayParser() data = StringIO() data.write(u'\u0001') data.seek(0) stdout = sys.stdout sys.stdout = StringIO() bits = parser._debug_bits(data, ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']) output = sys.stdout.getvalue() sys.stdout.close() sys.stdout = stdout self.assertEqual( output, """1....... = A: Not set .0...... = B: Not set ..0..... = C: Not set ...0.... = D: Not set ....0... = E: Not set .....0.. = F: Not set ......0. = G: Not set .......0 = H: Not set """) self.assertEqual(bits, (1, 0, 0, 0, 0, 0, 0, 0))
def test_debug_bits_with_labels(self): parser = ReplayParser() data = StringIO() data.write(u'\u0001') data.seek(0) stdout = sys.stdout sys.stdout = StringIO() bits = parser._debug_bits(data, ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']) output = sys.stdout.getvalue() sys.stdout.close() sys.stdout = stdout self.assertEqual(output, """1....... = A: Not set .0...... = B: Not set ..0..... = C: Not set ...0.... = D: Not set ....0... = E: Not set .....0.. = F: Not set ......0. = G: Not set .......0 = H: Not set """) self.assertEqual(bits, (1, 0, 0, 0, 0, 0, 0, 0))
def test_file_str(self): parser = ReplayParser(debug=True) response = parser.parse(self.folder_path + '2s.replay') self.assertIsInstance(response, dict) self.assertEqual(response['header']['Id'], '016D2CB946676AFDC11D29BFD84C9CB3')
def test_debug_bits(self): parser = ReplayParser() data = StringIO() data.write(u'\u0001') data.seek(0) stdout = sys.stdout sys.stdout = StringIO() bits = parser._debug_bits(data) output = sys.stdout.getvalue() sys.stdout.close() sys.stdout = stdout self.assertEqual( output, """1....... .0...... ..0..... ...0.... ....0... .....0.. ......0. .......0 """) self.assertEqual(bits, (1, 0, 0, 0, 0, 0, 0, 0))
def test_debug_bits(self): parser = ReplayParser() data = StringIO() data.write(u'\u0001') data.seek(0) stdout = sys.stdout sys.stdout = StringIO() bits = parser._debug_bits(data) output = sys.stdout.getvalue() sys.stdout.close() sys.stdout = stdout self.assertEqual(output, """1....... .0...... ..0..... ...0.... ....0... .....0.. ......0. .......0 """) self.assertEqual(bits, (1, 0, 0, 0, 0, 0, 0, 0))
def test_read_name_table(self): parser = ReplayParser() # Passing some unusual data into this function will cause it to throw # an exception. with open(self.folder_path + '2s.replay', 'rb') as f: with self.assertRaises(Exception): parser._read_name_table(f)
def test_read_bit(self): parser = ReplayParser() self.assertEqual(parser._read_bit(u'\u0001', 0), 1) self.assertEqual(parser._read_bit(u'\u0001', 1), 0) self.assertEqual(parser._read_bit(u'\u0001', 2), 0) self.assertEqual(parser._read_bit(u'\u0001', 3), 0) self.assertEqual(parser._read_bit(u'\u0001', 4), 0) self.assertEqual(parser._read_bit(u'\u0001', 5), 0) self.assertEqual(parser._read_bit(u'\u0001', 6), 0) self.assertEqual(parser._read_bit(u'\u0001', 7), 0)
def test_limited_action_replay(self): """ This is a very simple replay which doesn't have much action taking place. """ parser = ReplayParser() with open(self.folder_path + 'limited_action.replay', 'rb') as f: response = parser.parse(f) self.assertIsInstance(response, dict) self.assertEqual(response['header']['Id'], 'C6ADF673457FE9B7B2A82DAB36E8FF86')
def test_broken_replay(self): """ This replay file was purposefully broken by deleting a large portion of the data. """ parser = ReplayParser() with open(self.folder_path + 'broken.replay', 'rb') as f: with self.assertRaises(struct.error): parser.parse(f)
def test_score_wrong_replay(self): """ This is a very replay which has some weird goal header data. """ parser = ReplayParser() with open(self.folder_path + 'score_wrong.replay', 'rb') as f: response = parser.parse(f) self.assertIsInstance(response, dict) self.assertEqual(response['header']['Id'], 'B76567B84633D0D9CD8D4597DB0CAB30')
def test_106_replay(self): """ A replay from version 1.05. """ parser = ReplayParser() with open(self.folder_path + '1.06.replay', 'rb') as f: response = parser.parse(f) self.assertIsInstance(response, dict) self.assertEqual(response['header']['Id'], 'E64C704042DFFF5E92F76EB9217B6422') self.assertIn('PlayerStats', response['header'])
def test_106_2_replay(self): """ A replay from version 1.05, with bots. """ parser = ReplayParser() with open(self.folder_path + '1.06_2.replay', 'rb') as f: response = parser.parse(f) self.assertIsInstance(response, dict) self.assertEqual(response['header']['Id'], 'BBA60356493A53E6D4D7ADBA4E5D99B9') self.assertIn('PlayerStats', response['header'])
def main(): global args parse_input_args() with Ow(sys.stderr) as ow, Pc( 'cache.csv', ['nickname', 'id', 'global_rating']) as cache: rp = Rp(args.dirs, ow) a = API(args.key, ow) replays = rp.read_replays() cache_players(replays, cache, a) tank_info = a.tank_tiers() if args.weighted else None team_ratings = team_average_ratings(replays, cache, tank_info) outputs(replays, team_ratings, cache)
def test_104_replay(self): """ A replay from version 1.04. """ parser = ReplayParser() with open(self.folder_path + '1.04.replay', 'rb') as f: response = parser.parse(f) self.assertIsInstance(response, dict) self.assertEqual(response['header']['Id'], '0AB18BAB4CCE97201B7753A84B358D48') self.assertNotIn('PlayerStats', response['header'])
def test_105_replay(self): """ A replay from version 1.05. """ parser = ReplayParser() with open(self.folder_path + '1.05.replay', 'rb') as f: response = parser.parse(f) self.assertIsInstance(response, dict) self.assertEqual(response['header']['Id'], '56E7708C45ED1CF3B9E51EBF1ADF4431') self.assertNotIn('PlayerStats', response['header'])
def test_file_attr(self): class Obj: class File: path = self.folder_path + '2s.replay' file = File() parser = ReplayParser() response = parser.parse(Obj()) self.assertIsInstance(response, dict) self.assertEqual(response['header']['Id'], '016D2CB946676AFDC11D29BFD84C9CB3')
def test_keyframes_missing_replay(self): """ For some reason, this replay is missing the key frames from when goals were scored, so that data is not available to a parser. This is a good test to ensure the parser can handle odd scenarios. """ parser = ReplayParser() with open(self.folder_path + 'keyframes_missing.replay', 'rb') as f: response = parser.parse(f) self.assertIsInstance(response, dict) self.assertEqual(response['header']['Id'], '50D5031342FF90D9F25BE5A0152E56B8')
def test_2s_replay(self): """ This is the shortest possible replay, at only 2 seconds long. It was created by loading in to a split-screen 2v2 ranked match and forfeiting as soon as the action was available. """ parser = ReplayParser() with open(self.folder_path + '2s.replay', 'rb') as f: response = parser.parse(f) self.assertIsInstance(response, dict) self.assertEqual(response['header']['Id'], '016D2CB946676AFDC11D29BFD84C9CB3')
def main(): global args, logfile parse_input_args() if args.save_img: logfile = open(f'{args.output_name}.log', 'w', encoding='utf8') with Ow(sys.stderr) as ow, Pc( 'cache.csv', ['nickname', 'id', 'global_rating']) as cache: rp = Rp(args.dirs, ow) a = API(args.key, ow, args.region) replays = rp.read_replays(args.filter_platoons) cache_players(replays, cache, a) team_ratings = team_average_ratings(replays, cache) outputs(replays, team_ratings, cache) if logfile: logfile.close()
def main(): global args, logfile parse_input_args() if args.save_img: logfile = open(f'{args.save_img}.log', 'w', encoding='utf8') with Ow(sys.stderr) as ow, Pc( 'cache.csv', ['nickname', 'id', 'global_rating']) as cache: rp = Rp(args.dirs, ow) a = API(args.key, ow) replays = rp.read_replays() cache_players(replays, cache, a) tank_info = None # = a.tank_tiers() if args.weighted else None team_ratings = team_average_ratings(replays, cache, tank_info) outputs(replays, team_ratings, cache) if logfile: logfile.close()
def main(): if not len(sys.argv) > 1: print('need a dir name') exit() with Ow(sys.stderr) as ow: rp = Rp(sys.argv[1:], ow) lengths = [] replays = rp.read_replays() for replay in replays: length = replay.get('ext', [{}])[0].get('common', {}).get('duration') if length: lengths.append(length) average_length = mean(lengths) minutes = int(average_length / 60) seconds = str(int(average_length % 60)).rjust(2, '0') print(f'\n{len(lengths)} replays:') print(f'average duration: {minutes}:{seconds}')
def test_sniff_bytes_3_bytes(self): parser = ReplayParser() data = StringIO() data.write('\x31\x32\x33') stdout = sys.stdout sys.stdout = StringIO() data.seek(0) parser._sniff_bytes(data, 3) output = sys.stdout.getvalue() sys.stdout.close() sys.stdout = stdout self.assertEqual(output, """**** BYTES **** Bytes: 31 32 33 ('Size:', 3) String: 123 """)
def test_sniff_bytes_2_bytes(self): parser = ReplayParser() data = StringIO() data.write('\x31\x32') stdout = sys.stdout sys.stdout = StringIO() data.seek(0) parser._sniff_bytes(data, 2) output = sys.stdout.getvalue() sys.stdout.close() sys.stdout = stdout self.assertEqual(output, """**** BYTES **** Bytes: 31 32 ('Size:', 2) Short: Signed: (12849,) Unsigned: (12849,) """)
def test_sniff_bytes_0_bytes(self): parser = ReplayParser() data = StringIO() data.write('') stdout = sys.stdout sys.stdout = StringIO() data.seek(0) parser._sniff_bytes(data, 0) output = sys.stdout.getvalue() sys.stdout.close() sys.stdout = stdout self.assertEqual(output, """**** BYTES **** Bytes: \n\ ('Size:', 0) String: \n\ """)
def main(): global args, logfile parse_input_args() with Ow(sys.stderr) as ow: rp = Rp(args.dirs, ow) replays = rp.read_replays() p = {'ally': {}, 'enemy': {}} print('sorting players') for battle in replays: replay_team = None teams = [[], []] std = battle.get('std') for player in std.get('vehicles').values(): name = player.get('name') team_num = player.get('team') - 1 # 1-indexed -> 0-indexed if name == std.get('playerName'): # note player's team and don't store them replay_team = team_num else: teams[team_num].append(name) if replay_team: #friendly team for name in teams[replay_team]: allies = p.get('ally') allies[name] = allies.get(name, 0) + 1 #enemy team for name in teams[1 - replay_team]: enemies = p.get('enemy') enemies[name] = enemies.get(name, 0) + 1 with open(args.output_name, 'w') as outfile: outfile.write(',Name,count\n') outfile.write('Ally') for player, count in p.get('ally').items(): outfile.write(f',{player},{count}\n') outfile.write('Enemy') for player, count in p.get('enemy').items(): outfile.write(f',{player},{count}\n')
def test_sniff_bytes_2_bytes(self): parser = ReplayParser() data = StringIO() data.write('\x31\x32') stdout = sys.stdout sys.stdout = StringIO() data.seek(0) parser._sniff_bytes(data, 2) output = sys.stdout.getvalue() sys.stdout.close() sys.stdout = stdout self.assertEqual( output, """**** BYTES **** Bytes: 31 32 ('Size:', 2) Short: Signed: (12849,) Unsigned: (12849,) """)
def test_sniff_bytes_3_bytes(self): parser = ReplayParser() data = StringIO() data.write('\x31\x32\x33') stdout = sys.stdout sys.stdout = StringIO() data.seek(0) parser._sniff_bytes(data, 3) output = sys.stdout.getvalue() sys.stdout.close() sys.stdout = stdout self.assertEqual( output, """**** BYTES **** Bytes: 31 32 33 ('Size:', 3) String: 123 """)
def test_read_integer(self): parser = ReplayParser() data = StringIO() data.write('\x01\x02\x03\x04\x05\x06\x07\x08') # Signed integers. data.seek(0) response = parser._read_integer(data, 1) self.assertEqual(response, 1) data.seek(0) response = parser._read_integer(data, 2) self.assertEqual(response, 513) data.seek(0) response = parser._read_integer(data, 4) self.assertEqual(response, 67305985) data.seek(0) response = parser._read_integer(data, 8) self.assertEqual(response, 578437695752307201)
def clean(self): if self.pk: return if self.file: # Process the file. parser = ReplayParser() try: replay_data = parser.parse(self.file)['header'] # Check if this replay has already been uploaded. replay = Replay.objects.filter( replay_id=replay_data['Id'] ) if replay.count() > 0: raise ValidationError(mark_safe("This replay has already been uploaded, <a href='{}'>you can view it here</a>.".format( replay[0].get_absolute_url() ))) except struct.error: raise ValidationError("The file you selected does not seem to be a valid replay file.")
def test_sniff_bytes_0_bytes(self): parser = ReplayParser() data = StringIO() data.write('') stdout = sys.stdout sys.stdout = StringIO() data.seek(0) parser._sniff_bytes(data, 0) output = sys.stdout.getvalue() sys.stdout.close() sys.stdout = stdout self.assertEqual( output, """**** BYTES **** Bytes: \n\ ('Size:', 0) String: \n\ """)
def clean(self): if self.pk: return if self.file: # Process the file. parser = ReplayParser() try: replay_data = parser.parse(self.file)['header'] # Check if this replay has already been uploaded. replay = Replay.objects.filter(replay_id=replay_data['Id']) if replay.count() > 0: raise ValidationError( mark_safe( "This replay has already been uploaded, <a href='{}'>you can view it here</a>." .format(replay[0].get_absolute_url()))) except struct.error: raise ValidationError( "The file you selected does not seem to be a valid replay file." )
def test_sniff_bytes_4_bytes(self): parser = ReplayParser() data = StringIO() data.write('\x31\x32\x33\x34') stdout = sys.stdout sys.stdout = StringIO() data.seek(0) parser._sniff_bytes(data, 4) output = sys.stdout.getvalue() sys.stdout.close() sys.stdout = stdout self.assertEqual(output, """**** BYTES **** Bytes: 31 32 33 34 ('Size:', 4) Integer: Signed: (875770417,), Unsigned: (875770417,) Float: (1.6688933612840628e-07,) String: 1234 """)
def test_sniff_bytes_4_bytes(self): parser = ReplayParser() data = StringIO() data.write('\x31\x32\x33\x34') stdout = sys.stdout sys.stdout = StringIO() data.seek(0) parser._sniff_bytes(data, 4) output = sys.stdout.getvalue() sys.stdout.close() sys.stdout = stdout self.assertEqual( output, """**** BYTES **** Bytes: 31 32 33 34 ('Size:', 4) Integer: Signed: (875770417,), Unsigned: (875770417,) Float: (1.6688933612840628e-07,) String: 1234 """)
'DATABASE_ID', 'NAME', 'GOLD', 'REPLAY' ]) f = open('corsairs.csv', 'wb') print Player._fields w = csv.DictWriter(f, Player._fields, delimiter=';') w.writeheader() for i, file in enumerate(listdir(BASE_DIR)): print file players = {} replayInfo = ReplayParser(path.join(BASE_DIR, file), False).get_info()['hidden'] if replayInfo is None: print 'UNKNOWN result' continue winnerTeamId = replayInfo['battle_result']['winner_team_id'] for player in replayInfo['players'].itervalues(): vehicleId = player['shipId'] players[vehicleId] = Player( DATABASE_ID=player['accountDBID'], NAME=player['name'], GOLD=300 if player['teamId'] == winnerTeamId else 0, REPLAY=file )
xy = array(values, dtype=dtype) key_frames = [] prev_key_value = 0 for frame in frames: key_value = frame[3] if not key_value == prev_key_value: prev_key_value = key_value new_data = array([(frame[0], frame[1], frame[2])], dtype=dtype) xy = append(xy, new_data, 0) key_array = parse_keys(key_value, keys) key_frames.append([frame[0], key_array]) xy = sort(xy, order='time') return xy, key_frames if __name__ == '__main__': # Test select from multiple from replay_parser import ReplayParser import os import psutil import cProfile replay = ReplayParser("Cynesta_-_S3RL_feat_Mixie_Moon_-_FriendZoned_Slayeds_Insane_2020-04-21_Osu.osr") frames, times = replay.get_frames() replay.dump_frames("whitecat_frames.txt") #xy_pos, key_frames = preprocess_frames(frames, {'left': 'F', 'right': 'G', 'smoke': 'D'})
def test_parse_replay(self, replay_path): parser = ReplayParser(replay_path, strict=True) result = parser.get_info() self.assertNotEqual(None, result['hidden']) self.assertEqual(None, result['error'])
import sys import json from replay_parser import ReplayParser from utils import OverWriter if len(sys.argv) < 3: print('Please provide an input directory and output filename') exit() out_file_name = f'{sys.argv[2]}.ppr' with OverWriter() as ow: replays = ReplayParser([sys.argv[1]], ow).read_replays() print(f'{len(replays)} read. Saving as {out_file_name}.') with open(out_file_name, 'w') as outfile: json.dump(replays, outfile)
def test_pretty_byte_string(self): parser = ReplayParser() response = parser._pretty_byte_string(u'\u0000\u0001\u0002\u0003') self.assertEqual(response, '00 01 02 03')
def save(self, *args, **kwargs): super(Replay, self).save(*args, **kwargs) # Server name if self.file and not self.processed: # Process the file. parser = ReplayParser() data = parser.parse(self.file)['header'] Goal.objects.filter( replay=self, frame__isnull=True, ).delete() Player.objects.filter( replay=self, ).delete() # If we have a stats table, pull in the data. if 'PlayerStats' in data: # We can show a leaderboard! self.show_leaderboard = True for player in data['PlayerStats']: """ { 'OnlineID': 0, 'Name': 'Swabbie', 'Saves': 0, 'Platform': { 'OnlinePlatform': 'OnlinePlatform_Unknown' }, 'Score': 115, 'Goals': 1, 'Shots': 1, 'Team': 1, 'bBot': True, 'Assists': 0 } """ Player.objects.get_or_create( replay=self, player_name=player['Name'].decode(chardet.detect(player['Name'])['encoding']), platform=player['Platform'].get('OnlinePlatform', ''), saves=player['Saves'], score=player['Score'], goals=player['Goals'], shots=player['Shots'], team=player['Team'], assists=player['Assists'], bot=player['bBot'], online_id=player['OnlineID'], ) for index, goal in enumerate(data['Goals']): player, created = Player.objects.get_or_create( replay=self, player_name=goal['PlayerName'].decode(chardet.detect(goal['PlayerName'])['encoding']), team=goal['PlayerTeam'], ) Goal.objects.get_or_create( replay=self, number=index + 1, player=player, frame=goal['frame'], ) data['PlayerName'] = data['PlayerName'].decode( chardet.detect(data['PlayerName'])['encoding'] ) player, created = Player.objects.get_or_create( replay=self, player_name=data['PlayerName'], team=data.get('PrimaryPlayerTeam', 0), ) self.replay_id = data['Id'] self.player_name = data['PlayerName'] self.player_team = data.get('PrimaryPlayerTeam', 0) map_obj, created = Map.objects.get_or_create( slug=data['MapName'].lower(), ) self.map = map_obj self.timestamp = datetime.fromtimestamp( time.mktime( time.strptime( data['Date'], '%Y-%m-%d:%H-%M' ) ) ) self.team_sizes = data['TeamSize'] self.team_0_score = data.get('Team0Score', 0) self.team_1_score = data.get('Team1Score', 0) self.match_type = data['MatchType'] self.server_name = data.get('ServerName', '') # Parser V2 values self.keyframe_delay = data['KeyframeDelay'] self.max_channels = data['MaxChannels'] self.max_replay_size_mb = data['MaxReplaySizeMB'] self.num_frames = data['NumFrames'] self.record_fps = data['RecordFPS'] self.excitement_factor = self.calculate_excitement_factor() self.processed = True self.save()
def test_file_exception(self): parser = ReplayParser() with self.assertRaises(TypeError): parser.parse(None)