pnxenopoulos / awpy

Python library to parse, analyze and visualize Counter-Strike 2 data
http://www.awpycs.com
MIT License
387 stars 58 forks source link

Incorrect Kill Count Calculation as a result of incorrect filtering of non-play ticks. #346

Open onlinehunter opened 3 months ago

onlinehunter commented 3 months ago

I'm using awpy2 dev in my project, specifically awpy==2.0.0b2 from the pip repository. I've encountered an issue with the parse_kills(events: dict[str, pd.DataFrame]) method where it filters out non-play ticks using theremove_nonplay_ticks(kill_df) method.

In one of the demos, I noticed that this function incorrectly filters out some kills during gameplay. Upon further investigation, I found that approximately one second before the final kill and the round end, events are marked with is_ct_timeout=True.

Here is the FACEIT demo: https://www.faceit.com/en/cs2/room/1-0f23ea46-6beb-4d50-8728-eed8d87bb8a8

For instance, take round 1. This is the result produced by the current code of awpy==2.0.0b2:

kills = dem.kills[dem.kills['round']==1][['tick', 'round', 'attacker_name', 'victim_name', 'clock', 'ticks_since_freeze_time_end']]

   tick  round attacker_name victim_name  clock  ticks_since_freeze_time_end
0  6135      1        OlasX6    Arbuz097  01:43                          779
1  6425      1     VladDemYo      OlasX6  01:39                         1069
2  6693      1     DamianSTG   lilnaweed  01:35                         1337
3  6937      1     VladDemYo   DamianSTG  01:31                         1581
4  7068      1      kamyqowy   VladDemYo  01:29                         1712
5  7571      1        Arvi17      Zinkkq  01:21                         2215

I adjusted the code to remove non-play moments filtering and added is_terrorist_timeout and is_ct_timeoutfields to the result returned by parse_kills. This is the new result:

kills = dem.kills[dem.kills['round']==1][['tick', 'round', 'attacker_name', 'victim_name', 'clock', 'ticks_since_freeze_time_end', 'is_terrorist_timeout', 'is_ct_timeout']]
kills
    tick round attacker_name victim_name  clock  ticks_since_freeze_time_end  is_terrorist_timeout  is_ct_timeout
6   6135     1        OlasX6    Arbuz097  01:43                          779                 False          False
7   6425     1     VladDemYo      OlasX6  01:39                         1069                 False          False
8   6693     1     DamianSTG   lilnaweed  01:35                         1337                 False          False
9   6937     1     VladDemYo   DamianSTG  01:31                         1581                 False          False
10  7068     1      kamyqowy   VladDemYo  01:29                         1712                 False          False
11  7571     1        Arvi17      Zinkkq  01:21                         2215                 False          False
12  7933     1      kamyqowy    humidion  01:15                         2577                 False           True

As seen, the final kill at tick 7933 is filtered out by the current code of awpy==2.0.0b2, because is_ct_timeout=True at the moment of this tick.

Upon further analysis, I concluded that is_ct_timeout=True andis_terrorist_timeout=True flags are set when the team had been voted for a timeout, not when the timeout actually starts.

This causes incorrect filtering of non-play ticks.

pnxenopoulos commented 3 months ago

Thanks for finding this. Probably the best thing to do here is to say a team is in a timeout any time between a timeout start even and a round start. I will move to use that model for now, but might be worth talking with LaihoE about the demoparser library. This will be fixed in b3!

onlinehunter commented 3 months ago

Thank you. Yes, it can be a problem or bug on the demoparser2 side.