diff --git a/src/config.rs b/src/config.rs index 24b6684..e42e724 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,6 +1,6 @@ //! `config` contains logic for configuring and running the tournament -use std::sync::{Arc, Mutex}; +use std::{sync::{Arc, Mutex}, cmp::Ordering}; use rand::{prelude::*, distributions}; use threadpool::ThreadPool; use constcat::concat; @@ -207,7 +207,7 @@ impl Config { /// * `player_1`- A [player](Player) /// * `player_2`- A [player](Player) (may be the same as `player_1`) /// * `score_totals` - Total score values for the players in the tournament - fn add_game(&self, player_1: Player, player_2: Player, score_totals: (Arc>, Arc>)) { + fn add_game(&self, player_1: Player, player_2: Player, score_totals: (Arc>, Arc>)) { let rounds = self.rounds; let show_games = self.show_games; self.threadpool.execute(move || { @@ -220,17 +220,27 @@ impl Config { } if let Ok(mut score) = score_totals.0.lock() { - *score += scores.0; + score.0 += scores.0; + score.1 += match scores.0.cmp(&scores.1) { + Ordering::Less => -1, + Ordering::Equal => 0, + Ordering::Greater => 1, + } } if let Ok(mut score) = score_totals.1.lock() { - *score += scores.1; + score.0 += scores.1; + score.1 += match scores.1.cmp(&scores.0) { + Ordering::Less => -1, + Ordering::Equal => 0, + Ordering::Greater => 1, + } } }); } } -/// Create a vector of atomically reference counted and mutable score counters. +/// Create a vector of atomically reference counted and mutable score and relative win counters. /// /// # Arguments /// @@ -239,14 +249,14 @@ impl Config { /// # Panics /// /// If `length == 0`. -fn init_scores(length: usize) -> Vec>> { +fn init_scores(length: usize) -> Vec>> { if length == 0 { panic!("Cannot initialize scores with a length of 0"); } let mut scores = Vec::new(); for _ in 0..length { - scores.push(Arc::new(Mutex::new(0))); + scores.push(Arc::new(Mutex::new((0, 0)))); } scores @@ -305,9 +315,9 @@ fn random_rounds(min: u32, max: u32) -> u32 { /// /// let scores_1 = run(&config_1, &players).unwrap(); /// -/// assert_eq!(scores_1, [(36, "1"), (5, "2")]); +/// assert_eq!([(scores_1[0].0, scores_1[0].2), (scores_1[1].0, scores_1[1].2)], [(36, "1"), (5, "2")]); /// ``` -pub fn run<'a>(config: &Config, players: &'a Vec) -> Result, &'static str> { +pub fn run<'a>(config: &Config, players: &'a Vec) -> Result, &'static str> { if players.len() < 2 { return Err("Too few players"); } @@ -334,9 +344,12 @@ pub fn run<'a>(config: &Config, players: &'a Vec) -> Result>(); - scores.sort(); + scores.sort_unstable_by(|a, b| a.0.cmp(&b.0)); Ok(scores.iter() .rev() @@ -366,8 +379,8 @@ mod tests { let scores_1 = run(&config_1, &players).unwrap(); let scores_2 = run(&config_2, &players).unwrap(); - assert_eq!(scores_1, [(36, "1"), (5, "2")]); - assert_eq!(scores_2, [(14, "1"), (3, "2")]); + assert_eq!([(scores_1[0].0, scores_1[0].2), (scores_1[1].0, scores_1[1].2)], [(36, "1"), (5, "2")]); + assert_eq!([(scores_2[0].0, scores_2[0].2), (scores_2[1].0, scores_2[1].2)], [(14, "1"), (3, "2")]); } #[test] diff --git a/src/main.rs b/src/main.rs index 6dacf0c..b6241a9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,7 @@ fn main() { } }; - println!("Program start\n"); + println!("\nTournament start\n"); let players = vec![ Player::with_name("Take back 1", take_back_once_prisoner), @@ -40,10 +40,15 @@ fn main() { let scores = run(&config, &players).unwrap(); - println!("{0} rounds!", config.rounds()); + println!("{0} rounds!\n", config.rounds()); + println!("no. program_name avg_score rel_win_ratio"); + println!("--------------------------------------------------------------"); + for (i, v) in scores.iter().enumerate() { - println!("{0}. {2} - {1:.2}", i + 1, v.0 as f32 / players.len() as f32, v.1); + let placement = format!("{}.", i + 1); + let ratio = format!("({:.2}%)", v.1 * 100.0); + println!("{0:<3} {2:<32} {1:<11.2} {3:<8}", placement, v.0 as f32 / players.len() as f32, v.2, ratio); } - println!("\nProgram end"); + println!("\nTournament end\n"); } \ No newline at end of file diff --git a/src/programs/prisoners.rs b/src/programs/prisoners.rs index 8871a7a..8769635 100644 --- a/src/programs/prisoners.rs +++ b/src/programs/prisoners.rs @@ -10,18 +10,6 @@ pub fn take_back_once_prisoner(last_moves: &[Move]) -> Color { Color::Green } -pub fn friendly(_last_moves: &[Move]) -> Color { - Color::Green -} - -pub fn evil(_last_moves: &[Move]) -> Color { - Color::Red -} - -pub fn blue(_last_moves: &[Move]) -> Color { - Color::Blue -} - pub fn tit_for_tat_prisoner(last_moves: &[Move]) -> Color { if let Some(last_move) = last_moves.last() { if last_move.1 == Color::Red { diff --git a/src/programs/simple.rs b/src/programs/simple.rs index 32eb8cd..7e0d2f7 100644 --- a/src/programs/simple.rs +++ b/src/programs/simple.rs @@ -1,5 +1,17 @@ use crate::programs::prelude::*; +pub fn friendly(_last_moves: &[Move]) -> Color { + Color::Green +} + +pub fn evil(_last_moves: &[Move]) -> Color { + Color::Red +} + +pub fn blue(_last_moves: &[Move]) -> Color { + Color::Blue +} + pub fn random(_last_moves: &[Move]) -> Color { *[Color::Red, Color::Green, Color::Blue].choose(&mut rand::thread_rng()).unwrap() }