toefungi-elo-calculator
Version:
A package to do all necessary computations to determine ELO rankings
173 lines • 7.54 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
/**
* https://metinmediamath.wordpress.com/2013/11/27/how-to-calculate-the-elo-rating-including-example/
*
* EloCalculator class to do calculations to determine the elo of a player after a match.
*/
var EloCalculator = /** @class */ (function () {
/**
* Constructor method for the EloCalculator class.
*
* @param {boolean} shouldRound Whether or not the new ELO should be rounded before being returned.
* @param {number} kFactor The factor the new ELO is calculated against.
*/
function EloCalculator(shouldRound, kFactor) {
if (shouldRound === void 0) { shouldRound = true; }
if (kFactor === void 0) { kFactor = 32; }
this.kFactor = 32;
this.kFactor = kFactor;
this.shouldRound = shouldRound;
}
/**
* @private
*
* Takes a current ELO score and will convert it to it's equivalent base10 value which can be used
* to determine ELO for a win, loss or draw.
*
* @param {number} elo An ELO score to be converted to base10.
* @return {Promise<number>} The equivalent base10 rank of the given ELO.
*/
EloCalculator.prototype.convertEloToBase10 = function (elo) {
var divide = function () { return elo / 400; };
var convertToBase10 = function (value) { return Math.pow(10, value); };
return Promise.resolve()
.then(divide)
.then(convertToBase10);
};
/**
* @private
*
* Calculates the base10 equivalent value of each player's ELO score which can then be used to determine the new ELO
* score for the player.
*
* @param {number} playerElo The initial ELO of the player.
* @param {number} opponentElo The initial ELO of the opponent.
* @return {Promise<RelativeRank>} An object containing the equivalent base10 value of both player's ELO score.
*/
EloCalculator.prototype.determineRelativeRank = function (playerElo, opponentElo) {
return Promise.all([
this.convertEloToBase10(playerElo),
this.convertEloToBase10(opponentElo)
]).then(function (_a) {
var player = _a[0], opponent = _a[1];
return ({ player: player, opponent: opponent });
});
};
/**
* @private
*
* Determines the scoring factor of the player based on their rank against their opponents rank.
*
* @param {number} playerRank The base10 value of the player's ELO score.
* @param {number} opponentRank The base10 value of the opponent's ELO score.
* @return {Promise<number>} The determined scoring factor.
*/
EloCalculator.prototype.determineScoreFactor = function (playerRank, opponentRank) {
var add = function () { return playerRank + opponentRank; };
var divide = function (value) { return playerRank / value; };
return Promise.resolve()
.then(add)
.then(divide);
};
/**
* @private
*
* Determines the new ELO of a player based on the score factor, a win or loss and current ELO score.
*
* @param {number} playerElo A player's current ELO score.
* @param {number} scoringFactor A factor derived from the player's relative base10 ELO score with their opponent's .
* @param {ScoringBonus} score Enum with [ WIN, LOSS, DRAW ].
* @param {number} scoreDiff The difference in the score as a number.
* @return {Promise<number>} The new calculated ELO.
*/
EloCalculator.prototype.determineElo = function (playerElo, scoringFactor, score, scoreDiff) {
var _this = this;
var getFactor = function (difference) {
if (!difference) {
return _this.kFactor;
}
return Math.log(Math.abs(difference) + 1) * _this.kFactor;
};
var subtract = function () { return score - scoringFactor; };
var add = function (value) { return playerElo + value; };
var multiply = function (value) { return value * getFactor(scoreDiff); };
return Promise.resolve()
.then(subtract)
.then(multiply)
.then(add);
};
/**
* @private
*
* Rounds off the ELO score before it is returned.
*
* @param {number} elo A value representing the ELO.
* @return {Promise<number>} The rounded off ELO value.
*/
EloCalculator.prototype.rounding = function (elo) {
var _this = this;
return Promise.resolve()
.then(function () {
if (!_this.shouldRound) {
return elo;
}
return Math.round(elo);
});
};
/**
* @private
*
* Creates a probability object which will be returned to the user.
*
* @param {number} probability The probability of the `player` to win the game.
* @return {Promise<Probabilities>} The probability of a win for either player based on the `player` ELO.
*/
EloCalculator.prototype.createProbability = function (probability) {
return Promise.resolve()
.then(function () {
var player = Math.round(probability * 100);
var opponent = Math.round((1 - probability) * 100);
return {
player: player,
opponent: opponent
};
});
};
/**
* Calculate the ELO of a player after a match based on their opponent's ELO and whether or not the player won the game.
*
* @param {number} playerElo The ELO of the player.
* @param {number} opponentElo The ELO of the opponent.
* @param {ScoringBonus} score The outcome of the game for the player, enum with [ WIN, LOSS, DRAW ].
* @param {number} scoreDiff The difference in the score as a number.
* @return {Promise<number>} The new ELO of the player.
*/
EloCalculator.prototype.calculateElo = function (playerElo, opponentElo, score, scoreDiff) {
var _this = this;
return Promise.resolve()
.then(function () { return _this.determineRelativeRank(playerElo, opponentElo); })
.then(function (relativeRank) { return _this.determineScoreFactor(relativeRank.player, relativeRank.opponent); })
.then(function (scoringFactor) { return _this.determineElo(playerElo, scoringFactor, score, scoreDiff); })
.then(function (elo) { return _this.rounding(elo); });
};
/**
* Calculate the win probability for players in a match up given their respective ELO's.
*
* @param {number} playerElo The ELO of the player.
* @param {number} opponentElo The ELO of the opponent.
* @return {Promise<Probabilities>} The win probability for each player respectively.
*/
EloCalculator.prototype.caluclateWinProbability = function (playerElo, opponentElo) {
var determineDiff = function () { return opponentElo - playerElo; };
var determineProbability = function (elo) { return 1 / (1 + elo); };
return Promise.resolve()
.then(determineDiff)
.then(this.convertEloToBase10)
.then(determineProbability)
.then(this.createProbability);
};
return EloCalculator;
}());
exports.EloCalculator = EloCalculator;
//# sourceMappingURL=EloCalculator.js.map