Last active
December 5, 2019 21:41
-
-
Save hilnius/9347c6fd0f84dc3bb6d5acedad631b39 to your computer and use it in GitHub Desktop.
A Google Sheets function to compute ELO for Mario-Kart games
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var _ = LodashGS.load(); | |
/* | |
NEXT_ELO Google Sheets function | |
This method computes the ELO for our Mario Kart tournament. | |
Usage: =NEXT_ELO(results_range, elo_range) | |
- results_range is an horizontal range that contains the results of a game. | |
- elo_range is an horizontal range that contains the ELOs before that game. | |
Returns: an horizontal range containing the new elo of all players after | |
considering the game results. | |
The formula is based on https://en.wikipedia.org/wiki/Elo_rating_system | |
Considering one results line, we consider the rank of all players that | |
participated in that race, and consider wins & losses depending on other | |
participant's scores. If a line contains 4 players' scores, we consider | |
3 wins/0 losses for the first, 2w/1l for the second, 1w/2l for the third | |
and 0w/3l for the fourth. There can be draws if players have the same score. | |
Example usage: | |
Sheet1: | |
[P1, P2, P3, P4, P5, P6] | |
[12, 35, 60, , 45, ] # You can use race or tourney points ! | |
[12, 35, 60, , 45, ] | |
[ , , 60, 22, 45, 17] | |
[ ... ] | |
Sheet2: | |
[ P1 , P2 , P3 , P4 , P5 , P6 ] | |
[ 1000, 1000, 1000, 1000, 1000, 1000 ] | |
[=NEXT_ELO(Sheet1!A2:F2; Shee2!A2:F2)] ## only need to put it in the first cell ! | |
[=NEXT_ELO(Sheet1!A3:F3; Shee2!A3:F3)] | |
[ ... ] | |
© Robin Nicollet | |
*/ | |
function NEXT_ELO(marioKartTourneyResultsRange, currentEloLine) { | |
var results = []; | |
for (var i = 0; i < marioKartTourneyResultsRange[0].length; i++) { | |
if (marioKartTourneyResultsRange[0][i]) { | |
results.push({ | |
playerColumn: i, | |
tourneyPoints: marioKartTourneyResultsRange[0][i], | |
currentElo: currentEloLine[0][i], | |
}); | |
} | |
} | |
var p = function (D) { | |
return 1/(1 + Math.exp(-D / 400 * Math.LN10)); | |
}; | |
_.forEach(results, function (currentPlayerResult) { | |
var K = 40; | |
var currentPlayerNewElo = currentPlayerResult.currentElo; | |
_.forEach(results, function (otherPlayerResult) { | |
if (otherPlayerResult.playerColumn != currentPlayerResult.playerColumn) { | |
var D = currentPlayerResult.currentElo - otherPlayerResult.currentElo; | |
var W = 0; | |
if (currentPlayerResult.tourneyPoints > otherPlayerResult.tourneyPoints) { | |
W = 1; | |
} else if (currentPlayerResult.tourneyPoints == otherPlayerResult.tourneyPoints) { | |
W = 0.5; | |
} | |
currentPlayerNewElo += K * (W - p(D)); | |
} | |
}); | |
currentPlayerResult.newElo = currentPlayerNewElo; | |
}); | |
return [_.map(currentEloLine[0], function (currentElo, column) { | |
var result = _.find(results, _.matches({ playerColumn: column })); | |
if (result) { | |
return result.newElo; | |
} | |
return currentElo; | |
})]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment