ELO is a small TypeScript library for calculating Elo ratings — the system used in chess and many other competitive games to measure relative skill.
It follows FIDE rules out of the box: K-factors by age, games played, and rating tier; a 400-point rating difference cap; and performance rating calculation. Zero runtime dependencies.
Most Elo libraries on npm give you the basic formula and nothing else. If you're building a chess platform or any app that follows FIDE rules, you'd have to implement the rest yourself. This library ships it all out of the box:
If you don't need FIDE compliance, any Elo library will do. If you do, this is the one.
npm install @echecs/elo
import { update } from '@echecs/elo';
// Two players both rated 1400. Player A wins.
const [playerA, playerB] = update(1400, 1400, 1);
console.log(playerA); // 1410
console.log(playerB); // 1390
Basic — when you just need new ratings after a game:
import { update } from '@echecs/elo';
const [newRatingA, newRatingB] = update(1400, 1400, 1); // → [1410, 1390]
Player options — pass a player object when you need to apply FIDE K-factor rules for age or experience:
import { update } from '@echecs/elo';
// Young player (age < 18, rating < 2300) gets K=40
const [newRatingA, newRatingB] = update({ age: 15, rating: 1400 }, 1400, 1); // → [1420, 1390]
// New player (≤ 30 games played) also gets K=40
const [newRatingC, newRatingD] = update(
{ gamesPlayed: 10, rating: 1400 },
1400,
1,
); // → [1420, 1390]
Game options — pass a game object as the third argument when the game type affects the K-factor:
import { update } from '@echecs/elo';
// Blitz and rapid games always use K=20
const [newRatingA, newRatingB] = update(2400, 2400, {
gameType: 'blitz',
result: 1,
}); // → [2410, 2390]
K-factor cap — pass gamesInPeriod when a player has played many games in
the current rating period and the §8.3.3 cap applies:
import { update } from '@echecs/elo';
// New player (K=40) with 18 games played in the period — K is capped to 38
const [newRatingA, newRatingB] = update(
{ gamesInPeriod: 18, gamesPlayed: 0, rating: 1400 },
1400,
1,
); // → [1419, 1390]
Performance rating — use performance() to calculate a player's FIDE
performance rating over a tournament:
import { performance } from '@echecs/elo';
const rating = performance([
{ opponentRating: 1600, result: 1 },
{ opponentRating: 1600, result: 0.5 },
{ opponentRating: 1600, result: 0 },
]); // 1600
Initial rating — use initial() to calculate a new (unrated) player's first
FIDE rating. If the player scored zero points across their entire first event,
omit all games from that event before calling (§8.2.1):
import { initial } from '@echecs/elo';
const rating = initial([
{ opponentRating: 1600, result: 1 },
{ opponentRating: 1500, result: 0.5 },
{ opponentRating: 1700, result: 0 },
{ opponentRating: 1600, result: 1 },
{ opponentRating: 1550, result: 1 },
]); // → 1752
Full API reference is available at https://mormubis.github.io/elo/
Contributions are welcome. Please read CONTRIBUTING.md for guidelines on how to submit issues and pull requests.