rust_elo_multiplayer/
lib.rs

1pub struct EloRank {
2    pub k: i32,
3    pub players: Vec<f64>,
4}
5impl Default for EloRank {
6    fn default() -> EloRank {
7        EloRank {
8            k: 32,
9            players: vec![1000f64, 1000f64],
10        }
11    }
12}
13
14impl EloRank {
15    fn calculate_expected(&self) -> Vec<f64> {
16        let amount_of_players = self.players.len() as f64;
17        let mut expected_array: Vec<f64> = vec![];
18        for (i, _) in self.players.iter().enumerate() {
19            let sum = self.players.iter().enumerate().fold(0f64, |s, (j, p)| {
20                if i == j {
21                    s
22                } else {
23                    s + 1.0 / (1.0 + 10f64.powf((p - self.players[i]) / 400f64))
24                }
25            });
26            let expected = sum / ((amount_of_players * (amount_of_players - 1f64)) / 2f64);
27            expected_array.push(expected)
28        }
29        return expected_array;
30    }
31
32    fn calculate_scores(&self) -> Vec<f64> {
33        let amount_of_players = self.players.len() as f64;
34        let mut scores: Vec<f64> = vec![];
35        for (i, _) in self.players.iter().enumerate() {
36            let score = (amount_of_players - (i as f64 + 1f64))
37                / (amount_of_players * (amount_of_players - 1f64) / 2f64);
38            scores.push(score);
39        }
40        scores
41    }
42
43    pub fn calculate(&self) -> Vec<f64> {
44        let amount_of_players = self.players.len() as f64;
45        let expected = self.calculate_expected();
46        let scores = self.calculate_scores();
47        let mut new_elo: Vec<f64> = vec![];
48        for (i, p) in self.players.iter().enumerate() {
49            new_elo
50                .push(p + (self.k as f64) * (amount_of_players - 1f64) * (scores[i] - expected[i]));
51        }
52        new_elo
53    }
54}
55
56#[cfg(test)]
57mod tests {
58    use crate::EloRank;
59    #[test]
60    fn test_elo() {
61        let elo = EloRank {
62            players: vec![897.0, 978.0],
63            ..Default::default()
64        };
65        assert_eq!(elo.calculate(), vec![916.6640435522738, 958.3359564477262]);
66
67        let elo = EloRank {
68            players: vec![978.0, 897.0],
69            ..Default::default()
70        };
71        assert_eq!(elo.calculate(), vec![990.3359564477262, 884.6640435522738]);
72
73        let elo = EloRank {
74            players: vec![1000.0, 1000.0, 1000.0],
75            ..Default::default()
76        };
77        assert_eq!(
78            elo.calculate(),
79            vec![1021.3333333333334, 1000.0, 978.6666666666666]
80        );
81
82        let elo = EloRank {
83            players: vec![897.0, 978.0, 982.0, 995.0, 1017.0, 1034.0, 1096.0],
84            ..Default::default()
85        };
86        assert_eq!(
87            elo.calculate(),
88            vec![
89                933.4271852776218,
90                998.2520240277877,
91                992.7510517787325,
92                995.4420183323965,
93                1006.3245067439552,
94                1012.6627230848082,
95                1060.140490754698
96            ]
97        );
98    }
99}