rust_elo/
lib.rs

1pub mod elo {
2    pub enum MatchWinner {
3        PlayerB = 0,
4        PlayerA = 1,
5    }
6
7    pub struct EloRank {
8        pub k: i32,
9    }
10
11    impl EloRank {
12
13        fn calculate_expected(&self, score_a: f64, score_b: f64) -> f64 {
14            1.0 / (1.0 + (10f64.powf((score_b - score_a) / 400.0)))
15        }
16
17        fn winner_to_score(&self, winner: MatchWinner) -> (f64, f64) {
18            match winner {
19                MatchWinner::PlayerA => (1.0, 0.0),
20                MatchWinner::PlayerB => (0.0, 1.0),
21            }
22        }
23
24        pub fn calculate(&self, player_a: f64, player_b: f64, winner: MatchWinner) -> (f64, f64) {
25            let k = self.k as f64;
26
27            let expected_a = self.calculate_expected(player_a, player_b);
28            let expected_b = self.calculate_expected(player_b, player_a);
29
30            println!("{} {}", player_a, expected_a);
31            println!("{} {}", player_b, expected_b);
32
33            let (score_a, score_b) = self.winner_to_score(winner);
34            let new1 = player_a + k * (score_a - expected_a);
35            let new2 = player_b + k * (score_b - expected_b);
36
37            (new1.round(), new2.round())
38        }
39    }
40}
41
42#[cfg(test)]
43mod tests {
44    use crate::elo::{EloRank, MatchWinner};
45
46    #[test]
47    fn calculates_correct_ratings() {
48        let elo = EloRank { k: 32 };
49        let (player_a_new, player_b_new) = elo.calculate(1200.0, 1400.0, MatchWinner::PlayerA);
50        assert_eq!(player_a_new, 1224.0);
51        assert_eq!(player_b_new, 1376.0);
52
53        let (player_a_new, player_b_new) = elo.calculate(1200.0, 1400.0, MatchWinner::PlayerB);
54        assert_eq!(player_a_new, 1192.0);
55        assert_eq!(player_b_new, 1408.0);
56    }
57
58    #[test]
59    fn rounds_ratings_properly() {
60        let elo = EloRank { k: 32 };
61        let (player_a_new, player_b_new) = elo.calculate(1802.0, 1186.0, MatchWinner::PlayerA);
62        assert_eq!(player_a_new, 1803.0);
63        assert_eq!(player_b_new, 1185.0);
64    }
65}