A tiny app to find similar cyclists given a chosen rider. The selection can be filtered based on age, country, and rider characteristics.
Note: Since November 28, 2022, the free Heroku resources are sadly not available anymore. Don't worry, you can still enjoy the app locally!
Note 2: Check out the sborms/cyclingsimilarity.com repository for a more extensive implementation of this idea.
Note 3: Tried to put the app back online on either Vercel or PythonAnywhere but the free plans were not sufficient (damn you too large virtual environments!).
Note 4: It's a bingo! The app is now available on Azure App Service for free, see the instructions.
Note 5: "Error 403 - This web app is stopped." After many months, Azure was fed up with supporting this crazy popular app for free but it was nice while it lasted.
This little tool has several possible applications:
- Gaming (e.g. Pro Cycling Manager or Wielermanager)
- Transfers (to replace a certain rider)
- Scouting (to find the next talent within a certain region)
- You can simply use it out of curiosity
There are of course much more advanced tools to use for above purposes, but it can be useful to provide quick and initial guidance.
The data come from the community-made PCM.daily Expansion Pack 2022 u1 database (released June 28th, 2022) for the game Pro Cycling Manager (PCM) 2022. Note that as the database is an update from before the Tour de France 2022, it is not the most recent reflection of a rider's capabilities (for example, Jonas Vingegaard is not the strongest climber). The cyclist's statistics remain overall a very good representation.
In the database each rider has 13 characteristics representing various facets of cycling (such as climbing, sprinting, cobblestones, and so on). The stats have been extracted from the database to Excel using this tool, and are the sole basis for comparing riders.
There is another stats dataset under the data
folder, from the final community-made WorldDB 2021 database for PCM 2020, downloaded from the Steam Workshop. Other databases (and for other PCM versions) can be found when you register on pcmdaily.com.
The most similar riders are computed using KNN (K nearest neighbors) search. There are only 5000+ riders in the database, so I could use a brute-force approach. The algorithm compares the vector of the 13 characteristics for the chosen rider with the vectors for all riders, and returns the nearest neighbors. Dead simple!
My initial attempt was with the FAISS library, but Heroku (cf. below) doesn't seem to support this library. I based myself on the first example in here, using the exact L2 norm functionality, to find the riders with the smallest Euclidean distance (thus most similar) versus the base rider. The library is much more powerful, but this use case didn't require more complexity. Related code is found in the bin
folder.
The plot shown is called a spider (or radar, star, polar) chart, made with the Plotly library.
The tool is a Python Dash app. It is my first, and I just started with the official tutorial, then modified along until I reached my desired outcome. My development environment was PyCharm.
It is made available on a free Heroku server. I followed these steps, but had to do some obligatory troubleshooting to get it up and running.
Not going to lie, the app is not the prettiest (especially on mobile), but it is functional. To make it prettier, further diving into this would be a good resource I think.
The app can be deployed on Azure App Service for free, see this quickstart and below commands to create the application. Give it some minutes to show up.
First log in to your Azure account:
az login
Set some variables:
$rg = "rg-find-a-similar-pro-cyclist"
$app = "find-a-similar-pro-cyclist"
$location = "westeurope"
Then create the web application (note that the F1
indicates to use the free plan) and adjust the startup command:
az webapp up \
--runtime PYTHON:3.9 \
--sku F1 \
--logs \
--name $app \
--resource-group $rg \
--location $location
az webapp config set \
--resource-group $rg \
--name $app \
--startup-file "gunicorn --bind=0.0.0.0 --timeout 600 app:server"
To see the logs in your terminal, do:
az webapp log tail --name $app --resource-group $rg
In case you want do delete the app, run this:
az group delete --name $rg --no-wait
If you are interested in expanding the logic, or improving the app('s layout), get in touch! You can read the article on Medium (see top) for more background.