コード例 #1
0
ファイル: test_demofile.py プロジェクト: themsoum7/demoparser
def test_parse_invalid_command():
    # Demo files have a 1072 byte header that isn't needed here
    data = b'HL2DEMO\x00' + bytes([0] * 1064)
    header = CommandHeader()
    header.player = 1
    header.tick = 1
    header.command = 99

    df = DemoFile(data + header.pack())
    with pytest.raises(CommandError) as exc:
        df.parse()

    assert 'Unrecognized command' in str(exc.value)
コード例 #2
0
    def __init__(self, game_id, data):
        self.current_frame = 0
        print("Loading game", game_id)
        # TODO: Use game_id to determine file

        #Extract DEM file data
        d = DemoFile(data)

        current_round = 0
        round_active = False

        # Internal state classes used by the parser! CAREFUL HERE :O
        s_players = []

        #Callback Functions
        def tick_start(msg):
            #If first round has not begun yet, return
            if not round_active:
                return

            # print(msg) # Updates every 8 ticks?

            # Save from their player state to ours
            for o_pl, th_pl in zip(self.m_rounds[-1].players, s_players):
                spotted = th_pl.get_prop('DT_BaseEntity', 'm_bSpotted')

                pos = int(th_pl.position['x']), int(th_pl.position['y'])
                o_pl.add_position(pos, spotted)

        def round_start(msg, msg1):
            nonlocal round_active
            nonlocal s_players

            round_active = True

            print("Round ", current_round)

            #If previous round never ended with a round_end event, it was probably not a real round
            if self.m_rounds and self.m_rounds[-1].m_rid == current_round:
                del self.m_rounds[-1]
            self.m_rounds.append(Round(current_round))

            #In professional matches, there are sometimes players that have no team or are spectators
            #Store refrences to the internal state of the parser, so we can grab em again later.
            s_players = [
                p for p in d.entities.players
                if p.team and p.team.name != 'Spectator'
            ]

            s_players = sorted(s_players, key=lambda p: p.team.name)

            # Generate our players
            players = [Person(p.name, p.team.name) for p in s_players]
            # And add to round
            self.m_rounds[-1].players = players

        def round_end(event, msg):
            nonlocal current_round
            nonlocal round_active

            round_active = False
            current_round += 1

        def death(event, msg):
            for idx, key in enumerate(event['event'].keys):
                if key.name == 'userid':
                    user_id = msg.keys[idx].val_short
                    victim = d.entities.get_by_user_id(user_id)

            if victim and round_active:
                # Find player index
                for p in self.m_rounds[-1].players:
                    if p.m_name == victim.name:
                        pos = int(victim.position['x']), int(
                            victim.position['y'])
                        p.die(pos)

        #Add callback events (calls function whenever event occurs in file)
        d.add_callback('tick_start', tick_start)
        d.add_callback('round_start', round_start)
        d.add_callback('round_end', round_end)
        d.add_callback('player_death', death)

        #create list of rounds
        self.m_rounds = []

        #Begin parseing file (may take a while)
        d.parse()

        #Close file
        print("Finished loading game!")
コード例 #3
0
num_dashes = 20


def seperate(n=num_dashes):
    for count in range(n):
        print('-', end='')
    print()


#Open and parse .dem file
filename = input('Filename(default=\'match.dem\'): ')
if filename == '':
    filename = 'match.dem'
print(f'opening \'{filename}\' as DemoFile \'df\'')
data = open(filename, 'rb').read()
df = DemoFile(data)
print('done reading')
print('parsing \'df\'...')
df.parse()
print('finished')
seperate()
print()

players = dict()
for player in df.entities.players:
    teamname = df.entities.teams[player.team_num].clan
    if teamname == '':
        continue
    if teamname not in players:
        players[teamname] = [player]
    else:
