random_pairings/
pairing_generator.rs1use crate::person::Person;
2
3use std::collections::VecDeque;
4
5use rand::{
6 seq::SliceRandom, Rng,
7};
8
9#[derive(Debug, Clone)]
10pub struct PairingGenerator {
11 people: Vec<Person>,
12}
13
14impl PairingGenerator {
15 pub fn new() -> Self {
16 PairingGenerator {
17 people: Vec::new(),
18 }
19 }
20
21 pub fn add_person(&mut self, name: &str) -> Result<(), String> {
22 if self.people.iter().any(|p| p.name == name) {
23 return Err(format!("Tried to add duplicate person: {}", name));
24 }
25
26 self.people.push(Person::new(name));
27
28 Ok(())
29 }
30
31 pub fn add_couple(&mut self, first_name: &str, second_name: &str) -> Result<(), String> {
32 if self.people.iter().any(|p| p.name == first_name) {
33 return Err(format!("Tried to add duplicate person: {}", first_name));
34 }
35 if self.people.iter().any(|p| p.name == second_name) {
36 return Err(format!("Tried to add duplicate person: {}", second_name));
37 }
38
39 self.people.push(Person::with_spouse(first_name, second_name));
40 self.people.push(Person::with_spouse(second_name, first_name));
41
42 Ok(())
43 }
44
45 pub fn generate_pairings<R>(&self, rng: &mut R) -> Vec<Person> where R: Rng + ?Sized {
46 let mut unassigned_people = self.people.clone();
47 let mut assigned_people: Vec<Person> = Vec::with_capacity(unassigned_people.len());
48 let mut shuffled = unassigned_people.clone();
49 shuffled.shuffle(rng);
50 let mut shuffled = VecDeque::from(shuffled);
51
52 while unassigned_people.len() > 0 {
53 let mut person = unassigned_people.pop().unwrap();
54 let mut choice = shuffled.pop_front().unwrap();
55 let mut name = choice.name.clone();
56 let mut retries = 0;
57 while !person.is_valid_choice(&name) {
58 if retries >= 2 {
59 let swap_index = assigned_people.iter().position(|p| p.is_valid_choice(&name) && person.is_valid_choice(p.choice.as_ref().unwrap())).unwrap();
60 name = match &assigned_people[swap_index].choice {
61 Some(name) => name.clone(),
62 None => panic!("Person with no choice on assigned list"),
63 };
64 assigned_people[swap_index].choice = Some(choice.name.clone());
65 break;
66 } else {
67 shuffled.push_back(choice);
68 choice = shuffled.pop_front().unwrap();
69 name = choice.name.clone();
70 retries += 1;
71 }
72 }
73 person.choice = Some(name.clone());
74 assigned_people.push(person);
75 }
76
77 assigned_people
78 }
79}