def test_q3_to_ql_process_user_info_twice_change_team(self): data = ( r"0.2 ClientUserinfoChanged: 2 " r"n\Bartoszer\t\3\model\xaero/default\hmodel\xaero/default" r"\c1\4\c2\5\hc\100\w\0\l\0\rt\0\st\0") data2 = ( r"0.2 ClientUserinfoChanged: 2 " r"n\Bartoszer\t\0\model\sarge/default\hmodel\xaero/default" r"\c1\4\c2\5\hc\100\w\0\l\0\rt\0\st\0") transformer = quake3.Q3toQL([]) transformer.time_offset = 0.1 transformer.server_domain = "mydomain" transformer.match_guid = 'dummy' transformer.process_raw_event(data) assert transformer.players player_info = list(transformer.players.values())[0] assert player_info['name'] == 'Bartoszer' assert player_info['model'] == r'xaero/default' events = transformer.process_raw_event(data2) assert len(events) == 1 ev = events[0] assert ev['TYPE'] == 'PLAYER_SWITCHTEAM' assert ev['DATA']['TIME'] == 0.1 assert ev['DATA']['WARMUP'] is False assert ev['DATA']['MATCH_GUID'] == 'dummy' assert ev['DATA']['KILLER']['NAME'] == 'Bartoszer' assert ev['DATA']['KILLER']['STEAM_ID'] assert ev['DATA']['KILLER']['OLD_TEAM'] == 'SPECTATOR' assert ev['DATA']['KILLER']['TEAM'] == 'FREE'
def test_q3_to_ql_process_warmup(self): data = "15.6 Warmup:" transformer = quake3.Q3toQL([]) result = transformer.result assert not result['warmup'] transformer.process_raw_event(data) assert result['warmup']
def test_q3_to_ql_process_user_info_twice_same_team(self): data = ( r"0.2 ClientUserinfoChanged: 2 " r"n\Bartoszer\t\0\model\xaero/default\hmodel\xaero/default" r"\c1\4\c2\5\hc\100\w\0\l\0\rt\0\st\0") data2 = ( r"0.2 ClientUserinfoChanged: 2 " r"n\Bartoszer\t\0\model\sarge/default\hmodel\xaero/default" r"\c1\4\c2\5\hc\100\w\0\l\0\rt\0\st\0") transformer = quake3.Q3toQL([]) transformer.time_offset = 0.1 transformer.server_domain = "mydomain" transformer.match_guid = 'dummy' transformer.process_raw_event(data) assert transformer.players player_info = list(transformer.players.values())[0] assert player_info['name'] == 'Bartoszer' assert player_info['model'] == r'xaero/default' events = transformer.process_raw_event(data2) assert events == [] assert len(transformer.players) == 1 player_info = list(transformer.players.values())[0] assert player_info['model'] == r'sarge/default'
def test_quake3_feed_preprocess(q3_dump): feeder = quake3.Q3MatchFeeder() matches = [] for line in q3_dump.splitlines(): try: feeder.feed(line) except dataprovider.FeedFull: matches.append(feeder.consume()) for match in matches: transformer = quake3.Q3toQL(match['EVENTS']) transformer.process() result = transformer.result preprocessor = dataprovider.MatchPreprocessor() preprocessor.process_events(result['events']) for ev in preprocessor.events: assert not ev['DATA'].get('WARMUP', False) assert preprocessor.match_guid assert preprocessor.events if preprocessor.finished: assert preprocessor.duration
def test_q3_to_ql_process_exit(self): transformer = quake3.Q3toQL([]) transformer.server_domain = "mydomain" transformer.match_guid = 'dummy' data = ( r'10.0 InitGame: \dmflags\0\fraglimit\200\timelimit\15' r'\sv_hostname\MY Q3\sv_maxclients\32\sv_minRate\0\sv_maxRate\0' r'\sv_dlRate\100\sv_minPing\0\sv_maxPing\0\sv_floodProtect\0' r'\sv_allowDownload\1\sv_dlURL\http://10.40.3.11:8000/\capturelimit\8' r'\version\ioq31.36+u20160616+dfsg1-1/' r'Ubuntu linux-x86_64 Jun 27 2016\com_gamename\Quake3Arena' r'\com_protocol\71\g_gametype\0\mapname\nodm9\sv_privateClients\0' r'\server_ospauth\0\gamename\osp\gameversion\OSP v1.03a' r'\Players_Active\1 2 3 4 5 6 7 8 \server_promode\0\g_needpass\0\server_freezetag\0' ) data1 = ( "15.6 ServerTime: 20170623124301 12:43:01 (23 Jun 2017)") data2 = ( r'915.6 Exit: Timelimit hit.') transformer.process_raw_event(data) assert transformer.time_offset == 10 assert transformer.match_report_event is None transformer.process_raw_event(data1) assert transformer.result['start_date'] transformer.process_raw_event(data2) ev = transformer.match_report_event assert ev assert ev['TYPE'] == 'MATCH_REPORT' assert ev['DATA']['MAP'] == 'nodm9' assert ev['DATA']['GAME_LENGTH'] == 905.6 assert ev['DATA']['GAME_TYPE'] == 'FFA' assert ev['DATA']['EXIT_MSG'] == 'Timelimit hit.' assert transformer.result['finish_date']
def test_q3_to_ql_process_user_info(self): data = ( r"0.2 ClientUserinfoChanged: 2 " r"n\Bartoszer\t\0\model\xaero/default\hmodel\xaero/default" r"\c1\4\c2\5\hc\100\w\0\l\0\rt\0\st\0") transformer = quake3.Q3toQL([]) transformer.time_offset = 0.1 transformer.server_domain = "mydomain" transformer.match_guid = 'dummy' result = transformer.process_raw_event(data) assert transformer.players player_info = list(transformer.players.values())[0] assert player_info['name'] == 'Bartoszer' assert player_info['model'] == r'xaero/default' player_id = transformer.client_player_map['2'] assert player_id assert transformer.players[player_id] is player_info ev = result[0] assert ev['TYPE'] == 'PLAYER_CONNECT' evd = ev['DATA'] assert evd['MATCH_GUID'] == 'dummy' assert evd['NAME'] == 'Bartoszer' assert evd['STEAM_ID'] assert evd['TIME'] == 0.1 assert evd['WARMUP'] is False ev = result[1] assert ev['TYPE'] == 'PLAYER_SWITCHTEAM' assert ev['DATA']['KILLER']['NAME'] == 'Bartoszer' assert ev['DATA']['KILLER']['OLD_TEAM'] == 'SPECTATOR' assert ev['DATA']['KILLER']['TEAM'] == 'FREE'
def api2_admin_rebuild(): if not auth(flask.request.form['token']): return 'Bye' data_store().prepare_for_rebuild() # TODO Server Domain is not saved data_dir = app.config['RAW_DATA_DIR'] if data_dir: for f in listdir(data_dir): with open(path.join(data_dir, f)) as fh: data = fh.read() match = { 'EVENTS': data.splitlines() } server_domain = app.config['SERVER_DOMAIN'] source_type = 'Q3' transformer = quake3.Q3toQL(match['EVENTS']) transformer.server_domain = server_domain try: transformer.process() except Exception as e: # TODO save for investigation if error logger.exception(e) continue results = transformer.result # PREPROCESS preprocessor = dataprovider.MatchPreprocessor() preprocessor.process_events(results['events']) if not preprocessor.finished: continue fmi = dataprovider.FullMatchInfo( events=preprocessor.events, match_guid=preprocessor.match_guid, duration=preprocessor.duration, start_date=results['start_date'], finish_date=results['finish_date'], server_domain=server_domain, source=source_type) analyzer = analyze.Analyzer() report = analyzer.analyze(fmi) data_store().store_analysis_report(report) data_store().post_rebuild() return 'OK' return 'No Data'
def test_q3_to_ql_ts2match_time(self): transformer = quake3.Q3toQL([]) with pytest.raises(AssertionError): transformer.ts2match_time(10) transformer.time_offset = 10 res = transformer.ts2match_time(15) assert res == 5 with pytest.raises(AssertionError): transformer.ts2match_time(5)
def api2_admin_match_import(): """ Import q3 match log previously stored in RAW_DATA_DIR The log file should contain single match events, excluding match delimiter (-----) """ if not auth(flask.request.form['token']): return 'Bye' # TODO this code should be rewritten if 'file' not in flask.request.files: raise Exception("No Files") req_file = flask.request.files['file'] data = req_file.read().decode("utf-8") match = { 'EVENTS': data.splitlines() } server_domain = app.config['SERVER_DOMAIN'] source_type = 'Q3' transformer = quake3.Q3toQL(match['EVENTS']) transformer.server_domain = server_domain try: transformer.process() except Exception as e: # TODO save for investigation if error logger.exception(e) return 'Failed' results = transformer.result # PREPROCESS preprocessor = dataprovider.MatchPreprocessor() preprocessor.process_events(results['events']) if not preprocessor.finished: return 'Match not finished' fmi = dataprovider.FullMatchInfo( events=preprocessor.events, match_guid=preprocessor.match_guid, duration=preprocessor.duration, start_date=results['start_date'], finish_date=results['finish_date'], server_domain=server_domain, source=source_type) analyzer = analyze.Analyzer() report = analyzer.analyze(fmi) data_store().store_analysis_report(report) return 'OK'
def test_q3_to_ql(self, q3_full_match): feeder = Q3MatchFeeder() matches = [] for line in q3_full_match.splitlines(): try: feeder.feed(line) except FeedFull: match = feeder.consume() matches.append(match) game = matches[-1] transformer = quake3.Q3toQL(game['EVENTS']) transformer.process()
def test_q3_to_ql_extract(self): data = "15.6 ServerTime: 20170623124300 12:43:00 (23 Jun 2017)" transformer = quake3.Q3toQL([]) ts, name, args = transformer.extract(data) assert ts == 15.6 assert name == "ServerTime" assert args == "20170623124300 12:43:00 (23 Jun 2017)" data = "15.7 Game End:" ts, name, args = transformer.extract(data) assert ts == 15.7 assert name == "Game End" assert args == ""
def test_q3_to_ql_player_disconnected(self): data1 = (r"0.2 ClientUserinfoChanged: 1 " r"n\Bartoszer\t\3\model\xaero/default\hmodel\xaero/default" r"\c1\4\c2\5\hc\100\w\0\l\0\rt\0\st\0") data2 = (r'712.9 ClientDisconnect: 1') transformer = quake3.Q3toQL([]) transformer.time_offset = 0.1 transformer.server_domain = "mydomain" transformer.match_guid = 'dummy' transformer.process_raw_event(data1) ev = transformer.process_raw_event(data2) assert ev assert ev['TYPE'] == 'PLAYER_DISCONNECT' assert ev['DATA']['NAME'] == 'Bartoszer' assert ev['DATA']['STEAM_ID'] assert ev['DATA']['TIME'] == 712.8 assert ev['DATA']['WARMUP'] is False assert ev['DATA']['MATCH_GUID'] == 'dummy'
def test_q3_to_ql_process_client_info_changed_same_nick(self): # This test is not incorrect at the moment # multiple clients may be present the same, # unique id is assigned during connection and # changed later data = (r"0.2 ClientUserinfoChanged: 2 " r"n\Bartoszer\t\3\model\xaero/default\hmodel\xaero/default" r"\c1\4\c2\5\hc\100\w\0\l\0\rt\0\st\0") data2 = (r"0.2 ClientUserinfoChanged: 3 " r"n\Bartoszer\t\0\model\sarge/default\hmodel\xaero/default" r"\c1\4\c2\5\hc\100\w\0\l\0\rt\0\st\0") transformer = quake3.Q3toQL([]) transformer.time_offset = 0.1 transformer.server_domain = "mydomain" transformer.match_guid = 'dummy' transformer.process_raw_event(data) with pytest.raises(AssertionError): transformer.process_raw_event(data2)
def test_q3_to_ql_process_kill(self): data = ( r"0.2 ClientUserinfoChanged: 2 " r"n\Bartoszer\t\3\model\xaero/default\hmodel\xaero/default" r"\c1\4\c2\5\hc\100\w\0\l\0\rt\0\st\0") data2 = ( r"0.2 ClientUserinfoChanged: 3 " r"n\Bolek\t\0\model\sarge/default\hmodel\xaero/default" r"\c1\4\c2\5\hc\100\w\0\l\0\rt\0\st\0") data3 = ( r"884.3 Kill: 2 3 7: Bartoszer killed Bolek by MOD_ROCKET_SPLASH 5") transformer = quake3.Q3toQL([]) transformer.time_offset = 0.1 transformer.server_domain = "mydomain" transformer.match_guid = 'dummy' transformer.process_raw_event(data) transformer.process_raw_event(data2) events = transformer.process_raw_event(data3) ev = events[0] assert ev['TYPE'] == 'PLAYER_KILL' assert ev['DATA']['MATCH_GUID'] == 'dummy' assert ev['DATA']['MOD'] == 'ROCKET_SPLASH' assert int(ev['DATA']['TIME']) == 884 assert ev['DATA']['KILLER']['NAME'] == 'Bartoszer' assert ev['DATA']['KILLER']['STEAM_ID'] assert ev['DATA']['KILLER']['TEAM'] == '3' assert ev['DATA']['VICTIM']['NAME'] == 'Bolek' assert ev['DATA']['VICTIM']['STEAM_ID'] assert ev['DATA']['VICTIM']['TEAM'] == '0' evd = events[1] assert evd['TYPE'] == 'PLAYER_DEATH' assert evd['DATA'] == ev['DATA']
def test_q3_to_ql_process_server_time(self): data = "15.6 ServerTime: 20170623124301 12:43:01 (23 Jun 2017)" transformer = quake3.Q3toQL([]) si = transformer.result['server_info'] si['gametype'] = 'FFA' si['timelimit'] = 15 si['fraglimit'] = 200 si['capturelimit'] = 8 si['mapname'] = 'q3dm6' si['sv_hostname'] = 'MyServ' event = transformer.process_raw_event(data) result = transformer.result assert result['start_date'] == datetime.datetime(2017, 6, 23, 12, 43, 1) assert event['TYPE'] == 'MATCH_STARTED' evd = event['DATA'] assert evd['GAME_TYPE'] == 'FFA' assert evd['TIME_LIMIT'] == 15 assert evd['FRAG_LIMIT'] == 200 assert evd['CAPTURE_LIMIT'] == 8 assert evd['MAP'] == 'q3dm6' assert evd['SERVER_TITLE'] == 'MyServ'
def test_quake3_analyze(q3_dump): feeder = quake3.Q3MatchFeeder() matches = [] for line in q3_dump.splitlines(): try: feeder.feed(line) except dataprovider.FeedFull: matches.append(feeder.consume()) for match in matches[-1:]: transformer = quake3.Q3toQL(match['EVENTS']) transformer.process() result = transformer.result preprocessor = dataprovider.MatchPreprocessor() preprocessor.process_events(result['events']) if not preprocessor.finished: continue fmi = dataprovider.FullMatchInfo.from_preprocessor( preprocessor, transformer.result['start_date'], transformer.result['finish_date'], 'serv-domain', 'Q3') analyzer = analyze.Analyzer() result = analyzer.analyze(fmi) assert result.match_metadata.duration == 900 assert result.match_metadata.frag_limit == 200 assert result.match_metadata.map_name == 'nodm9' assert result.match_metadata.match_guid assert result.match_metadata.server_domain == 'serv-domain' assert result.match_metadata.server_name == 'MY Q3' assert result.match_metadata.time_limit == 15 assert result.final_scores['291b0ba5fdf78b268369a9d7'][0] == 0 assert result.final_scores['6a018beb6405ef59ce1471b0'][0] == 27 assert result.final_scores['7ee3d47a164c6544ea50fee6'][0] == 37 assert result.final_scores['88fdc96e8804eaa084d740f8'][0] == 33 assert result.final_scores['9ac5682eefa9134bbfe3c481'][0] == 42 assert result.final_scores['a126a35a25eab0623f504183'][0] == 41 assert result.final_scores['d37928942982cc79e7e0fe12'][0] == 85 assert result.final_scores['e0fbefd04b9203526e6f22b8'][0] == 45 assert result.final_scores['q3-world'][0] == 16 assert len(result.team_switches) == 10 assert result.team_switches[-1] == (697.3, '291b0ba5fdf78b268369a9d7', None, 'DISCONNECTED') assert result.players[ '291b0ba5fdf78b268369a9d7'].name == 'Turbo Wpierdol' assert result.players['6a018beb6405ef59ce1471b0'].name == 'MACIEK' assert result.players['7ee3d47a164c6544ea50fee6'].name == 'n0npax' assert result.players['88fdc96e8804eaa084d740f8'].name == 'darkside' assert result.players['9ac5682eefa9134bbfe3c481'].name == 'BOLEK' assert result.players[ 'a126a35a25eab0623f504183'].name == 'killer clown' assert result.players['d37928942982cc79e7e0fe12'].name == 'Bartoszer' assert result.players['e0fbefd04b9203526e6f22b8'].name == 'Stefan' assert result.kills[-1] == (897.1, 'd37928942982cc79e7e0fe12', 'd37928942982cc79e7e0fe12', 'ROCKET_SPLASH') assert result.server_info.server_name == 'MY Q3' assert result.server_info.server_domain == 'serv-domain' assert result.server_info.server_type == 'Q3' assert result.special_scores['GAUNTLET_KILL'][3] == ( 150.4, 'd37928942982cc79e7e0fe12', 'e0fbefd04b9203526e6f22b8', 1) assert result.special_scores['KILLING_SPREE'][2] == ( 64.9, 'd37928942982cc79e7e0fe12', '9ac5682eefa9134bbfe3c481', 1)
feeder = quake3.Q3MatchFeeder() raw_matches = [] for line in data.splitlines(): try: feeder.feed(line) except quake3.FeedFull: raw_matches.append(feeder.consume()) feeder.feed(line) raw_matches.append(feeder.consume()) final_results = [] for match in raw_matches: transformer = quake3.Q3toQL(match['EVENTS']) transformer.server_domain = SERVER_DOMAIN try: transformer.process() except Exception as e: print(e) continue results = transformer.result # PREPROCESS preprocessor = dataprovider.MatchPreprocessor() preprocessor.process_events(results['events']) if not preprocessor.finished:
def api2_upload(): if not auth(flask.request.form['token']): return 'Bye' # TODO this code should be rewritten if 'file' not in flask.request.files: raise Exception("No Files") req_file = flask.request.files['file'] data = req_file.read().decode("utf-8") server_domain = app.config['SERVER_DOMAIN'] source_type = 'Q3' feeder = quake3.Q3MatchFeeder() matches = [] for line in data.splitlines(): try: feeder.feed(line) except quake3.FeedFull: matches.append(feeder.consume()) feeder.feed(line) final_results = [] errors = 0 for match in matches: # TRANSFORM TO QL transformer = quake3.Q3toQL(match['EVENTS']) transformer.server_domain = server_domain try: transformer.process() except Exception as e: # TODO save for investigation if error errors += 1 logger.exception(e) continue results = transformer.result # PREPROCESS preprocessor = dataprovider.MatchPreprocessor() preprocessor.process_events(results['events']) if not preprocessor.finished: continue if app.config['RAW_DATA_DIR']: base = app.config['RAW_DATA_DIR'] preprocessor.match_guid p = path.join(base, "{}.log".format(preprocessor.match_guid)) with open(p, 'w') as fh: for line in match['EVENTS']: fh.write(line) fh.write('\n') final_results.append(dataprovider.FullMatchInfo( events=preprocessor.events, match_guid=preprocessor.match_guid, duration=preprocessor.duration, start_date=results['start_date'], finish_date=results['finish_date'], server_domain=server_domain, source=source_type)) fmi = final_results[-1] analyzer = analyze.Analyzer() report = analyzer.analyze(fmi) data_store().store_analysis_report(report) return flask.jsonify({ "ACCEPTED_MATCHES": [ r.get_summary() for r in final_results], "ERRORS": errors })