scarlet_queen_selector/
tournament.rs

1use std::{
2    collections::{HashMap, HashSet},
3    rc::Rc,
4};
5
6use scarlet_queen_core::{EachCrateIndividual, Individual, SelectorIndividualTrait};
7
8use crate::error::SelectorError;
9
10#[derive(Debug)]
11pub struct TournamentSelectorIndividual<T, const R: usize> {
12    individual: Rc<Individual<T>>,
13}
14
15impl<T, const R: usize> EachCrateIndividual for TournamentSelectorIndividual<T, R> {
16    type Item = T;
17
18    fn new(individual: &Rc<Individual<T>>) -> Self {
19        TournamentSelectorIndividual {
20            individual: Rc::clone(individual),
21        }
22    }
23
24    fn get_id(&self) -> usize {
25        self.individual.get_id()
26    }
27
28    fn get_value(&self) -> &T {
29        self.individual.get_value()
30    }
31
32    fn get_individual(&self) -> &Individual<T> {
33        &self.individual
34    }
35}
36
37impl<T, const R: usize> SelectorIndividualTrait<R> for TournamentSelectorIndividual<T, R> {
38    type Err = SelectorError;
39
40    fn selected_ids<'a, G>(
41        group: G,
42        scores: HashMap<usize, usize>,
43    ) -> Result<HashSet<usize>, Self::Err>
44    where
45        G: IntoIterator<Item = &'a Self>,
46        Self: 'a,
47    {
48        let group: Vec<&Self> = group.into_iter().collect::<Vec<&Self>>();
49
50        if group.len() < R {
51            return Err(SelectorError::TooFewGroupError);
52        };
53
54        let mut id_with_score: Vec<(usize, usize)> = group
55            .into_iter()
56            .map(|v| {
57                let id: usize = v.get_id();
58                scores
59                    .get(&id)
60                    .map_or(Err(SelectorError::BadScoreDataError), |&v| Ok((id, v)))
61            })
62            .collect::<Result<Vec<(usize, usize)>, SelectorError>>()?;
63
64        id_with_score.sort_by_key(|&(_, v)| -(v as isize));
65
66        Ok(id_with_score
67            .into_iter()
68            .take(R)
69            .map(|(id, _)| id)
70            .collect::<HashSet<usize>>())
71    }
72}
73
74#[cfg(test)]
75mod tests {
76    use std::{
77        collections::{HashMap, HashSet},
78        rc::Rc,
79    };
80
81    use scarlet_queen_core::{EachCrateIndividual, Individual, SelectorIndividualTrait};
82
83    use crate::tournament::TournamentSelectorIndividual;
84
85    #[test]
86    fn test_tournamentselectorindividual_selectorindividualtrait_selectedids() {
87        let group: Vec<TournamentSelectorIndividual<&'static str, 2>> = vec![
88            TournamentSelectorIndividual::new(&Rc::new(Individual::new_with_id(1, "A"))),
89            TournamentSelectorIndividual::new(&Rc::new(Individual::new_with_id(2, "A"))),
90            TournamentSelectorIndividual::new(&Rc::new(Individual::new_with_id(3, "B"))),
91            TournamentSelectorIndividual::new(&Rc::new(Individual::new_with_id(4, "B"))),
92            TournamentSelectorIndividual::new(&Rc::new(Individual::new_with_id(5, "C"))),
93            TournamentSelectorIndividual::new(&Rc::new(Individual::new_with_id(6, "C"))),
94        ];
95        let scores: HashMap<usize, usize> =
96            HashMap::from([(1, 10), (2, 10), (3, 20), (4, 20), (5, 30), (6, 30)]);
97
98        let selected = <TournamentSelectorIndividual<&'static str, 2> as SelectorIndividualTrait<
99            2,
100        >>::selected_ids(&group, scores)
101        .unwrap();
102        assert_eq!(selected, HashSet::from([5, 6]));
103    }
104}