I am a Below Average Quake Champions Player

August 04, 2018

I have recently started to play Quake Champions by Bethesda. I wondered how I fared against other players in this game. Fortunately Bethesda has publicly accessible data by way of their Quake Stats website. This website aggregates match information and computes ELO-like scoring for participating players. I use this data to show how I compare to other players in the game Quake Champions. This required Python scripting to get the data, some light shell scripting to get the data into an easy to analyze form, and finally I used scipy to calculate histograms and other statistics values which help to summarize the data.

I focus on the “duel” game format, which involves only two players. As of writing this blog post my ELO in duel was around 1400. How do I match up to other players? Unfortunately it seems this is below average!

I wrote the following Python script to grab the raw HTML for everyone that participates in ranked duels

from selenium import webdriver
from bs4 import BeautifulSoup

browser = webdriver.Chrome() #replace with .Firefox(), or with the browser of your choice
url="https://stats.quake.com/leaderboards/"
browser.get(url) #navigate to the page




idx=0
#Get navigation select by its xpath (found via Chrome "copy xpath" feature)
element = browser.find_element_by_xpath("//*[@id='root']/div/div[2]/div[2]/div/select")
#loop over all options 
all_options = element.find_elements_by_tag_name("option")
for option in all_options:
    #print option to terminal so I know progress
    print("Value is: %s" % option.get_attribute("value"))
    #Navigate to appropriate option
    option.click()
    #get leaderboard fully rendered HTMl
    leader_html=browser.execute_script("return document.body.innerHTML") 
    f=open("data/leaderboards{}.txt".format(idx),"w")
    #prettify HTML to make exploration easier
    soup = BeautifulSoup(leader_html, 'html.parser')
    #write to file
    f.write(soup.prettify())
    f.close()
    idx=idx+1

It took me a little while to figure out how to get the data from the quakestats website since I have never done that kind of task before.

Fortunately the remaining tasks I’m quite comfortable with. First I used grep to isolate the ELO scores as follows (note the whitespace):

cat ./data/* |grep '         [0-9]\?[0-9][0-9][0-9]'

I figured out the right regex and whitespace by trial and error. It seemed easier to do this than to involve a full-blown HTML parser as all I wanted was this singular value, which had a very consistent format in the Quake stats website.

Next I used Scipy (via the Anaconda Python Distribution) to compute the mean and standard deviation of these values:

import numpy as np
import matplotlib as mat
import scipy.stats
#mat.use('agg')
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
%matplotlib inline
elos=np.loadtxt("out")
avg_elo=np.mean(elos)
std_elo=np.std(elos)
print("Average ELO: {}".format(avg_elo))
print("STD ELO: {}".format(std_elo))

Immediately from these I can see that I am sadly a below average Quake player! The average ELO was 1553.98 and the standard deviation was 276.6. I thought it would be interesting to plot these results as a histogram plot, which I do below:

Quake ELO Data

I generated this with the following script

n, bins, patches = plt.hist(elos, 50, density=1, facecolor='green', alpha=0.75,label="Quake stats ELO data")
# add a 'best fit' line
mu=avg_elo
sigma=std_elo
y = scipy.stats.norm.pdf( bins, mu, sigma)
l = plt.plot(bins, y, 'r-', linewidth=2,label="Normal distribution")
plt.plot(1400.0,0.0,'bo',markersize=20,label="My current ELO")
plt.legend()
fig = plt.gcf()
plt.show()
fig.savefig('elo.svg')

Next Steps

The above simple analysis shows that I am a below average Quake Champions player. Further analysis could try and show how effective the ELO ranking they compute is at predicting match outcomes, for example: if I as a 1400 ranked player face a 1500 ranked player, what is my probability of success? There is a formula for this, but how well does that formula match up with actual match outcomes? Testing the formula would require retrieving all available match data and computing the probability of winning a match given a ELO difference. I may do this at a later date.