From b5e73cbbcf77d8edcd5e5fe4a78dbf2f72915614 Mon Sep 17 00:00:00 2001 From: Simon Gardling Date: Wed, 30 Apr 2025 13:52:19 -0400 Subject: [PATCH] elo: improve code quality and add confidence intervals --- src/elo.rs | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/elo.rs b/src/elo.rs index dbd35f0..9ea10c5 100644 --- a/src/elo.rs +++ b/src/elo.rs @@ -9,7 +9,7 @@ use indicatif::{ProgressBar, ProgressStyle}; use rand::seq::SliceRandom; use rayon::iter::{IntoParallelIterator, ParallelIterator}; use skillratings::{ - glicko2::{glicko2, Glicko2Rating}, + glicko2::{confidence_interval, glicko2, Glicko2Rating}, Outcomes, Rating, }; use std::num::NonZero; @@ -30,7 +30,7 @@ pub fn run() { ..Default::default() }; - let configs = [2, 4, 6] + let configs = [6] .into_iter() .map(move |d| FutureMoveConfig { max_depth: d, @@ -143,13 +143,22 @@ pub struct PlayerArena { impl std::fmt::Display for PlayerArena { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let mut players_i: Vec = (0..self.players.len()).collect(); - players_i.sort_by_key(|&i| -(self.players[i].2.rating() * 100.0) as i64); + + players_i.sort_by(|&a, &b| { + self.players[b] + .2 + .rating() + .total_cmp(&self.players[a].2.rating()) + }); for i in players_i { + let conf_interval = confidence_interval(&self.players[i].2); + writeln!( f, - "({:.2}): {}", + "({:.2}[+/-{:.2}]): {}", self.players[i].2.rating(), + conf_interval.1 - self.players[i].2.rating(), self.players[i].0 )?; } @@ -163,9 +172,8 @@ impl PlayerArena { Self { players: players .into_iter() - .zip([Default::default()].into_iter().cycle()) - // flatten tuple - .map(|((a, b), c)| (a, b, c)) + // All starting ratings should be the default + .map(|(a, b)| (a, b, Default::default())) .collect(), } } @@ -238,9 +246,12 @@ impl PlayerArena { received_num += 1; p.inc(1); + // add extra newline after progressbar println!(); + // break if all pairs were recieved if received_num == num { + drop(receiver); break; } } @@ -265,14 +276,12 @@ impl PlayerArena { } fn process_outcome(&mut self, player1: usize, player2: usize, outcome: &Outcomes) { - let (np1, np2) = glicko2( + (self.players[player1].2, self.players[player2].2) = glicko2( &self.players[player1].2, &self.players[player2].2, outcome, &Default::default(), ); - self.players[player1].2 = np1; - self.players[player2].2 = np2; } fn play_two_inner(player_1: Box, player_2: Box) -> Outcomes {