1#[derive(Debug, Clone, PartialEq)]
3pub struct MobType {
4 pub index: usize,
6 cost: usize,
8}
9
10impl MobType {
11 pub fn new(index: usize, cost: usize) -> Self {
12 MobType {
13 index: index,
14 cost: cost,
15 }
16 }
17}
18
19#[derive(Debug, Clone)]
20struct MobCostMap(Vec<(usize, usize)>);
21
22impl From<&Vec<MobType>> for MobCostMap {
23 fn from(mob_types: &Vec<MobType>) -> MobCostMap {
24 let mut map_cost_map_contents = mob_types
25 .iter()
26 .map(|e| (e.cost, e.index))
27 .collect::<Vec<(usize, usize)>>();
28 map_cost_map_contents.sort_by(|a, b| a.0.cmp(&b.0));
29 MobCostMap(map_cost_map_contents)
30 }
31}
32
33#[derive(Debug, PartialEq, Clone)]
35pub struct Wave {
36 pub wave_number: Option<usize>,
38 pub total_cost: usize,
40 pub mobs: Vec<MobType>,
42}
43
44impl Wave {
45 pub fn gen_from_max_total_cost(mut max_total_cost: usize, mob_types: &Vec<MobType>) -> Wave {
47 let mut mob_cost_map: MobCostMap = MobCostMap::from(mob_types);
48 let mut total_cost: usize = 0;
49 let mut mobs: Vec<MobType> = Vec::new();
50 while max_total_cost > 0 || mob_cost_map.0.len() > 0 {
51 if let Some(mob_cost) = mob_cost_map.0.last() {
52 if max_total_cost >= mob_cost.0 {
53 max_total_cost -= mob_cost.0;
54 total_cost += mob_cost.0;
55 mobs.push(MobType {
56 index: mob_cost.1,
57 cost: mob_cost.0,
58 });
59 } else {
60 mob_cost_map.0.remove(mob_cost_map.0.len() - 1);
61 }
62 } else {
63 break;
64 }
65 }
66 Wave {
67 wave_number: None,
68 total_cost: total_cost,
69 mobs: mobs,
70 }
71 }
72}
73
74#[derive(Debug, Clone)]
76pub struct Waves {
77 next_wave: usize,
79 cost_function: fn(usize) -> usize,
81 mob_types: Vec<MobType>,
83}
84
85impl Waves {
86 pub fn builder() -> WavesBuilder {
88 WavesBuilder {
89 next_wave: 1,
90 mob_types: Vec::new(),
91 cost_function: |wave_nr| wave_nr,
92 }
93 }
94 pub fn gen_single_current_wave(&self) -> Wave {
97 let max_total_cost: usize = (self.cost_function)(self.get_next_wave_number());
98 let wave: Wave = Wave::gen_from_max_total_cost(max_total_cost, &self.mob_types);
99 wave
100 }
101 pub fn get_next_wave_number(&self) -> usize {
103 self.next_wave
104 }
105}
106
107impl Iterator for Waves {
108 type Item = Wave;
109 fn next(&mut self) -> Option<Self::Item> {
110 let max_total_cost: usize = (self.cost_function)(self.next_wave);
111 let mut wave: Wave = Wave::gen_from_max_total_cost(max_total_cost, &self.mob_types);
112 wave.wave_number = Some(self.next_wave);
113 self.next_wave += 1;
114 Some(wave)
115 }
116}
117
118pub struct WavesBuilder {
119 next_wave: usize,
120 mob_types: Vec<MobType>,
121 cost_function: fn(usize) -> usize,
122}
123
124impl WavesBuilder {
125 pub fn add_mob_type(mut self, mob_type: MobType) -> WavesBuilder {
127 self.mob_types.push(mob_type);
128 self
129 }
130 pub fn add_mob_types(mut self, mut mob_types: Vec<MobType>) -> WavesBuilder {
132 self.mob_types.append(&mut mob_types);
133 self
134 }
135 pub fn with_mob_types(mut self, mob_types: Vec<MobType>) -> WavesBuilder {
137 self.mob_types = mob_types;
138 self
139 }
140 pub fn with_cost_function(mut self, f: fn(usize) -> usize) -> WavesBuilder {
142 self.cost_function = f;
143 self
144 }
145 pub fn with_starting_wave(mut self, starting_wave: usize) -> WavesBuilder {
147 self.next_wave = starting_wave;
148 self
149 }
150 pub fn build(self) -> Waves {
152 Waves {
153 next_wave: self.next_wave,
154 cost_function: self.cost_function,
155 mob_types: self.mob_types,
156 }
157 }
158}
159
160#[cfg(test)]
161mod tests {
162 use super::*;
163
164 #[test]
165 fn mob_cost_map_length() {
166 let mob_type_a = MobType { index: 1, cost: 1 };
167 let mob_type_b = MobType { index: 2, cost: 2 };
168 let mob_type_c = MobType { index: 3, cost: 3 };
169 let mob_types = vec![mob_type_a, mob_type_c, mob_type_b];
170 let mob_cost_map = MobCostMap::from(&mob_types);
171 println!("{:?}", mob_cost_map);
172 assert_eq!(mob_cost_map.0.len(), 3);
173 }
174
175 #[test]
176 fn gen_wave_from_max_total_cost_7_a() {
177 let mob_type_a = MobType { index: 1, cost: 1 };
178 let mob_type_b = MobType { index: 2, cost: 2 };
179 let mob_type_c = MobType { index: 3, cost: 3 };
180 let mob_types = vec![mob_type_a, mob_type_c, mob_type_b];
181 let wave: Wave = Wave::gen_from_max_total_cost(7, &mob_types);
182 println!("{:?}", wave);
183 assert_eq!(wave.total_cost, 7);
184 assert_eq!(wave.mobs.len(), 3);
185 }
186
187 #[test]
188 fn gen_wave_from_max_total_cost_8() {
189 let mob_type_a = MobType { index: 1, cost: 1 };
190 let mob_type_b = MobType { index: 2, cost: 2 };
191 let mob_type_c = MobType { index: 3, cost: 3 };
192 let mob_types = vec![mob_type_a, mob_type_c, mob_type_b];
193 let wave: Wave = Wave::gen_from_max_total_cost(8, &mob_types);
194 println!("{:?}", wave);
195 assert_eq!(wave.total_cost, 8);
196 assert_eq!(wave.mobs.len(), 3);
197 }
198
199 #[test]
200 fn gen_wave_from_max_total_cost_11() {
201 let mob_type_a = MobType { index: 1, cost: 1 };
202 let mob_type_b = MobType { index: 2, cost: 4 };
203 let mob_types = vec![mob_type_b, mob_type_a];
204 let wave: Wave = Wave::gen_from_max_total_cost(11, &mob_types);
205 println!("{:?}", wave);
206 assert_eq!(wave.total_cost, 11);
207 assert_eq!(wave.mobs.len(), 5);
208 }
209
210 #[test]
211 fn gen_wave_from_max_total_cost_7_b() {
212 let mob_type_a = MobType { index: 1, cost: 2 };
213 let mob_type_b = MobType { index: 2, cost: 4 };
214 let mob_types = vec![mob_type_b, mob_type_a];
215 let wave: Wave = Wave::gen_from_max_total_cost(7, &mob_types);
216 println!("{:?}", wave);
217 assert_eq!(wave.total_cost, 6);
218 assert_eq!(wave.mobs.len(), 2);
219 }
220
221 #[test]
222 fn roundtrip() {
223 let mob_type_a = MobType { index: 1, cost: 1 };
224 let mob_type_b = MobType { index: 2, cost: 3 };
225 let mob_type_c = MobType { index: 3, cost: 5 };
226 let mob_type_d = MobType { index: 4, cost: 7 };
227 let mob_types = vec![mob_type_a, mob_type_c, mob_type_b, mob_type_d];
228
229 let mob_cost_map = MobCostMap::from(&mob_types);
230 assert_eq!(mob_cost_map.0, [(1, 1), (3, 2), (5, 3), (7, 4)]);
231 println!("{:?}", mob_cost_map);
232
233 let mut waves = Waves::builder()
234 .with_mob_types(mob_types)
235 .with_starting_wave(2)
236 .with_cost_function(|wave| wave * 3)
237 .build();
238 println!("{:?}", waves);
239 let wave_1 = waves.next();
240 let wave_2 = waves.next();
241 let wave_3 = waves.next();
242 let wave_4 = waves.next();
243 let wave_5 = waves.next();
244 println!("{:?}", wave_1);
245 println!("{:?}", wave_2);
246 println!("{:?}", wave_3);
247 println!("{:?}", wave_4);
248 println!("{:?}", wave_5);
249 let test_wave_5 = Some(Wave {
250 wave_number: Some(6),
251 total_cost: 18,
252 mobs: vec![
253 MobType { index: 4, cost: 7 },
254 MobType { index: 4, cost: 7 },
255 MobType { index: 2, cost: 3 },
256 MobType { index: 1, cost: 1 },
257 ],
258 });
259 assert_eq!(wave_5, test_wave_5);
260 }
261}