1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
//Import standard/imported modules
use rand::Rng;

//Import source modules
use crate::person::Person;

/// # `People` trait
///
/// A `People` implementation is representative of a collection of `Person`s.  It is
/// implemented by the `Elevator` and `Floor` structs.  It defines a set of functions
/// for managing `Person`s in aggregate.
pub trait People {
    /// Expected to generate the number of tips to collect from the people
    fn gen_num_tips(&self, rng: &mut impl Rng) -> usize;

    /// Expected to determine the destination floors for all people and return it as
    /// a vector.
    fn get_dest_floors(&self) -> Vec<usize>;

    /// Expected to determine the total number of people and return it as a usize.
    fn get_num_people(&self) -> usize;

    /// Expected to determine the number of people waiting, that is, not at their
    /// desired floor.
    fn get_num_people_waiting(&self) -> usize;

    /// Expected to determine the number of people going to a particular floor
    fn get_num_people_going_to_floor(&self, floor_to: usize) -> usize;

    /// Expected to read the wait times from people waiting/not at their desired floor
    /// and aggregate the total into a usize.
    fn get_aggregate_wait_time(&self) -> usize;

    /// Expected to determine whether anyone in the collection of people are going to
    /// a given floor, returning a bool which is true if so, and false if not.
    fn are_people_going_to_floor(&self, floor_index: usize) -> bool;

    /// Expected to determine whether anyone in the collection of people is waiting/not
    /// at their desired floor, returning a bool which is true if so, and false if not.
    fn are_people_waiting(&self) -> bool;

    /// Expected to increment the wait times (by `1_usize`) among all people waiting/not
    /// at their desired floor.
    fn increment_wait_times(&mut self);

    /// Expected to reset the wait times (to `0_usize`) among all people who have a
    /// nonzero wait time and are on their desired floor.
    fn reset_wait_times(&mut self);
}

impl People for Vec<Person> {
    /// Generates the number of people among the collection of people who will tip.
    fn gen_num_tips(&self, rng: &mut impl Rng) -> usize {
        //Initialize a counter for the number of people who will tip
        let mut num_tips: usize = 0_usize;

        //Loop through the people and generate whether each person will tip
        for pers in self.iter() {
            if pers.gen_tip(rng) {
                num_tips += 1_usize;
            }
        }

        //Return the counter
        num_tips
    }

    /// Determines the destination floors for all people and returns it as a vector.
    fn get_dest_floors(&self) -> Vec<usize> {
        //Initialize a new vector of usizes
        let mut dest_floors: Vec<usize> = Vec::new();

        //Loop through the vector of persons
        for pers in self.iter() {
            //Add the dest floor to the vector
            let dest_floor = pers.floor_to;
            dest_floors.push(dest_floor);
        }

        //Return the destination floors vector
        dest_floors
    }

    /// Determines the total number of people and returns it as a usize.
     fn get_num_people(&self) -> usize {
        //Return the length of the vector
        self.len()
    }

    /// Determines the number of people waiting, that is, not at their desired floor.
    fn get_num_people_waiting(&self) -> usize {
        //Initialize a usize counting the numper of people waiting
        let mut num_waiting: usize = 0_usize;

        //Loop through the vector of persons
        for pers in self.iter() {
            //Skip if the person is not waiting
            if pers.floor_on == pers.floor_to {
                continue;
            }

            //If the person is waiting, increment the counter
            num_waiting += 1_usize;
        }

        //Return the counter
        num_waiting
    }

    /// Determines the number of people going to a particular floor
    fn get_num_people_going_to_floor(&self, floor_to: usize) -> usize {
        //Initialize a usize counting the number of people going to the floor
        let mut num_going_to_floor: usize = 0_usize;

        //Loop through the vector of persons
        for pers in self.iter() {
            //Skip if the person is not going to that floor
            if pers.floor_to != floor_to {
                continue;
            }

            //If the person is going to that floor, increment the counter
            num_going_to_floor += 1_usize;
        }

        //Return the counter
        num_going_to_floor
    }

    /// Reads the wait times from people waiting/not at their desired floor and aggregates
    /// the total into a usize.
    fn get_aggregate_wait_time(&self) -> usize {
        //Initialize a usize for the number of time steps the people spent waiting
        let mut aggregate_wait_time: usize = 0_usize;

        //Loop through the vector of persons
        for pers in self.iter() {
            //Increment the usize with their wait time
            aggregate_wait_time += pers.wait_time;
        }

        //Return the usize
        aggregate_wait_time
    }

    /// Determines whether anyone in the collection of people are going to a given floor,
    /// and returns a bool which is true if so, and false if not.
    fn are_people_going_to_floor(&self, floor_index: usize) -> bool {
        //Initialize a boolean tracking if people are going to the given floor
        let mut is_going_to_floor: bool = false;

        //Loop through the people on the elevator and check
        for pers in self.iter() {
            //If the person is not going to the given floor then skip
            if pers.floor_to != floor_index {
                continue;
            }

            //Otherwise update the boolean and break
            is_going_to_floor = true;
            break;
        }

        //Return the is_going_to_floor boolean
        is_going_to_floor
    }

    /// Determines whether anyone in the collection of people is waiting/not at their
    /// desired floor, and returns a bool which is true if so, and false if not.
    fn are_people_waiting(&self) -> bool {
        //Initialize a boolean tracking if people are waiting
        let mut is_waiting: bool = false;

        //Loop through the people and check if they are waiting
        for pers in self.iter() {
            //If the person is not waiting, then skip
            if pers.floor_on == pers.floor_to {
                continue;
            }

            //Otherwise update the boolean and break
            is_waiting = true;
            break;
        }

        //Return the is_going_to_floor boolean
        is_waiting
    }

    /// Increments the wait times (by `1_usize`) among all people waiting/not at
    /// their desired floor.
    fn increment_wait_times(&mut self) {
        //Loop through the people and increment their wait times
        for pers in self.iter_mut() {
            pers.increment_wait_time();
        }
    }

    /// Resets the wait times (to `0_usize`) among all people who have a nonzero
    /// wait time and are on their desired floor.
    fn reset_wait_times(&mut self) {
        //Loop through the people and reset their wait times
        for pers in self.iter_mut() {
            pers.reset_wait_time();
        }
    }
}