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_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_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_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_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_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_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 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_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_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 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 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 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 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 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)