From 4acb26b702eb9088c8d97ce4621193ca3ba4f355 Mon Sep 17 00:00:00 2001 From: Nicolas <> Date: Sun, 3 Apr 2022 14:43:14 +0200 Subject: [PATCH] Add trait for mocking --- src/fill/factory.rs | 81 +++++++++++++++++++++++++++++++++++++++++++++ src/fill/mod.rs | 35 ++------------------ src/vec.rs | 45 +++++++++++++++++++++++-- 3 files changed, 126 insertions(+), 35 deletions(-) create mode 100644 src/fill/factory.rs diff --git a/src/fill/factory.rs b/src/fill/factory.rs new file mode 100644 index 0000000..0abe083 --- /dev/null +++ b/src/fill/factory.rs @@ -0,0 +1,81 @@ +use clap::ArgEnum; +use rand::prelude::IteratorRandom; +use rand::Rng; +use crate::fill::FillMode; +use crate::fill::level::LevelFillMode; +use crate::vec::Vector; + +#[derive(Copy, Clone, ArgEnum)] +pub enum FillModeEnum { + Circle, + Level, + Stripe +} + +pub trait FillModeFactory { + fn create(&self, mode: FillModeEnum, size: Vector) -> Box; + + fn choose(&self, options: Vec, rng: &mut impl Rng) -> FillModeEnum; +} + +pub struct SimpleFillModeFactory; + +impl SimpleFillModeFactory { + pub fn new() -> Self { + Self { } + } +} + +impl FillModeFactory for SimpleFillModeFactory { + fn create(&self, mode: FillModeEnum, _: Vector) -> Box { + match mode { + FillModeEnum::Circle => todo!(), + FillModeEnum::Level => Box::new(LevelFillMode::new()), + FillModeEnum::Stripe => todo!() + } + } + + fn choose(&self, mut options: Vec, rng: &mut impl Rng) -> FillModeEnum { + if options.is_empty() { + options.push(FillModeEnum::Circle); + options.push(FillModeEnum::Level); + options.push(FillModeEnum::Stripe); + } + options.into_iter().choose_stable(rng).unwrap() + } +} + +#[cfg(test)] +mod test { + use rand::rngs::mock::StepRng; + use super::*; + + #[test] + fn create() { + let factory = SimpleFillModeFactory::new(); + let size = Vector::ZERO; + + factory.create(FillModeEnum::Circle, size); + factory.create(FillModeEnum::Level, size); + factory.create(FillModeEnum::Stripe, size); + } + + #[test] + fn choose_from_all() { + let rng = &mut StepRng::new(0, 1); + + let factory = SimpleFillModeFactory::new(); + + assert!(matches!(factory.choose(Vec::new(), rng), FillModeEnum::Stripe)); + } + + #[test] + fn choose_from_options() { + let rng = &mut StepRng::new(0, 1); + let options = vec![FillModeEnum::Circle]; + + let factory = SimpleFillModeFactory::new(); + + assert!(matches!(factory.choose(options, rng), FillModeEnum::Circle)); + } +} \ No newline at end of file diff --git a/src/fill/mod.rs b/src/fill/mod.rs index 83505f3..c5d4c6c 100644 --- a/src/fill/mod.rs +++ b/src/fill/mod.rs @@ -1,42 +1,11 @@ mod level; -use clap::ArgEnum; -use rand::prelude::IteratorRandom; -use rand::Rng; -use crate::fill::level::LevelFillMode; +pub mod factory; + use crate::vec::Vector; /// Used to choose the colors of characters. pub trait FillMode { /// Gets the color for this character. - /// # Arguments - /// * `level`: - /// * `pos`: - /// - /// returns: f32 fn sample(&self, level: f32, pos: Vector) -> f32; -} - -#[derive(Copy, Clone, ArgEnum)] -pub enum FillModeEnum { - Circle, - Level, - Stripe -} - -pub fn choose_fill_mode(mut options: Vec, rng: &mut impl Rng) -> FillModeEnum { - if options.is_empty() { - options.push(FillModeEnum::Circle); - options.push(FillModeEnum::Level); - options.push(FillModeEnum::Stripe); - } - options.into_iter().choose(rng).unwrap() -} - -pub fn create_fill_mode(mode: FillModeEnum, _: Vector) -> Box { - match mode { - FillModeEnum::Circle => todo!(), - FillModeEnum::Level => Box::new(LevelFillMode::new()), - FillModeEnum::Stripe => todo!() - } } \ No newline at end of file diff --git a/src/vec.rs b/src/vec.rs index 237f74c..90ce8d4 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -6,7 +6,9 @@ pub struct Vector { } impl Vector { - pub fn new(x: f32, y: f32) -> Self { + pub const ZERO: Vector = Vector::new(0.0, 0.0); + + pub const fn new(x: f32, y: f32) -> Self { Self { x, y } } @@ -15,6 +17,45 @@ impl Vector { /// * `x`: The x axis of the terminal character. /// * `y`: The y axis of the terminal character. pub fn from_terminal(x: usize, y: usize) -> Self { - Vector::new(x as f32, y as f32 * 2.0) + Self::new(x as f32, y as f32 * 2.0) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn new() { + let vec = Vector::new(3.0, 5.0); + + assert_eq!(3.0, vec.x); + assert_eq!(5.0, vec.y); + } + + #[test] + fn from_terminal() { + let vec = Vector::from_terminal(2, 4); + + assert_eq!(2.0, vec.x); + assert_eq!(8.0, vec.y); + } + + #[test] + fn copy() { + let vec = Vector::new(2.0, 4.0); + let copy = vec; + + assert_eq!(vec.x, copy.x); + assert_eq!(vec.y, copy.y); + } + + #[test] + fn clone() { + let vec = Vector::new(2.0, 4.0); + let clone = vec.clone(); + + assert_eq!(vec.x, clone.x); + assert_eq!(vec.y, clone.y); } } \ No newline at end of file