2021-08-06 23:27:41 -04:00
|
|
|
use crate::color::Rgb;
|
2021-08-15 13:43:27 -04:00
|
|
|
use serde::{Deserialize, Serialize};
|
2021-08-12 21:06:22 -04:00
|
|
|
use std::collections::vec_deque;
|
2021-08-21 14:02:08 -04:00
|
|
|
use std::iter;
|
2021-07-31 14:29:21 -04:00
|
|
|
|
2021-08-01 19:38:17 -04:00
|
|
|
pub mod collide;
|
|
|
|
pub mod fade;
|
2021-08-15 14:18:18 -04:00
|
|
|
pub mod flashing;
|
2021-08-01 19:38:17 -04:00
|
|
|
pub mod moving_pixel;
|
|
|
|
pub mod moving_rainbow;
|
2021-08-09 21:28:42 -04:00
|
|
|
pub mod orb;
|
2021-08-01 19:38:17 -04:00
|
|
|
pub mod solid;
|
2021-08-21 14:02:08 -04:00
|
|
|
pub use collide::{Collide, CollideParams};
|
|
|
|
pub use fade::{Fade, FadeParams};
|
|
|
|
pub use flashing::{Flashing, FlashingParams};
|
|
|
|
pub use moving_pixel::{MovingPixel, MovingPixelParams};
|
|
|
|
pub use moving_rainbow::{MovingRainbow, MovingRainbowParams};
|
|
|
|
pub use orb::{Orb, OrbParams};
|
|
|
|
pub use solid::{Solid, SolidParams};
|
|
|
|
|
|
|
|
pub trait FormRender {
|
|
|
|
fn render(&self) -> String;
|
|
|
|
}
|
|
|
|
pub trait InputRender {
|
|
|
|
fn render(&self, name: &str) -> String;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl InputRender for bool {
|
|
|
|
fn render(&self, name: &str) -> String {
|
|
|
|
format!(
|
2021-08-21 15:24:21 -04:00
|
|
|
r#"<label for="{name}">{name}</label><input type="checkbox" name="{name}" {}/>"#,
|
2021-08-21 14:02:08 -04:00
|
|
|
if *self { " checked" } else { "" },
|
2021-08-21 15:24:21 -04:00
|
|
|
name = name,
|
2021-08-21 14:02:08 -04:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl InputRender for Rgb {
|
|
|
|
fn render(&self, name: &str) -> String {
|
|
|
|
format!(
|
2021-08-21 21:45:55 -04:00
|
|
|
r#"<label for="{name}">{name}</label><input type="color" value="{}" name="{name}" />"#,
|
2021-08-21 14:02:08 -04:00
|
|
|
self.to_hex_str(),
|
2021-08-21 15:24:21 -04:00
|
|
|
name = name,
|
2021-08-21 14:02:08 -04:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl InputRender for Vec<Rgb> {
|
|
|
|
fn render(&self, name: &str) -> String {
|
|
|
|
self.iter()
|
|
|
|
.chain(iter::once(&Rgb::default()))
|
|
|
|
.enumerate()
|
|
|
|
.fold(String::new(), |acc, (i, c)| {
|
|
|
|
acc + &c.render(&format!("{}-{}", name, i)) + "\n"
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl InputRender for u8 {
|
|
|
|
fn render(&self, name: &str) -> String {
|
|
|
|
format!(
|
2021-08-21 15:24:21 -04:00
|
|
|
r#"<label for="{name}">{name}</label><input type="number" max="255" min="0" step="1" value="{}" name="{name}" />"#,
|
|
|
|
self,
|
|
|
|
name = name,
|
2021-08-21 14:02:08 -04:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
2021-07-31 14:29:21 -04:00
|
|
|
|
2021-08-21 15:24:21 -04:00
|
|
|
impl InputRender for u16 {
|
|
|
|
fn render(&self, name: &str) -> String {
|
|
|
|
format!(
|
|
|
|
r#"<label for="{name}">{name}</label><input type="number" max="65535" min="0" step="1" value="{}" name="{name}" />"#,
|
|
|
|
self,
|
|
|
|
name = name,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
2021-08-12 21:06:22 -04:00
|
|
|
pub enum Parameters {
|
2021-08-21 14:02:08 -04:00
|
|
|
Collide(CollideParams),
|
|
|
|
Fade(FadeParams),
|
|
|
|
MovingPixel(MovingPixelParams),
|
|
|
|
MovingRainbow(MovingRainbowParams),
|
|
|
|
Orb(OrbParams),
|
|
|
|
Solid(SolidParams),
|
|
|
|
Flashing(FlashingParams),
|
2021-08-10 17:44:03 -04:00
|
|
|
}
|
|
|
|
|
2021-08-21 15:24:21 -04:00
|
|
|
impl Default for Parameters {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self::Solid(SolidParams::default())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FormRender for Parameters {
|
|
|
|
fn render(&self) -> String {
|
|
|
|
match self {
|
|
|
|
Self::Collide(ref p) => p.render(),
|
|
|
|
Self::Fade(ref p) => p.render(),
|
|
|
|
Self::MovingPixel(ref p) => p.render(),
|
|
|
|
Self::MovingRainbow(ref p) => p.render(),
|
|
|
|
Self::Orb(ref p) => p.render(),
|
|
|
|
Self::Solid(ref p) => p.render(),
|
|
|
|
Self::Flashing(ref p) => p.render(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-12 21:06:22 -04:00
|
|
|
impl Parameters {
|
2021-08-21 15:24:21 -04:00
|
|
|
pub fn default_with_name(name: &str) -> Option<Self> {
|
|
|
|
match name {
|
|
|
|
"Collide" => Some(Self::Collide(CollideParams::default())),
|
|
|
|
"Fade" => Some(Self::Fade(FadeParams::default())),
|
|
|
|
"MovingPixel" => Some(Self::MovingPixel(MovingPixelParams::default())),
|
|
|
|
"MovingRainbow" => Some(Self::MovingRainbow(MovingRainbowParams::default())),
|
|
|
|
"Orb" => Some(Self::Orb(OrbParams::default())),
|
|
|
|
"Solid" => Some(Self::Solid(SolidParams::default())),
|
|
|
|
"Flashing" => Some(Self::Flashing(FlashingParams::default())),
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
2021-08-21 15:51:10 -04:00
|
|
|
pub const fn get_name(&self) -> &str {
|
2021-08-21 15:24:21 -04:00
|
|
|
match self {
|
|
|
|
Self::Collide(_) => "Collide",
|
|
|
|
Self::Fade(_) => "Fade",
|
|
|
|
Self::MovingPixel(_) => "MovingPixel",
|
|
|
|
Self::MovingRainbow(_) => "MovingRainbow",
|
|
|
|
Self::Orb(_) => "Orb",
|
|
|
|
Self::Solid(_) => "Solid",
|
|
|
|
Self::Flashing(_) => "Flashing",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pub const fn get_names() -> &'static [&'static str] {
|
|
|
|
&[
|
|
|
|
"Solid",
|
|
|
|
"Collide",
|
|
|
|
"Fade",
|
|
|
|
"MovingPixel",
|
|
|
|
"MovingRainbow",
|
|
|
|
"Orb",
|
|
|
|
"Flashing",
|
|
|
|
]
|
|
|
|
}
|
2021-08-15 14:18:18 -04:00
|
|
|
pub fn into_pattern(self) -> Box<dyn Pattern + Send + Sync> {
|
2021-08-10 17:44:03 -04:00
|
|
|
match self {
|
2021-08-21 14:02:08 -04:00
|
|
|
Self::Collide(ref p) => Box::new(Collide::new(p)),
|
|
|
|
Self::Fade(ref p) => Box::new(Fade::new(p)),
|
|
|
|
Self::MovingPixel(ref p) => Box::new(MovingPixel::new(p)),
|
|
|
|
Self::MovingRainbow(ref p) => Box::new(MovingRainbow::new(p)),
|
|
|
|
Self::Orb(ref p) => Box::new(Orb::new(p)),
|
|
|
|
Self::Solid(ref p) => Box::new(Solid::new(p)),
|
|
|
|
Self::Flashing(ref p) => Box::new(Flashing::new(p)),
|
2021-08-10 17:44:03 -04:00
|
|
|
}
|
|
|
|
}
|
2021-08-09 23:13:38 -04:00
|
|
|
}
|
|
|
|
|
2021-08-10 17:44:03 -04:00
|
|
|
pub trait Pattern: std::fmt::Debug + Send + Sync {
|
2021-08-06 20:32:16 -04:00
|
|
|
fn init(&mut self, num_lights: u16) -> Result<(), ()>;
|
|
|
|
fn step(&mut self) -> Result<bool, ()>;
|
2021-08-12 21:06:22 -04:00
|
|
|
fn get_strip(&self) -> vec_deque::Iter<Rgb>;
|
2021-07-31 14:29:21 -04:00
|
|
|
}
|
|
|
|
|
2021-08-01 19:38:17 -04:00
|
|
|
// #[cfg(test)]
|
|
|
|
// mod tests {
|
|
|
|
// use super::*;
|
|
|
|
// const NUM_LIGHTS: u16 = 10;
|
2021-08-06 23:27:41 -04:00
|
|
|
// fn test_strip() -> Vec<Rgb> {
|
2021-08-01 19:38:17 -04:00
|
|
|
// vec![color::BLACK; NUM_LIGHTS.into()]
|
|
|
|
// }
|
|
|
|
// #[test]
|
|
|
|
// fn moving_pixel() {
|
2021-08-06 23:27:41 -04:00
|
|
|
// let color = Rgb(123, 152, 89);
|
2021-08-01 19:38:17 -04:00
|
|
|
// let mut pat = MovingPixel::new(color.clone());
|
|
|
|
// let mut strip = test_strip();
|
|
|
|
|
|
|
|
// assert!(pat.init(&mut strip, NUM_LIGHTS).is_ok());
|
|
|
|
// // One is my color
|
|
|
|
// assert_eq!(strip.iter().filter(|c| **c == color).count(), 1);
|
|
|
|
// // The rest are off
|
|
|
|
// assert_eq!(
|
|
|
|
// strip.iter().filter(|c| **c == color::BLACK).count(),
|
|
|
|
// (NUM_LIGHTS - 1).into()
|
|
|
|
// );
|
|
|
|
// pat.step(&mut strip);
|
|
|
|
// // One is my color
|
|
|
|
// assert_eq!(strip.iter().filter(|c| **c == color).count(), 1);
|
|
|
|
// // The rest are off
|
|
|
|
// assert_eq!(
|
|
|
|
// strip.iter().filter(|c| **c == color::BLACK).count(),
|
|
|
|
// (NUM_LIGHTS - 1).into()
|
|
|
|
// );
|
|
|
|
// }
|
|
|
|
// #[test]
|
|
|
|
// fn solid() {}
|
|
|
|
// #[test]
|
|
|
|
// fn moving_rainbow() {}
|
|
|
|
// #[test]
|
|
|
|
// fn fade() {}
|
|
|
|
// #[test]
|
|
|
|
// fn collide() {}
|
|
|
|
// }
|