#[derive(Debug, Clone, PartialEq)]
pub struct MobType {
index: usize,
cost: usize,
}
impl MobType {
pub fn new(index: usize, cost: usize) -> Self {
MobType {
index: index,
cost: cost,
}
}
}
#[derive(Debug, Clone)]
struct MobCostMap(Vec<(usize, usize)>);
impl From<&Vec<MobType>> for MobCostMap {
fn from(mob_types: &Vec<MobType>) -> MobCostMap {
let mut map_cost_map_contents = mob_types
.iter()
.map(|e| (e.cost, e.index))
.collect::<Vec<(usize, usize)>>();
map_cost_map_contents.sort_by(|a, b| a.0.cmp(&b.0));
MobCostMap(map_cost_map_contents)
}
}
#[derive(Debug, PartialEq)]
pub struct Wave {
wave_number: Option<usize>,
total_cost: usize,
mobs: Vec<MobType>,
}
impl Wave {
pub fn gen_from_max_total_cost(mut max_total_cost: usize, mob_types: &Vec<MobType>) -> Wave {
let mut mob_cost_map: MobCostMap = MobCostMap::from(mob_types);
let mut total_cost: usize = 0;
let mut mobs: Vec<MobType> = Vec::new();
while max_total_cost > 0 || mob_cost_map.0.len() > 0 {
if let Some(mob_cost) = mob_cost_map.0.last() {
if max_total_cost >= mob_cost.0 {
max_total_cost -= mob_cost.0;
total_cost += mob_cost.0;
mobs.push(MobType {
index: mob_cost.1,
cost: mob_cost.0,
});
} else {
mob_cost_map.0.remove(mob_cost_map.0.len() - 1);
}
} else {
break;
}
}
Wave {
wave_number: None,
total_cost: total_cost,
mobs: mobs,
}
}
}
#[derive(Debug, Clone)]
pub struct Waves {
next_wave: usize,
cost_function: fn(usize) -> usize,
mob_types: Vec<MobType>,
}
impl Waves {
pub fn builder() -> WavesBuilder {
WavesBuilder {
next_wave: 1,
mob_types: Vec::new(),
cost_function: |wave_nr| wave_nr,
}
}
}
impl Iterator for Waves {
type Item = Wave;
fn next(&mut self) -> Option<Self::Item> {
let max_total_cost: usize = (self.cost_function)(self.next_wave);
let mut wave: Wave = Wave::gen_from_max_total_cost(max_total_cost, &self.mob_types);
wave.wave_number = Some(self.next_wave);
self.next_wave += 1;
Some(wave)
}
}
pub struct WavesBuilder {
next_wave: usize,
mob_types: Vec<MobType>,
cost_function: fn(usize) -> usize,
}
impl WavesBuilder {
pub fn add_mob_type(mut self, mob_type: MobType) -> WavesBuilder {
self.mob_types.push(mob_type);
self
}
pub fn add_mob_types(mut self, mut mob_types: Vec<MobType>) -> WavesBuilder {
self.mob_types.append(&mut mob_types);
self
}
pub fn with_mob_types(mut self, mob_types: Vec<MobType>) -> WavesBuilder {
self.mob_types = mob_types;
self
}
pub fn with_cost_function(mut self, f: fn(usize) -> usize) -> WavesBuilder {
self.cost_function = f;
self
}
pub fn with_starting_wave(mut self, starting_wave: usize) -> WavesBuilder {
self.next_wave = starting_wave;
self
}
pub fn build(self) -> Waves {
Waves {
next_wave: self.next_wave,
cost_function: self.cost_function,
mob_types: self.mob_types,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn mob_cost_map_length() {
let mob_type_a = MobType { index: 1, cost: 1 };
let mob_type_b = MobType { index: 2, cost: 2 };
let mob_type_c = MobType { index: 3, cost: 3 };
let mob_types = vec![mob_type_a, mob_type_c, mob_type_b];
let mob_cost_map = MobCostMap::from(&mob_types);
println!("{:?}", mob_cost_map);
assert_eq!(mob_cost_map.0.len(), 3);
}
#[test]
fn gen_wave_from_max_total_cost_7_a() {
let mob_type_a = MobType { index: 1, cost: 1 };
let mob_type_b = MobType { index: 2, cost: 2 };
let mob_type_c = MobType { index: 3, cost: 3 };
let mob_types = vec![mob_type_a, mob_type_c, mob_type_b];
let wave: Wave = Wave::gen_from_max_total_cost(7, &mob_types);
println!("{:?}", wave);
assert_eq!(wave.total_cost, 7);
assert_eq!(wave.mobs.len(), 3);
}
#[test]
fn gen_wave_from_max_total_cost_8() {
let mob_type_a = MobType { index: 1, cost: 1 };
let mob_type_b = MobType { index: 2, cost: 2 };
let mob_type_c = MobType { index: 3, cost: 3 };
let mob_types = vec![mob_type_a, mob_type_c, mob_type_b];
let wave: Wave = Wave::gen_from_max_total_cost(8, &mob_types);
println!("{:?}", wave);
assert_eq!(wave.total_cost, 8);
assert_eq!(wave.mobs.len(), 3);
}
#[test]
fn gen_wave_from_max_total_cost_11() {
let mob_type_a = MobType { index: 1, cost: 1 };
let mob_type_b = MobType { index: 2, cost: 4 };
let mob_types = vec![mob_type_b, mob_type_a];
let wave: Wave = Wave::gen_from_max_total_cost(11, &mob_types);
println!("{:?}", wave);
assert_eq!(wave.total_cost, 11);
assert_eq!(wave.mobs.len(), 5);
}
#[test]
fn gen_wave_from_max_total_cost_7_b() {
let mob_type_a = MobType { index: 1, cost: 2 };
let mob_type_b = MobType { index: 2, cost: 4 };
let mob_types = vec![mob_type_b, mob_type_a];
let wave: Wave = Wave::gen_from_max_total_cost(7, &mob_types);
println!("{:?}", wave);
assert_eq!(wave.total_cost, 6);
assert_eq!(wave.mobs.len(), 2);
}
#[test]
fn roundtrip() {
let mob_type_a = MobType { index: 1, cost: 1 };
let mob_type_b = MobType { index: 2, cost: 3 };
let mob_type_c = MobType { index: 3, cost: 5 };
let mob_type_d = MobType { index: 4, cost: 7 };
let mob_types = vec![mob_type_a, mob_type_c, mob_type_b, mob_type_d];
let mob_cost_map = MobCostMap::from(&mob_types);
assert_eq!(mob_cost_map.0, [(1, 1), (3, 2), (5, 3), (7, 4)]);
println!("{:?}", mob_cost_map);
let mut waves = Waves::builder()
.with_mob_types(mob_types)
.with_starting_wave(2)
.with_cost_function(|wave| wave * 3)
.build();
println!("{:?}", waves);
let wave_1 = waves.next();
let wave_2 = waves.next();
let wave_3 = waves.next();
let wave_4 = waves.next();
let wave_5 = waves.next();
println!("{:?}", wave_1);
println!("{:?}", wave_2);
println!("{:?}", wave_3);
println!("{:?}", wave_4);
println!("{:?}", wave_5);
let test_wave_5 = Some(Wave {
wave_number: Some(6),
total_cost: 18,
mobs: vec![
MobType { index: 4, cost: 7 },
MobType { index: 4, cost: 7 },
MobType { index: 2, cost: 3 },
MobType { index: 1, cost: 1 },
],
});
assert_eq!(wave_5, test_wave_5);
}
}