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