コード例 #4
0
def get_coordinates():
    def m_start(event, msg):
        result.append("Match start")

    def r_start(event, msg):
        for idx, key in enumerate(event['event'].keys):
            if key.name == 'objective':
                objective = msg.keys[idx].val_string

        result.append([objective])

    def r_end(event, msg):
        for idx, key in enumerate(event['event'].keys):
            if key.name == 'winner':
                winner = msg.keys[idx].val_byte
            elif key.name == 'reason':
                reason = msg.keys[idx].val_byte
            elif key.name == 'legacy':
                legacy = msg.keys[idx].val_byte
            elif key.name == 'message':
                message = msg.keys[idx].val_string
            elif key.name == 'player_count':
                player_count = msg.keys[idx].val_short

        result.append([message])

    def death(event, msg):
        for idx, key in enumerate(event['event'].keys):
            if key.name == 'attacker':
                user_id = msg.keys[idx].val_short
                attacker = d.entities.get_by_user_id(user_id)
            elif key.name == 'userid':
                user_id = msg.keys[idx].val_short
                victim = d.entities.get_by_user_id(user_id)
            elif key.name == 'weapon':
                weapon = msg.keys[idx].val_string
            elif key.name == 'headshot':
                headshot = msg.keys[idx].val_bool

        if attacker and victim:
            result.append([attacker.position, victim.position])

    def remove_warmup(res_list):
        match_start_idx = len(res_list) - 1 - res_list[::-1].index(
            "Match start")
        new_res_list = res_list[match_start_idx:]
        return new_res_list

    def create_final_res(res_lst):
        new_result = remove_warmup(res_lst)
        res_with_round_num = define_round_num(new_result)
        res_no_trash = remove_trash(res_with_round_num)

        return res_no_trash

    def define_round_num(new_res_list):
        counter = 1
        for i in range(len(new_res_list)):
            if new_res_list[i] in ct_round_end_msgs:
                new_res_list[i] = [{
                    "Round msg": new_res_list[i][0],
                    "round num": counter,
                    "winner team": "CTs win"
                }]
                counter += 1
            elif new_res_list[i] in t_round_end_msgs:
                new_res_list[i] = [{
                    "Round msg": new_res_list[i][0],
                    "round num": counter,
                    "winner team": "Ts win"
                }]
                counter += 1

        return new_res_list

    def remove_trash(new_res_list):
        for el in new_res_list:
            if el == "Match start" or el == ['BOMB TARGET']:
                new_res_list.pop(new_res_list.index(el))
        return new_res_list

    def create_lists(new_res_list, att_list, vic_list, r_list, wnr_list,
                     tms_list, cts_lvl_list, ts_lvl_list):
        round_counter = 1
        kill_counter = 0
        kills_counter = []
        final_winner_list = []
        final_team_list = []
        idx = 0
        rnd_cntr = 1
        team_one = ""
        team_two = ""
        cts_final_lvls = []
        ts_final_lvls = []

        for el in new_res_list:
            if len(el) == 1:
                round_counter += 1
                kills_counter.append(kill_counter)
                kill_counter = 0
                wnr_list.append(el[0].get("winner team", ""))
                cts_lvl_list.append(el[0].get("ct buy level", ""))
                ts_lvl_list.append(el[0].get("t buy level", ""))
            else:
                att_list.append(el[0])
                vic_list.append(el[1])
                r_list.append(round_counter)
                kill_counter += 1

        for el in wnr_list:
            if rnd_cntr == 1:
                team_one = el

            if rnd_cntr == 15:
                team_two = team_one
                team_one = ""

            if rnd_cntr < 15:
                if el == team_one:
                    tms_list.append("Team 1")

                else:
                    tms_list.append("Team 2")
            else:
                if el == team_two:
                    tms_list.append("Team 2")
                else:
                    tms_list.append("Team 1")

            rnd_cntr += 1

        for el in kills_counter:
            for i in range(el):
                final_team_list.append(tms_list[idx])
                final_winner_list.append(wnr_list[idx])
                cts_final_lvls.append(cts_lvl_list[idx])
                ts_final_lvls.append(ts_lvl_list[idx])
            idx += 1

        return att_list, vic_list, r_list, final_winner_list, final_team_list, cts_final_lvls, ts_final_lvls

    def split_x_y_z(att_or_vic_list, att_or_vic_x, att_or_vic_y, att_or_vic_z):
        for el in att_or_vic_list:
            att_or_vic_x.append(el['x'])
            att_or_vic_y.append(el['y'])
            att_or_vic_z.append(el['z'])

        return att_or_vic_x, att_or_vic_y, att_or_vic_z

    def create_df_from_res(att_x, att_y, att_z, vic_x, vic_y, vic_z, rnds,
                           wnrs, tms):
        data_frame = pd.DataFrame({
            'attacker_x': att_x,
            'attacker_y': att_y,
            'attacker_z': att_z,
            'victim_x': vic_x,
            'victim_y': vic_y,
            'victim_z': vic_z,
            'round': rnds,
            'wnr_team': wnrs,
            'team_num': tms
        })
        return data_frame

    # points for old dust 2: StartX = -2486; StartY = -1150; EndX = 2127; EndY = 3455; ResX = 1024; ResY = 1024;

    def pointx_to_resolutionx(xinput, startX=-2486, endX=2127, resX=1024):
        sizeX = endX - startX
        if startX < 0:
            xinput += startX * (-1.0)
        else:
            xinput += startX
        xoutput = float((xinput / abs(sizeX)) * resX)
        return xoutput

    def pointy_to_resolutiony(yinput, startY=-1150, endY=3455, resY=1024):
        sizeY = endY - startY
        if startY < 0:
            yinput += startY * (-1.0)
        else:
            yinput += startY
        youtput = float((yinput / abs(sizeY)) * resY)
        return resY - youtput - 10

    # def convert_data(dataframe, list_of_dfs, rnds, wnrs, tms):
    #     new_df = pd.DataFrame()
    #     # Convert the data to radar positions
    #     new_df['att_map_x'] = dataframe['attacker_x'].apply(pointx_to_resolutionx)
    #     new_df['att_map_y'] = dataframe['attacker_y'].apply(pointy_to_resolutiony)
    #     new_df['vic_map_x'] = dataframe['victim_x'].apply(pointx_to_resolutionx)
    #     new_df['vic_map_y'] = dataframe['victim_y'].apply(pointy_to_resolutiony)
    #     new_df['round'] = rnds
    #     new_df['winner_team'] = wnrs
    #     new_df['team_num'] = tms
    #     list_of_dfs.append(new_df)
    #
    #     return list_of_dfs

    def convert_data(dataframe, actual_df, rnds, wnrs, tms, cts_lvls, t_lvls):
        new_df = pd.DataFrame()
        # Convert the data to radar positions
        new_df['att_map_x'] = dataframe['attacker_x'].apply(
            pointx_to_resolutionx)
        new_df['att_map_y'] = dataframe['attacker_y'].apply(
            pointy_to_resolutiony)
        new_df['vic_map_x'] = dataframe['victim_x'].apply(
            pointx_to_resolutionx)
        new_df['vic_map_y'] = dataframe['victim_y'].apply(
            pointy_to_resolutiony)
        new_df['round'] = rnds
        new_df['winner_team'] = wnrs
        new_df['team_num'] = tms
        new_df['t_buy_level'] = t_lvls
        new_df['ct_buy_level'] = cts_lvls
        actual_df.append(new_df)

        return actual_df

    # def df_to_csv(list_of_demos, list_of_dfs):
    #     for i in range(len(list_of_demos)):
    #         for j in range(len(list_of_dfs)):
    #             if i == j:
    #                 list_of_dfs[j].to_csv('../csv/{}.csv'.format(list_of_demos[i]))

    def df_to_csv(actual_df, actual_clear_df):
        actual_df[0].to_csv('../csv/{}.csv'.format(actual_clear_df[0]))

    def economy(dataframe, res_list):
        t_buy_level = 0
        ct_buy_level = 0
        counter = 1
        win_streak = 0
        prev_winner = ''

        for i in range(len(res_list)):
            if len(res_list[i]) == 1:
                rnd_winner = res_list[i][0].get("winner team")
                if counter == 1 or counter == 16:
                    win_streak = 0
                    if rnd_winner:
                        win_streak += 1
                    ct_buy_level = 1
                    t_buy_level = 1

                if counter == 2 or counter == 17:
                    if rnd_winner == "CTs win":
                        if rnd_winner == prev_winner:
                            win_streak += 1
                            ct_buy_level = 2.5
                            t_buy_level = 1.5
                        else:
                            win_streak = 1
                            ct_buy_level = 1.5
                            t_buy_level = 2.5
                    else:
                        if rnd_winner == prev_winner:
                            win_streak += 1
                            ct_buy_level = 1.5
                            t_buy_level = 2.5
                        else:
                            win_streak = 1
                            ct_buy_level = 2.5
                            t_buy_level = 1.5

                if counter == 3 or counter == 18:
                    if rnd_winner == "Ts win":
                        if rnd_winner == prev_winner:
                            win_streak += 1
                            ct_buy_level = 1.5
                            t_buy_level = 2.7
                        else:
                            win_streak = 1
                            ct_buy_level = 2.7
                            t_buy_level = 1.5
                    else:
                        if rnd_winner == prev_winner:
                            win_streak += 1
                            ct_buy_level = 2.7
                            t_buy_level = 1.5
                        else:
                            win_streak = 1
                            ct_buy_level = 1.5
                            t_buy_level = 2.7

                if 3 < counter <= 15 or 18 < counter <= 30:
                    if rnd_winner == "CTs win":
                        if rnd_winner != prev_winner:
                            win_streak = 1
                            # ct_buy_level += 0.2
                            t_buy_level -= 0.5
                        else:
                            if win_streak > 4 and t_buy_level == 2.5:
                                t_buy_level = 3
                            elif win_streak > 4 and t_buy_level == 3:
                                t_buy_level = 2.5
                            else:
                                win_streak += 1
                                if win_streak >= 4:
                                    ct_buy_level += 0.7
                                    t_buy_level = 2.5
                                else:
                                    if win_streak > 1 and ct_buy_level < 3:
                                        t_buy_level += 0.5
                                    else:
                                        ct_buy_level += 0.4
                                        t_buy_level -= 0.5
                                    if t_buy_level < 1:
                                        t_buy_level = 1

                        if ct_buy_level > 5:
                            ct_buy_level = 5
                        if t_buy_level > 5:
                            t_buy_level = 5

                    elif rnd_winner == "Ts win":
                        if rnd_winner != prev_winner:
                            win_streak = 1
                            ct_buy_level -= 0.8
                            # t_buy_level += 0.5
                        else:
                            if win_streak > 4 and ct_buy_level == 2.5:
                                ct_buy_level = 3
                            elif win_streak > 4 and ct_buy_level == 3:
                                ct_buy_level = 2.5
                            else:
                                win_streak += 1
                                if win_streak >= 4:
                                    ct_buy_level = 2.5
                                    t_buy_level += 0.7
                                else:
                                    if win_streak > 1 and t_buy_level < 3:
                                        ct_buy_level += 0.5
                                    else:
                                        ct_buy_level -= 0.4
                                        t_buy_level += 0.4
                                    if ct_buy_level < 1:
                                        ct_buy_level = 1

                        if ct_buy_level > 5:
                            ct_buy_level = 5
                        if t_buy_level > 5:
                            t_buy_level = 5
                res_list[i][0]["t buy level"] = round(t_buy_level, 1)
                res_list[i][0]["ct buy level"] = round(ct_buy_level, 1)
                res_list[i] = [res_list[i][0]]
                # res_list[0][i] = [res_list[0][i][0], {"t buy level": round(t_buy_level, 1), "ct buy level": round(ct_buy_level, 1)}]
                prev_winner = rnd_winner
                counter += 1

        return res_list

    def all_processes(res):
        final_res = create_final_res(res)
        new_final_res = economy(current_df, final_res)
        attackers_list, victims_list, rounds_list, winner_list, teams_list, ct_lvls, t_lvls = create_lists(
            final_res, attackers, victims, rounds, winners, teams,
            ct_final_lvls, t_final_lvls)
        attackers_x, attackers_y, attackers_z = split_x_y_z(
            attackers, attacker_x, attacker_y, attacker_z)
        vitctims_x, victims_y, victims_z = split_x_y_z(victims, victim_x,
                                                       victim_y, victim_z)
        df = create_df_from_res(attacker_x, attacker_y, attacker_z, victim_x,
                                victim_y, victim_z, rounds_list, winner_list,
                                teams_list)
        all_demos_result.append(new_final_res)
        new_dff = convert_data(df, current_df, rounds_list, winner_list,
                               teams_list, ct_lvls, t_lvls)
        df_to_csv(current_df, clear_demos_list)

        return all_demos_result

    all_demos_result = []
    current_df = []
    ct_round_end_msgs = [['#SFUI_Notice_Bomb_Defused'],
                         ['#SFUI_Notice_CTs_Win'],
                         ['#SFUI_Notice_Target_Saved']]
    t_round_end_msgs = [['#SFUI_Notice_Terrorists_Win'],
                        ['#SFUI_Notice_Target_Bombed']]

    demos_list = []
    clear_demos_list = []

    for file in os.listdir("../uploads"):
        if file.endswith(".dem"):
            demos_list.append(os.path.join("../uploads/", file))
            clear_demos_list.append(os.path.splitext(file)[0])

    for demo in demos_list:
        result = []
        attackers, victims, rounds, attacker_x, attacker_y, attacker_z, victim_x, victim_y, victim_z, winners, teams, ct_final_lvls, t_final_lvls = [], [], [], [], [], [], [], [], [], [], [], [], []
        data = open(demo, 'rb').read()
        d = DemoFile(data)
        d.add_callback('round_announce_match_start', m_start)
        d.add_callback('round_start', r_start)
        d.add_callback('player_death', death)
        d.add_callback('round_end', r_end)
        d.parse()
        data_res = all_processes(result)
    return data_res
