There was recently a discussion where a user was suspected to be a serial AFKer/early-solo-resigner.
On the one side it is a very annoying behavior (especially for the top-players, as it is mentioned oftentimes recently), but on the other side it is an accusation which is hard to prove, as opposite to simple "TK in battle X".
So I made a script which makes the relevant statistics for a given user.
Since I don't know how to parse replay files, I used the ZK website battles search. Thankfully all the data is there - the duration of the battle, whether and when the user "died" and so on.
I analysed the last 100 "valid" games of the user (this number can be easily changed in the settings), where "valid" means:
1. Name of the room includes "Teams All Welcome"
2. No exit voted
3. Duration > 1 min.
To give an example/reference point, here are results for myself:
All Battles:
battles count: 100
average battle duration: 25 min.
average played time: 24 min.
average relative played time: 95% of the battle duration
left before the end in 15% of battles
Won Battles:
battles count: 52
average battle duration: 24 min.
average played time: 24 min.
average relative played time: 98% of the battle duration
left before the end in 3% of battles
Lost Battles:
battles count: 48
average battle duration: 26 min.
average played time: 24 min.
average relative played time: 93% of the battle duration
left before the end in 27% of battles
So I very rarely left a game where my team is going to win, but don't like to play to the last solar, so in 27% of lost games I solo-resign/ragequit, but close to the end of the battle.
Now, these are the results for the suspected serial AFKer/resigner:
All Battles:
battles count: 100
average battle duration: 22 min.
average played time: 16 min.
average relative played time: 79% of the battle duration
left before the end in 49% of battles
Won Battles:
battles count: 47
average battle duration: 22 min.
average played time: 17 min.
average relative played time: 79% of the battle duration
left before the end in 44% of battles
Lost Battles:
battles count: 53
average battle duration: 22 min.
average played time: 16 min.
average relative played time: 78% of the battle duration
left before the end in 52% of battles
As we can see, this user quits half of the games, both won and lost, at the same average time-mark.
I hope this tool can help to (dis-)prove the similar accusations.
To run the script you need Bash and cURL.
The script is in the spoiler below:
[Spoiler]#!/bin/bash -u
# This script analyses the n last valid "Teams All Welcome" battles of a specific user, and calculates some solo-resign/AFK stats
# author: rollmops
# version: 1.0
# license: WTFPL
### SETTINGS
# this is my UserId, change it to the UserId you want to check (look at the web address of the user's homepage)
user_id='454168'
# how many valid last battles to analyse (bear in mind that it takes a second or two for each battle)
max_battles_to_analyse=100
### END OF SETTINGS
### FROM HERE ON, NO NEED TO CHANGE ANYTHING
# get the username to be sure the right UserID was given:
username=$(curl "https://zero-k.info/Users/Detail/$user_id" 2>/dev/null | grep -oP '\w+ (?=user page)')
echo "USER: $username"
# initializing counters
won_battles_count=0
won_battles_left_count=0
won_battles_total_duration=0
won_battles_total_played_time=0
won_battles_played_time_percent_accumulated=0
lost_battles_count=0
lost_battles_left_count=0
lost_battles_total_duration=0
lost_battles_total_played_time=0
lost_battles_played_time_percent_accumulated=0
# In zero-k.info, battles search results are given in the batches of 40, latest battles are first. Next batch automatically retrieved when you scroll down the page in the browser. Under the hood a Post request is sent, which is used in the loop below:
offset=0
while true; do
echo "fetching battles $((offset+1))-$((offset+40))..."
# prepare the string for the Post request
# $offset will grow by 40 in each iteration
payload='Title=&Map=&UserId='$user_id'&PlayersFrom=&PlayersTo=&Age=0&MinLength=&MaxLength=&Mission=2&Bots=2&Rank=8&Victory=0&offset='$offset
# get a batch of the search results (HTML)
battles_list=$(curl 'https://zero-k.info/Battles' -X POST -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' --data-raw "$payload" 2>/dev/null)
# if non-empty list retrieved, increase the $offset by 40, otherwise break the loop
echo "$battles_list" | grep -q "href='/Battles/Detail/" && (( offset = offset + 40 )) || break
# now parse the list, and for each battle ID, open its details page and get the relevant info
for battle_id in $(echo "$battles_list" | grep -oP "(?<=href='/Battles/Detail/)\d+"); do
echo -n "$battle_id: ";
# get "battle details" HTML page with the "Show winners" enabled
battle_details=$(curl 'https://zero-k.info/Battles/Detail/'$battle_id'?ShowWinners=True' 2>/dev/null)
# if not 'Teams All Welcome', discard
echo $battle_details | grep -q 'Teams All Welcome' || { echo "not TAW"; continue; }
# if exit voted (both teams appear Lost), discard
echo $battle_details | grep -qP 'Team \d Won' || { echo 'exit voted'; continue; }
# if battle duration is in seconds, discard
echo $battle_details | grep -oPz '(?s)Duration.*?</tr>' | grep -aq 'seconds' && { echo 'very short battle'; continue; }
# get battle duration in minutes
duration=$(echo $battle_details | grep -oPz '(?s)Duration.*?minutes' | grep -aoP '\d+')
echo -n "$duration min. "
# find to which team the user belongs (if UserId appears after 'Team 2', the team is 2, otherwise 1)
team_id=1
echo $battle_details | grep -qoPz "(?s)Team 2 .*/Users/Detail/$user_id" && team_id=2
echo -n "Team $team_id "
# find whether user's team won or lost
result=$(echo $battle_details | grep -oP "(?<=Team $team_id )\w+")
echo -n "$result "
# get the user's "died in ..." time (number of min. or sec.)
played_time=$(echo $battle_details | grep -oPz "(?s)/Users/Detail/$user_id.*?</span>" | grep -aoP '(?<=died in )\d+')
# if it's in seconds, divide by 60
echo $battle_details | grep -oPz "(?s)/Users/Detail/$user_id.*?</span>" | grep -qaP 'died in \d+ seconds' && (( played_time = played_time / 60 ))
# if no "died in ..." for the user, set it to the battle duration
[ -z $played_time ] && played_time=$duration
echo -n "played: $played_time min. "
# set a flag if the user left before the end
[[ $played_time -lt $duration ]] && left_before_end='YES' || left_before_end='no'
echo "left before end: $left_before_end"
# calculate the percentage of the battle duration at which user left
[[ $duration -gt 0 ]] && (( played_time_percent = 100 * played_time / duration )) || played_time_percent=100
# update the counters with the acquired data
if [[ $result == 'Won' ]]; then
(( won_battles_count++ ))
[[ $left_before_end == 'YES' ]] && (( won_battles_left_count++ ))
(( won_battles_total_duration += duration ))
(( won_battles_total_played_time += played_time ))
(( won_battles_played_time_percent_accumulated += played_time_percent ))
else
(( lost_battles_count++ ))
[[ $left_before_end == 'YES' ]] && (( lost_battles_left_count++ ))
(( lost_battles_total_duration += duration ))
(( lost_battles_total_played_time += played_time ))
(( lost_battles_played_time_percent_accumulated += played_time_percent ))
fi
# if the max_battles_to_analyse reached, quit both the loops
[[ $(( won_battles_count + lost_battles_count )) -eq $max_battles_to_analyse ]] && break 2
done
done
# calculate and print the stats
(( all_battles_count = won_battles_count + lost_battles_count ))
echo
echo
echo "RESULTS"
echo
echo "All Battles:"
echo
echo "battles count: $all_battles_count"
echo "average battle duration: $(( ( won_battles_total_duration + lost_battles_total_duration ) / all_battles_count )) min."
echo "average played time: $(( ( won_battles_total_played_time + lost_battles_total_played_time ) / all_battles_count )) min."
echo "average relative played time: $(( ( won_battles_played_time_percent_accumulated + lost_battles_played_time_percent_accumulated ) / all_battles_count))% of the battle duration"
echo "left before the end in $(( 100 * ( won_battles_left_count + lost_battles_left_count ) / all_battles_count ))% of battles"
echo
echo "Won Battles:"
echo
echo "battles count: $won_battles_count"
echo "average battle duration: $(( won_battles_total_duration / won_battles_count )) min."
echo "average played time: $(( won_battles_total_played_time / won_battles_count )) min."
echo "average relative played time: $(( won_battles_played_time_percent_accumulated / won_battles_count))% of the battle duration"
echo "left before the end in $(( 100 * won_battles_left_count / won_battles_count ))% of battles"
echo
echo "Lost Battles:"
echo
echo "battles count: $lost_battles_count"
echo "average battle duration: $(( lost_battles_total_duration / lost_battles_count )) min."
echo "average played time: $(( lost_battles_total_played_time / lost_battles_count )) min."
echo "average relative played time: $(( lost_battles_played_time_percent_accumulated / lost_battles_count))% of the battle duration"
echo "left before the end in $(( 100 * lost_battles_left_count / lost_battles_count ))% of battles"