skill_rating/elo/mod.rs
1//! # ELO rating
2//!
3//! This module contains all of the standard methods that would be used to calculate elo.
4//! The module provied the constants WIN, LOSE and DRAW.
5
6pub mod systems;
7
8/// The EloRating type is i32 since a rating can be negative.
9pub type EloRating = i32;
10/// The score for a won game
11pub const WIN: f32 = 1_f32;
12/// The score for a drawn game
13pub const DRAW: f32 = 0.5;
14/// The score for a lost game
15pub const LOSS: f32 = 0_f32;
16
17fn rating_change(k: u32, score: f32, exp_score: f32) -> EloRating {
18 (k as f32 * (score - exp_score)) as i32
19}
20
21/// Calculates the expected outcome of a match between two players.
22/// This will always be a number between 0 and 1.
23/// The closer to 1 the more favored the match is for player a.
24///
25/// # Example
26///
27/// Chance of a person winning
28///
29/// ```
30/// use skill_rating::elo;
31///
32/// let john = 1700;
33/// let paul = 1800;
34///
35/// // Calculate johns chance to win against paul
36/// let chance = elo::expected_score(john, paul) * 100_f32;
37/// ```
38pub fn expected_score(r_a: EloRating, r_b: EloRating) -> f32 {
39 1_f32 / (1_f32 + 10_f32.powf(((r_b - r_a) as f32) / 400_f32))
40}
41
42
43
44/// Calculates the updated elo ratings of both players after a match.
45/// The k_a and k_b are the K factors used to determine the updated rating,
46/// If you just want a default behaviou set these to 32, or use game_icc() instead.
47///
48/// # Example
49///
50/// Updates the rankings of John and Paul, after Paul won over John.
51///
52/// ```
53/// use skill_rating::elo;
54///
55/// let john = 1700;
56/// let paul = 1800;
57///
58/// let (john, paul) = elo::game(paul, john, elo::WIN, 32, 32);
59/// ```
60pub fn game(r_a: EloRating, r_b: EloRating, s_a: f32, k_a: u32, k_b: u32) -> (EloRating, EloRating) {
61 let s_b = 1_f32 - s_a;
62
63 let e_a = expected_score(r_a, r_b);
64 let e_b = 1_f32 - e_a;
65
66
67 let new_a = r_a + rating_change(k_a, s_a, e_a);
68 let new_b = r_b + rating_change(k_b, s_b, e_b);
69
70
71 (new_a, new_b)
72}
73
74
75/// Calculates the updated elo of a player, after a series of games.
76/// This might be used to calculate the rating of a player after a tournement.
77///
78/// # Example
79///
80/// Update the rating of John after competing in a chess tournement.
81///
82/// ```
83/// use skill_rating::elo;
84///
85/// let john = 1700;
86///
87/// // An array containing the results of johns games in the tournement
88/// let games = [(1600, elo::WIN), (1800, elo::DRAW), (2000, elo::LOSS)];
89///
90/// let john = elo::series(john, &games, 32);
91/// ```
92pub fn series(r_a: EloRating, games: &[(EloRating, f32)], k_factor: u32) -> EloRating {
93 let mut score = 0_f32;
94 let mut exp_score = 0_f32;
95
96 for game in games {
97 score += game.1;
98 exp_score = expected_score(r_a, game.0);
99 }
100
101 r_a + rating_change(k_factor, score, exp_score)
102}