コード例 #5
0
ファイル: player_death.py プロジェクト: themsoum7/demoparser
def death(event, msg):
    for idx, key in enumerate(event['event'].keys):
        if key.name == 'attacker':
            user_id = msg.keys[idx].val_short
            attacker = d.entities.get_by_user_id(user_id)
        elif key.name == 'userid':
            user_id = msg.keys[idx].val_short
            victim = d.entities.get_by_user_id(user_id)
        elif key.name == 'weapon':
            weapon = msg.keys[idx].val_string
        elif key.name == 'headshot':
            headshot = msg.keys[idx].val_bool

    if attacker and victim:
        print("\n --- Player Death at tick {}---".format(d.current_tick))
        print("{} killed by {} with {}. Headshot? {}.\n"
              "Attacker: health = {} position = {}\n"
              "Victim: position = {}".format(victim.name, attacker.name,
                                             weapon,
                                             'Yes' if headshot else 'No',
                                             attacker.health,
                                             attacker.position,
                                             victim.position))


if __name__ == "__main__":
    data = open(sys.argv[1], 'rb').read()
    d = DemoFile(data)
    d.add_callback('player_death', death)
    d.parse()
コード例 #6
0
ファイル: chat.py プロジェクト: themsoum7/demoparser
    print(t)


def server_text(msg):
    print_color(msg.text)


def game_chat(msg):
    params = {}

    if msg.msg_name.endswith('AllDead'):
        params['dead'] = '\x1b[0;31m* DEAD *\x1b[0m '
    else:
        params['dead'] = ''

    params['name'] = '{}{}\x1b[0m'.format(ansi_colors[msg.ent_idx % 14],
                                          msg.params[0])
    params['message'] = msg.params[1]

    fmt = "{dead}{name}: {message}".format(**params)
    print(fmt)


if __name__ == "__main__":
    data = open(sys.argv[1], 'rb').read()
    d = DemoFile(data)
    d.add_callback('SayText', server_text)
    d.add_callback('SayText2', game_chat)
    d.parse()