From a4854a943e2c371b8c9d7ecbe9ec6518517c1c73 Mon Sep 17 00:00:00 2001 From: atomflunder <80397293+atomflunder@users.noreply.github.com> Date: Thu, 27 Oct 2022 18:50:29 +0200 Subject: [PATCH] Change functions from taking Vecs to taking Slices --- CHANGELOG.md | 4 +++ Cargo.toml | 2 +- src/dwz.rs | 18 ++++++------ src/egf.rs | 4 +-- src/elo.rs | 6 ++-- src/glicko.rs | 8 +++--- src/glicko2.rs | 8 +++--- src/glicko_boost.rs | 9 +++--- src/ingo.rs | 7 ++--- src/sticko.rs | 10 +++---- src/trueskill.rs | 68 +++++++++++++++++++++------------------------ src/uscf.rs | 10 +++---- src/weng_lin.rs | 24 ++++++++-------- 13 files changed, 86 insertions(+), 92 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b38a4e..df474bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ This is a broad overview of the changes that have been made over the lifespan of this library. +## v0.19.2 - 2022-10-27 + +- Change every function that takes a Vec to now take a Slice + ## v0.19.1 - 2022-10-26 - Add more From implementations for rating structs diff --git a/Cargo.toml b/Cargo.toml index e617f60..d481838 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "skillratings" -version = "0.19.1" +version = "0.19.2" edition = "2021" description = "Calculate a player's skill rating using algorithms like Elo, Glicko, Glicko-2, TrueSkill and many more." readme = "README.md" diff --git a/src/dwz.rs b/src/dwz.rs index 3cd93eb..30f45d3 100644 --- a/src/dwz.rs +++ b/src/dwz.rs @@ -220,7 +220,7 @@ pub fn dwz( #[must_use] /// The "traditional" way of calculating a DWZ Rating of a player in a rating period or tournament. /// -/// Takes in a player as an [`DWZRating`] and their results as a Vec of tuples containing the opponent as an [`DWZRating`] +/// Takes in a player as an [`DWZRating`] and their results as a Slice of tuples containing the opponent as an [`DWZRating`] /// and the outcome of the game as an [`Outcome`](Outcomes). /// /// All of the outcomes are from the perspective of the player. @@ -258,7 +258,7 @@ pub fn dwz( /// assert!((new_player.rating.round() - 1635.0).abs() < f64::EPSILON); /// assert_eq!(new_player.index, 18); /// ``` -pub fn dwz_rating_period(player: &DWZRating, results: &Vec<(DWZRating, Outcomes)>) -> DWZRating { +pub fn dwz_rating_period(player: &DWZRating, results: &[(DWZRating, Outcomes)]) -> DWZRating { // DWZ was designed to be used in tournaments, so we do not need to loop over the opponents here. let points = results.iter().map(|r| r.1.to_chess_points()).sum(); @@ -324,7 +324,7 @@ pub fn expected_score(player_one: &DWZRating, player_two: &DWZRating) -> (f64, f /// consider using [`DWZRating::from()`](DWZRating) if you have an [`EloRating`](crate::elo::EloRating) /// or [`DWZRating::new()`](DWZRating) if not. /// -/// Takes in the player's age and their results as a Vec of tuples containing the opponent and the outcome. +/// Takes in the player's age and their results as a Slice of tuples containing the opponent and the outcome. /// If the actual player's age is unavailable or unknown, choose something `>25`. /// /// This only returns a DWZ rating if the results include at least 5 matches, @@ -378,7 +378,7 @@ pub fn expected_score(player_one: &DWZRating, player_two: &DWZRating) -> (f64, f /// assert!((player.rating - 1491.0).abs() < f64::EPSILON); /// assert_eq!(player.index, 1); /// ``` -pub fn get_first_dwz(player_age: usize, results: &Vec<(DWZRating, Outcomes)>) -> Option { +pub fn get_first_dwz(player_age: usize, results: &[(DWZRating, Outcomes)]) -> Option { if results.len() < 5 { return None; } @@ -709,7 +709,7 @@ mod tests { #[allow(clippy::unwrap_used)] let player = get_first_dwz( 26, - &vec![ + &[ (o1, Outcomes::WIN), (o2, Outcomes::DRAW), (o3, Outcomes::LOSS), @@ -724,7 +724,7 @@ mod tests { let all_win_player = get_first_dwz( 17, - &vec![ + &[ (o1, Outcomes::WIN), (o2, Outcomes::WIN), (o3, Outcomes::WIN), @@ -737,7 +737,7 @@ mod tests { let all_lose_player = get_first_dwz( 17, - &vec![ + &[ (o1, Outcomes::LOSS), (o2, Outcomes::LOSS), (o3, Outcomes::LOSS), @@ -750,7 +750,7 @@ mod tests { let less_than_5 = get_first_dwz( 32, - &vec![ + &[ (o1, Outcomes::LOSS), (o2, Outcomes::WIN), (o3, Outcomes::DRAW), @@ -796,7 +796,7 @@ mod tests { #[allow(clippy::unwrap_used)] let bad_player = get_first_dwz( 26, - &vec![ + &[ (o1, Outcomes::LOSS), (o2, Outcomes::DRAW), (o3, Outcomes::LOSS), diff --git a/src/egf.rs b/src/egf.rs index f65ee2e..f53022f 100644 --- a/src/egf.rs +++ b/src/egf.rs @@ -185,7 +185,7 @@ pub fn egf( #[must_use] /// Calculates an [`EGFRating`] in a traditional way using a rating period, commonly used for tournaments. /// -/// Takes in a player as an [`EGFRating`], their results as a Vec of tuples containing the opponent as an [`EGFRating`], +/// Takes in a player as an [`EGFRating`], their results as a Slice of tuples containing the opponent as an [`EGFRating`], /// the outcome of the game as an [`Outcome`](Outcomes), and an [`EGFConfig`] where you can specify handicaps for the players. /// /// --- @@ -235,7 +235,7 @@ pub fn egf( /// ``` pub fn egf_rating_period( player: &EGFRating, - results: &Vec<(EGFRating, Outcomes, EGFConfig)>, + results: &[(EGFRating, Outcomes, EGFConfig)], ) -> EGFRating { // According to the EGF, the rating values are not updated in between games. // Only the change in rating is kept track of. diff --git a/src/elo.rs b/src/elo.rs index ebe54e8..345ea23 100644 --- a/src/elo.rs +++ b/src/elo.rs @@ -183,6 +183,7 @@ pub fn elo( ) } +#[must_use] /// Calculates an [`EloRating`] in a non-traditional way using a rating period, /// for compatibility with the other algorithms. /// @@ -218,10 +219,9 @@ pub fn elo( /// /// assert!((new_player.rating.round() - 1210.0).abs() < f64::EPSILON); /// ``` -#[must_use] pub fn elo_rating_period( player: &EloRating, - results: &Vec<(EloRating, Outcomes)>, + results: &[(EloRating, Outcomes)], config: &EloConfig, ) -> EloRating { let mut player_rating = player.rating; @@ -322,7 +322,7 @@ mod tests { let new_player = elo_rating_period( &player, - &vec![ + &[ (opponent1, Outcomes::WIN), (opponent2, Outcomes::DRAW), (opponent3, Outcomes::LOSS), diff --git a/src/glicko.rs b/src/glicko.rs index a594e7f..88734a2 100644 --- a/src/glicko.rs +++ b/src/glicko.rs @@ -239,13 +239,14 @@ pub fn glicko( ) } +#[must_use] /// The "traditional" way of calculating a [`GlickoRating`] of a player in a rating period. /// /// Note that in this case, all of the matches are considered to be played at once. /// This means that the player will not get updated in-between matches, as you might expect. /// This will result in *slightly* different results than if you were to use the [`glicko`] function in a loop. /// -/// Takes in a player as an [`GlickoRating`] and their results as a Vec of tuples containing the opponent as an [`GlickoRating`], +/// Takes in a player as an [`GlickoRating`] and their results as a Slice of tuples containing the opponent as an [`GlickoRating`], /// the outcome of the game as an [`Outcome`](Outcomes) and a [`GlickoConfig`]. /// /// The outcome of the match is in the perspective of the player. @@ -293,10 +294,9 @@ pub fn glicko( /// assert!((new_player.rating.round() - 1464.0).abs() < f64::EPSILON); /// assert!((new_player.deviation.round() - 151.0).abs() < f64::EPSILON); /// ``` -#[must_use] pub fn glicko_rating_period( player: &GlickoRating, - results: &Vec<(GlickoRating, Outcomes)>, + results: &[(GlickoRating, Outcomes)], config: &GlickoConfig, ) -> GlickoRating { let q = 10_f64.ln() / 400.0; @@ -558,7 +558,7 @@ mod tests { let (np, _) = glicko(&player, &opponent, &Outcomes::WIN); - let rp = glicko_rating_period(&player, &vec![(opponent, Outcomes::WIN)], &config); + let rp = glicko_rating_period(&player, &[(opponent, Outcomes::WIN)], &config); assert_eq!(rp, np); } diff --git a/src/glicko2.rs b/src/glicko2.rs index b8322a2..e0afcfd 100644 --- a/src/glicko2.rs +++ b/src/glicko2.rs @@ -280,13 +280,14 @@ pub fn glicko2( (player_one_new, player_two_new) } +#[must_use] /// The "traditional" way of calculating a [`Glicko2Rating`] of a player in a rating period. /// /// Note that in this case, all of the matches are considered to be played at once. /// This means that the player will not get updated in-between matches, as you might expect. /// This will result in *slightly* different results than if you were to use the [`glicko2`] function in a loop. /// -/// Takes in a player as an [`Glicko2Rating`] and their results as a Vec of tuples containing the opponent as an [`Glicko2Rating`], +/// Takes in a player as an [`Glicko2Rating`] and their results as a Slice of tuples containing the opponent as an [`Glicko2Rating`], /// the outcome of the game as an [`Outcome`](Outcomes) and a [`Glicko2Config`]. /// /// The outcome of the match is in the perspective of the player. @@ -337,10 +338,9 @@ pub fn glicko2( /// assert!((new_player.deviation.round() - 152.0).abs() < f64::EPSILON); /// assert!((new_player.volatility - 0.059995984286488495).abs() < f64::EPSILON); /// ``` -#[must_use] pub fn glicko2_rating_period( player: &Glicko2Rating, - results: &Vec<(Glicko2Rating, Outcomes)>, + results: &[(Glicko2Rating, Outcomes)], config: &Glicko2Config, ) -> Glicko2Rating { if results.is_empty() { @@ -855,7 +855,7 @@ mod tests { let (np, _) = glicko2(&player, &opponent, &Outcomes::WIN, &config); - let rp = glicko2_rating_period(&player, &vec![(opponent, Outcomes::WIN)], &config); + let rp = glicko2_rating_period(&player, &[(opponent, Outcomes::WIN)], &config); assert_eq!(rp, np); } diff --git a/src/glicko_boost.rs b/src/glicko_boost.rs index c00d5f4..1c3fee7 100644 --- a/src/glicko_boost.rs +++ b/src/glicko_boost.rs @@ -312,7 +312,7 @@ pub fn glicko_boost( #[must_use] /// The "traditional" way of calculating a [`GlickoBoostRating`] of a player in a rating period. /// -/// Takes in a player as an [`GlickoBoostRating`] and their results as a Vec of tuples containing the opponent as a [`GlickoBoostRating`], +/// Takes in a player as an [`GlickoBoostRating`] and their results as a Slice of tuples containing the opponent as a [`GlickoBoostRating`], /// the outcome of the game as an [`Outcome`](Outcomes) and a [`bool`] specifying if the player was playing as player one, and a [`GlickoBoostConfig`]. /// /// --- @@ -377,7 +377,7 @@ pub fn glicko_boost( /// ``` pub fn glicko_boost_rating_period( player: &GlickoBoostRating, - results: &Vec<(GlickoBoostRating, Outcomes, bool)>, + results: &[(GlickoBoostRating, Outcomes, bool)], config: &GlickoBoostConfig, ) -> GlickoBoostRating { let q = 10_f64.ln() / 400.0; @@ -650,8 +650,7 @@ mod tests { let config = GlickoBoostConfig::new(); let (np, _) = glicko_boost(&player, &opponent, &Outcomes::WIN, &config); - let rp = - glicko_boost_rating_period(&player, &vec![(opponent, Outcomes::WIN, true)], &config); + let rp = glicko_boost_rating_period(&player, &[(opponent, Outcomes::WIN, true)], &config); assert_eq!(np, rp); } @@ -734,7 +733,7 @@ mod tests { }; let decayed_player = decay_deviation(&player, &GlickoBoostConfig::new()); - let rp_player = glicko_boost_rating_period(&player, &vec![], &GlickoBoostConfig::new()); + let rp_player = glicko_boost_rating_period(&player, &[], &GlickoBoostConfig::new()); assert_eq!(decayed_player, rp_player); assert!((decayed_player.deviation - 64.669_444_203_475_88).abs() < f64::EPSILON); diff --git a/src/ingo.rs b/src/ingo.rs index b242543..bd6d717 100644 --- a/src/ingo.rs +++ b/src/ingo.rs @@ -171,7 +171,7 @@ pub fn ingo( #[must_use] /// The "traditional" way of calculating a [`IngoRating`] of a player in a rating period. /// -/// Takes in a player as an [`IngoRating`] and their results as a Vec of tuples containing the opponent as an [`IngoRating`], +/// Takes in a player as an [`IngoRating`] and their results as a Slice of tuples containing the opponent as an [`IngoRating`], /// and the outcome of the game as an [`Outcome`](Outcomes) /// /// The outcome of the match is in the perspective of the player. @@ -220,10 +220,7 @@ pub fn ingo( /// /// assert!((new_player.rating.round() - 126.0).abs() < f64::EPSILON); /// ``` -pub fn ingo_rating_period( - player: &IngoRating, - results: &Vec<(IngoRating, Outcomes)>, -) -> IngoRating { +pub fn ingo_rating_period(player: &IngoRating, results: &[(IngoRating, Outcomes)]) -> IngoRating { // Ingo was meant to be used in tournaments, so we do not need to loop over the opponents here. let development = age_to_devcoefficent(player.age); diff --git a/src/sticko.rs b/src/sticko.rs index 573927f..02537e0 100644 --- a/src/sticko.rs +++ b/src/sticko.rs @@ -332,7 +332,7 @@ pub fn sticko( #[must_use] /// The "traditional" way of calculating a [`StickoRating`] of a player in a rating period. /// -/// Takes in a player as an [`StickoRating`] and their results as a Vec of tuples containing the opponent as an [`StickoRating`], +/// Takes in a player as an [`StickoRating`] and their results as a Slice of tuples containing the opponent as an [`StickoRating`], /// the outcome of the game as an [`Outcome`](Outcomes) and a [`bool`] specifying if the player was playing as player one, and a [`StickoConfig`]. /// /// --- @@ -397,7 +397,7 @@ pub fn sticko( /// ``` pub fn sticko_rating_period( player: &StickoRating, - results: &Vec<(StickoRating, Outcomes, bool)>, + results: &[(StickoRating, Outcomes, bool)], config: &StickoConfig, ) -> StickoRating { let q = 10_f64.ln() / 400.0; @@ -696,7 +696,7 @@ mod tests { let new_player = sticko_rating_period( &player, - &vec![ + &[ (opponent1, Outcomes::WIN, true), (opponent2, Outcomes::LOSS, true), (opponent3, Outcomes::LOSS, true), @@ -707,7 +707,7 @@ mod tests { assert!((new_player.rating.round() - 1464.0).abs() < f64::EPSILON); assert!((new_player.deviation - 151.398_902_447_969_33).abs() < f64::EPSILON); - let after_player = sticko_rating_period(&player, &vec![], &config); + let after_player = sticko_rating_period(&player, &[], &config); assert_eq!(player, after_player); } @@ -733,7 +733,7 @@ mod tests { let (np, _) = sticko(&player, &opponent, &Outcomes::WIN, &config); - let rp = sticko_rating_period(&player, &vec![(opponent, Outcomes::WIN, true)], &config); + let rp = sticko_rating_period(&player, &[(opponent, Outcomes::WIN, true)], &config); assert_eq!(rp, np); } diff --git a/src/trueskill.rs b/src/trueskill.rs index 67ba857..3ac6857 100644 --- a/src/trueskill.rs +++ b/src/trueskill.rs @@ -280,7 +280,7 @@ pub fn trueskill( /// Calculates a [`TrueSkillRating`] in a non-traditional way using a rating period, /// for compatibility with the other algorithms. /// -/// Takes in a player as an [`TrueSkillRating`] and their results as a Vec of tuples containing the opponent as an [`TrueSkillRating`], +/// Takes in a player as an [`TrueSkillRating`] and their results as a Slice of tuples containing the opponent as an [`TrueSkillRating`], /// the outcome of the game as an [`Outcome`](Outcomes) and a [`TrueSkillConfig`]. /// /// The outcome of the match is in the perspective of the player. @@ -328,7 +328,7 @@ pub fn trueskill( /// ``` pub fn trueskill_rating_period( player: &TrueSkillRating, - results: &Vec<(TrueSkillRating, Outcomes)>, + results: &[(TrueSkillRating, Outcomes)], config: &TrueSkillConfig, ) -> TrueSkillRating { let mut player_rating = player.rating; @@ -386,7 +386,7 @@ pub fn trueskill_rating_period( #[must_use] /// Calculates the [`TrueSkillRating`] of two teams based on their ratings, uncertainties, and the outcome of the game. /// -/// Takes in two teams as a Vec of [`TrueSkillRating`]s, the outcome of the game as an [`Outcome`](Outcomes) and a [`TrueSkillConfig`]. +/// Takes in two teams as a Slice of [`TrueSkillRating`]s, the outcome of the game as an [`Outcome`](Outcomes) and a [`TrueSkillConfig`]. /// /// The outcome of the match is in the perspective of `team_one`. /// This means [`Outcomes::WIN`] is a win for `team_one` and [`Outcomes::LOSS`] is a win for `team_two`. @@ -435,13 +435,13 @@ pub fn trueskill_rating_period( /// assert!((team_two[1].rating - 36.210_764_756_738_115).abs() < f64::EPSILON); /// ``` pub fn trueskill_teams( - team_one: &Vec, - team_two: &Vec, + team_one: &[TrueSkillRating], + team_two: &[TrueSkillRating], outcome: &Outcomes, config: &TrueSkillConfig, ) -> (Vec, Vec) { if team_one.is_empty() || team_two.is_empty() { - return (team_one.clone(), team_two.clone()); + return (team_one.to_vec(), team_two.to_vec()); } let total_players = (team_one.len() + team_two.len()) as f64; @@ -574,7 +574,7 @@ pub fn match_quality( /// Gets the quality of the match, which is equal to the probability that the match will end in a draw. /// The higher the Value, the better the quality of the match. /// -/// Takes in two teams as Vec of [`TrueSkillRating`]s and returns the probability of a draw occurring as an [`f64`] between 1.0 and 0.0. +/// Takes in two teams as a Slice of [`TrueSkillRating`]s and returns the probability of a draw occurring as an [`f64`] between 1.0 and 0.0. /// /// Similar to [`match_quality`]. /// @@ -610,8 +610,8 @@ pub fn match_quality( /// assert!((quality - 0.084_108_145_418_343_24).abs() < f64::EPSILON); /// ``` pub fn match_quality_teams( - team_one: &Vec, - team_two: &Vec, + team_one: &[TrueSkillRating], + team_two: &[TrueSkillRating], config: &TrueSkillConfig, ) -> f64 { let total_players = (team_one.len() + team_two.len()) as f64; @@ -693,7 +693,7 @@ pub fn expected_score( #[must_use] /// Calculates the expected outcome of two teams based on TrueSkill. /// -/// Takes in two teams as Vec of [`TrueSkillRating`]s and returns the probability of victory for each player as an [`f64`] between 1.0 and 0.0. +/// Takes in two teams as a Slice of [`TrueSkillRating`]s and returns the probability of victory for each player as an [`f64`] between 1.0 and 0.0. /// 1.0 means a certain victory for the player, 0.0 means certain loss. /// Values near 0.5 mean a draw is likely to occur. /// @@ -736,8 +736,8 @@ pub fn expected_score( /// assert!(((exp2 * 100.0).round() - 88.0).abs() < f64::EPSILON); /// ``` pub fn expected_score_teams( - team_one: &Vec, - team_two: &Vec, + team_one: &[TrueSkillRating], + team_two: &[TrueSkillRating], config: &TrueSkillConfig, ) -> (f64, f64) { let player_count = (team_one.len() + team_two.len()) as f64; @@ -1058,7 +1058,7 @@ mod tests { let player = trueskill_rating_period( &player_one, - &vec![(player_two, Outcomes::WIN)], + &[(player_two, Outcomes::WIN)], &TrueSkillConfig::new(), ); @@ -1067,7 +1067,7 @@ mod tests { let player = trueskill_rating_period( &player_one, - &vec![ + &[ (player_two, Outcomes::WIN), (player_three, Outcomes::DRAW), (player_four, Outcomes::LOSS), @@ -1115,7 +1115,7 @@ mod tests { let p1 = trueskill_rating_period( &player_one, - &vec![(player_two, Outcomes::DRAW)], + &[(player_two, Outcomes::DRAW)], &TrueSkillConfig::new(), ); @@ -1172,8 +1172,8 @@ mod tests { }; let (team_one, team_two) = trueskill_teams( - &vec![player_one, player_two], - &vec![player_three, player_four], + &[player_one, player_two], + &[player_three, player_four], &Outcomes::WIN, &TrueSkillConfig::new(), ); @@ -1189,8 +1189,8 @@ mod tests { assert!((team_two[1].uncertainty - 4.767_945_180_134_836).abs() < f64::EPSILON); let (team_two, team_one) = trueskill_teams( - &vec![player_three, player_four], - &vec![player_one, player_two], + &[player_three, player_four], + &[player_one, player_two], &Outcomes::LOSS, &TrueSkillConfig::new(), ); @@ -1224,8 +1224,8 @@ mod tests { }; let (team_one, team_two) = trueskill_teams( - &vec![player_one, player_two], - &vec![player_three, player_four], + &[player_one, player_two], + &[player_three, player_four], &Outcomes::DRAW, &TrueSkillConfig::new(), ); @@ -1240,12 +1240,8 @@ mod tests { assert!((team_two[0].uncertainty - 3.832_975_356_683_128).abs() < f64::EPSILON); assert!((team_two[1].uncertainty - 2.930_957_525_591_959_5).abs() < f64::EPSILON); - let (team_one, _) = trueskill_teams( - &vec![player_one], - &vec![], - &Outcomes::WIN, - &TrueSkillConfig::new(), - ); + let (team_one, _) = + trueskill_teams(&[player_one], &[], &Outcomes::WIN, &TrueSkillConfig::new()); assert_eq!(team_one[0], player_one); } @@ -1265,8 +1261,8 @@ mod tests { &TrueSkillConfig::new(), ); let (tp1, tp2) = trueskill_teams( - &vec![player_one], - &vec![player_two], + &[player_one], + &[player_two], &Outcomes::WIN, &TrueSkillConfig::new(), ); @@ -1296,14 +1292,14 @@ mod tests { }; let quality = match_quality_teams( - &vec![player_one, player_two], - &vec![player_three, player_four], + &[player_one, player_two], + &[player_three, player_four], &TrueSkillConfig::new(), ); let quality2 = match_quality_teams( - &vec![player_three, player_four], - &vec![player_one, player_two], + &[player_three, player_four], + &[player_one, player_two], &TrueSkillConfig::new(), ); @@ -1333,8 +1329,8 @@ mod tests { }; let (exp1, exp2) = expected_score_teams( - &vec![player_one, player_two], - &vec![player_three, player_four], + &[player_one, player_two], + &[player_three, player_four], &TrueSkillConfig::new(), ); @@ -1356,7 +1352,7 @@ mod tests { rating: 48.0, uncertainty: 1.2, }; - #[allow(clippy::default_trait_access)] + let player_two = TrueSkillRating { rating: 12.0, ..Default::default() diff --git a/src/uscf.rs b/src/uscf.rs index 47ba7e8..89f3932 100644 --- a/src/uscf.rs +++ b/src/uscf.rs @@ -276,7 +276,7 @@ pub fn uscf( /// This means that the player will not get updated in-between matches, as you might expect. /// This will result in *slightly* different results than if you were to use the [`uscf`] function in a loop. /// -/// Takes in a player as an [`USCFRating`] and their results as a Vec of tuples containing the opponent as an [`USCFRating`], +/// Takes in a player as an [`USCFRating`] and their results as a Slice of tuples containing the opponent as an [`USCFRating`], /// the outcome of the game as an [`Outcome`](Outcomes) and a [`USCFConfig`]. /// /// The outcome of the match is in the perspective of the player. @@ -324,7 +324,7 @@ pub fn uscf( /// ``` pub fn uscf_rating_period( player: &USCFRating, - results: &Vec<(USCFRating, Outcomes)>, + results: &[(USCFRating, Outcomes)], config: &USCFConfig, ) -> USCFRating { if results.is_empty() { @@ -619,7 +619,7 @@ mod tests { games: 39, }; - let rp = uscf_rating_period(&player, &vec![], &USCFConfig::new()); + let rp = uscf_rating_period(&player, &[], &USCFConfig::new()); assert_eq!(player, rp); } @@ -638,7 +638,7 @@ mod tests { let config = USCFConfig::new(); let (np, _) = uscf(&player, &opponent, &Outcomes::WIN, &config); - let npr = uscf_rating_period(&player, &vec![(opponent, Outcomes::WIN)], &config); + let npr = uscf_rating_period(&player, &[(opponent, Outcomes::WIN)], &config); assert_eq!(np, npr); @@ -652,7 +652,7 @@ mod tests { }; let (np, _) = uscf(&player, &opponent, &Outcomes::WIN, &config); - let npr = uscf_rating_period(&player, &vec![(opponent, Outcomes::WIN)], &config); + let npr = uscf_rating_period(&player, &[(opponent, Outcomes::WIN)], &config); assert_eq!(np, npr); } diff --git a/src/weng_lin.rs b/src/weng_lin.rs index 4ea9b53..fd76288 100644 --- a/src/weng_lin.rs +++ b/src/weng_lin.rs @@ -148,7 +148,6 @@ impl Default for WengLinConfig { } #[must_use] -#[allow(clippy::needless_pass_by_value)] /// Calculates the [`WengLinRating`]s of two players based on their old ratings, uncertainties, and the outcome of the game. /// /// Takes in two players as [`WengLinRating`]s, an [`Outcome`](Outcomes), and a [`WengLinConfig`]. @@ -237,7 +236,7 @@ pub fn weng_lin( /// Calculates a [`WengLinRating`] in a non-traditional way using a rating period, /// for compatibility with the other algorithms. /// -/// Takes in a player as an [`WengLinRating`] and their results as a Vec of tuples containing the opponent as an [`WengLinRating`], +/// Takes in a player as an [`WengLinRating`] and their results as a Slice of tuples containing the opponent as an [`WengLinRating`], /// the outcome of the game as an [`Outcome`](Outcomes) and a [`WengLinConfig`]. /// /// The outcome of the match is in the perspective of the player. @@ -274,7 +273,7 @@ pub fn weng_lin( /// ``` pub fn weng_lin_rating_period( player: &WengLinRating, - results: &Vec<(WengLinRating, Outcomes)>, + results: &[(WengLinRating, Outcomes)], config: &WengLinConfig, ) -> WengLinRating { let mut player_rating = player.rating; @@ -313,7 +312,7 @@ pub fn weng_lin_rating_period( #[must_use] /// Calculates the [`WengLinRating`] of two teams based on their ratings, uncertainties, and the outcome of the game. /// -/// Takes in two teams as a Vec of [`WengLinRating`]s, the outcome of the game as an [`Outcome`](Outcomes) and a [`WengLinConfig`]. +/// Takes in two teams as a Slice of [`WengLinRating`]s, the outcome of the game as an [`Outcome`](Outcomes) and a [`WengLinConfig`]. /// /// The outcome of the match is in the perspective of `team_one`. /// This means [`Outcomes::WIN`] is a win for `team_one` and [`Outcomes::LOSS`] is a win for `team_two`. @@ -363,13 +362,13 @@ pub fn weng_lin_rating_period( /// assert!(((new_two[2].rating * 100.0).round() - 1843.0).abs() < f64::EPSILON); /// ``` pub fn weng_lin_teams( - team_one: &Vec, - team_two: &Vec, + team_one: &[WengLinRating], + team_two: &[WengLinRating], outcome: &Outcomes, config: &WengLinConfig, ) -> (Vec, Vec) { if team_one.is_empty() || team_two.is_empty() { - return (team_one.clone(), team_two.clone()); + return (team_one.to_vec(), team_two.to_vec()); } let team_one_uncertainties: f64 = team_one.iter().map(|p| p.uncertainty.powi(2)).sum(); @@ -495,10 +494,9 @@ pub fn expected_score( } #[must_use] -#[allow(clippy::ptr_arg)] /// Calculates the expected outcome of two teams based on the Bradley-Terry model. /// -/// Takes in two teams as Vec of [`WengLinRating`]s and a [`WengLinConfig`], +/// Takes in two teams as a Slice of [`WengLinRating`]s and a [`WengLinConfig`], /// and returns the probability of victory for each player as an [`f64`] between 1.0 and 0.0. /// /// 1.0 means a certain victory for the player, 0.0 means certain loss. @@ -540,8 +538,8 @@ pub fn expected_score( /// assert!(((exp1 * 100.0).round() - 21.0).abs() < f64::EPSILON); /// ``` pub fn expected_score_teams( - team_one: &Vec, - team_two: &Vec, + team_one: &[WengLinRating], + team_two: &[WengLinRating], config: &WengLinConfig, ) -> (f64, f64) { let team_one_ratings: f64 = team_one.iter().map(|p| p.rating).sum(); @@ -754,7 +752,7 @@ mod tests { let outcome = Outcomes::WIN; let (op1, op2) = weng_lin(&player_one, &player_two, &outcome, &config); - let (tp1, tp2) = weng_lin_teams(&vec![player_one], &vec![player_two], &outcome, &config); + let (tp1, tp2) = weng_lin_teams(&[player_one], &[player_two], &outcome, &config); assert_eq!(op1, tp1[0]); assert_eq!(op2, tp2[0]); @@ -867,7 +865,7 @@ mod tests { let rating_player = weng_lin_rating_period( &player, - &vec![ + &[ (opponent_one, Outcomes::WIN), (opponent_two, Outcomes::DRAW), (opponent_two, Outcomes::LOSS),