rust_elo_multiplayer/
lib.rs1pub 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}