(Work in progress)
For a long time myself and my fellow pilots have wanted a drone racing ranking site that keeps track of all previous results and places each pilot on a master list, similar to chess ratings. After I learned the basics of Python, I needed to take on a project to force myself to learn harder concepts, but I did not want to spend my time on something uninteresting or useless in the long run. Creating this ranking system seemed like the perfect opportunity to implement and improve my Python skills.
The first step was getting some event result data to work with, which I chose to do in the form of .csv, because it was easy to create and I knew how to parse it with Python already.
Each CSV has 3 rows: overall placement, name (which includes real name and pilot handle, and prize money earned, if applicable. Having the pilot name in quotation makes it easy to parse out, and is how it listed by MultiGP.
I had heard of the Elo ranking system from video games and also knew it was behind chess rankings, so I decided to use this as my starting point for the algorithm. Conveniently, I was not the first to use Python for Elo calculation and I was able to find a great starting point online. It was also at this point that I realized I was in over my head for my limited experience, and while I could have spent many many hours watching videos and researching, I asked my friend Noah to help speed up the process and teach me as I went along. Huge thanks to them for the help on getting this going!
Because Elo was created for chess matchups of pairs, we had to take the overall event placements and generate pairwise matchups from it. When printed, it creates a massive output:
We then had to use the pairwise data to calculate the Elo rating of every pilot. The events must be processed in chronological order to have accurate and up-to-date results.
import eventparse
import elo
import os
from jinja2 import Environment, FileSystemLoader, select_autoescape
profiles, pairwise = eventparse.eventmerge()
for name, profile in profiles.items():
profile["elo"] = 1500
for match in pairwise:
winner = match["winner"]
loser = match["loser"]
winnerscore, loserscore = elo.EloRating(profiles[winner]["elo"], profiles[loser]["elo"], 40, 1)
profiles[winner]["elo"] = winnerscore
profiles[loser]["elo"] = loserscore
def elofunction(profile):
return profile[1]["elo"]
eloranked = sorted(profiles.items(), reverse = True, key = elofunction)
print("{" + "\n".join("{!r}: {!r},".format(k, v) for k, v in eloranked) + "}")
env = Environment(
loader=FileSystemLoader('%s/templates/' % os.path.dirname(os.path.abspath(__file__))),
autoescape=select_autoescape()
)
pilottemplate = env.get_template("pilot.html")
for name, profile in profiles.items():
out = pilottemplate.render(name = name, profile = profile)
outfile = open("output/{}.html".format(name.replace(" ", "_")), "w")
outfile.write(out)
outfile.close()
indextemplate = env.get_template("index.html")
out = indextemplate.render(profiles = profiles)
outfile = open("output/index.html", "w")
outfile.write(out)
outfile.close()
And it worked! This is still a work in progress and we are likely going to be creating our own custom algorithm instead of Elo, but we now have pilot ratings and can display it with some basic HTML.