add fill_unstable and use rust fmt

This commit is contained in:
Tobias Ollive 2022-03-12 20:52:37 +01:00
parent ae215ce252
commit 4dd5587b49
13 changed files with 127 additions and 77 deletions

View File

@ -33,7 +33,6 @@ async fn main() -> bluer::Result<()> {
let spectacle = Spectacle::from(config); let spectacle = Spectacle::from(config);
let spectacle = Arc::new(Mutex::new(spectacle)); let spectacle = Arc::new(Mutex::new(spectacle));
let adapter = bluetooth::create_session().await?; let adapter = bluetooth::create_session().await?;
let (tx_scan, rx_scan) = mpsc::channel(3); let (tx_scan, rx_scan) = mpsc::channel(3);

View File

@ -1,27 +1,29 @@
mod scanner; mod blink;
mod fade;
mod color_wipe; mod color_wipe;
mod rainbow; mod fade;
mod fade_random;
mod fade_unstable;
mod fill_random; mod fill_random;
mod fill_unstable; mod fill_unstable;
mod blink;
mod rain; mod rain;
mod fade_random; mod rainbow;
mod scanner;
use serde_derive::{Deserialize, Serialize};
use std::fmt;
use std::ops::{AddAssign, Div, Index, IndexMut, SubAssign};
use rand::Rng;
use rand::rngs::ThreadRng;
use crate::patterns::blink::Blink; use crate::patterns::blink::Blink;
use crate::patterns::color_wipe::ColorWipe; use crate::patterns::color_wipe::ColorWipe;
use crate::patterns::fade::Fade; use crate::patterns::fade::Fade;
use crate::patterns::fade_random::FadeRandom; use crate::patterns::fade_random::FadeRandom;
use crate::patterns::fade_unstable::FadeUnstable;
use crate::patterns::fill_random::FillRandom; use crate::patterns::fill_random::FillRandom;
use crate::patterns::fill_unstable::FillUnstable; use crate::patterns::fill_unstable::FillUnstable;
use crate::patterns::rain::Rain; use crate::patterns::rain::Rain;
use crate::patterns::rainbow::Rainbow; use crate::patterns::rainbow::Rainbow;
use crate::patterns::scanner::Scanner; use crate::patterns::scanner::Scanner;
use rand::rngs::ThreadRng;
use rand::Rng;
use serde_derive::{Deserialize, Serialize};
use std::fmt;
use std::ops::{AddAssign, Div, Index, IndexMut, SubAssign};
#[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Copy, Clone)] #[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Copy, Clone)]
#[serde(tag = "type")] #[serde(tag = "type")]
@ -34,10 +36,11 @@ pub(crate) enum Patterns<const N: usize> {
FillUnstable(FillUnstable<N>), FillUnstable(FillUnstable<N>),
Blink(Blink<N>), Blink(Blink<N>),
Rain(Rain<N>), Rain(Rain<N>),
FadeRandom(FadeRandom<N>) FadeRandom(FadeRandom<N>),
FadeUnstable(FadeUnstable<N>),
} }
pub trait Pattern : Iterator { pub trait Pattern: Iterator {
type Strip; type Strip;
fn init(&mut self) -> Option<Self::Strip>; fn init(&mut self) -> Option<Self::Strip>;
@ -58,6 +61,7 @@ impl<const N: usize> Iterator for Patterns<N> {
Patterns::Blink(p) => p.next(), Patterns::Blink(p) => p.next(),
Patterns::Rain(p) => p.next(), Patterns::Rain(p) => p.next(),
Patterns::FadeRandom(p) => p.next(), Patterns::FadeRandom(p) => p.next(),
Patterns::FadeUnstable(p) => p.next(),
} }
} }
} }
@ -76,6 +80,7 @@ impl<const N: usize> Pattern for Patterns<N> {
Patterns::Blink(p) => p.init(), Patterns::Blink(p) => p.init(),
Patterns::Rain(p) => p.init(), Patterns::Rain(p) => p.init(),
Patterns::FadeRandom(p) => p.init(), Patterns::FadeRandom(p) => p.init(),
Patterns::FadeUnstable(p) => p.init(),
} }
} }
@ -90,6 +95,7 @@ impl<const N: usize> Pattern for Patterns<N> {
Patterns::Blink(p) => p.is_last_iteration(), Patterns::Blink(p) => p.is_last_iteration(),
Patterns::Rain(p) => p.is_last_iteration(), Patterns::Rain(p) => p.is_last_iteration(),
Patterns::FadeRandom(p) => p.is_last_iteration(), Patterns::FadeRandom(p) => p.is_last_iteration(),
Patterns::FadeUnstable(p) => p.is_last_iteration(),
} }
} }
} }
@ -164,11 +170,7 @@ impl PixelColor {
green = self.green.saturating_sub(green_delta); green = self.green.saturating_sub(green_delta);
blue = self.blue.saturating_sub(blue_delta); blue = self.blue.saturating_sub(blue_delta);
} }
PixelColor { PixelColor { red, green, blue }
red,
green,
blue
}
} }
} }
@ -210,10 +212,12 @@ impl<const N: usize> Strip<N> {
} }
pub fn new(color: PixelColor) -> Strip<N> { pub fn new(color: PixelColor) -> Strip<N> {
Strip { 0: [Some(color); N] } Strip {
0: [Some(color); N],
}
} }
pub fn fill(&mut self, color: PixelColor) { pub fn fill(&mut self, color: PixelColor) {
self.0.fill(Some(color)); self.0.fill(Some(color));
} }
} }

View File

@ -1,7 +1,7 @@
use crate::patterns::fade::Fade; use crate::patterns::fade::Fade;
use crate::Strip;
use serde::{Serialize, Deserialize};
use crate::patterns::Pattern; use crate::patterns::Pattern;
use crate::Strip;
use serde::{Deserialize, Serialize};
/// # Blink /// # Blink
/// ///
@ -23,7 +23,7 @@ impl<const N: usize> Pattern for Blink<N> {
fn is_last_iteration(&self) -> bool { fn is_last_iteration(&self) -> bool {
match self.max_iteration { match self.max_iteration {
None => { false } None => false,
Some(max_iter) => { Some(max_iter) => {
if self.current_iteration >= max_iter { if self.current_iteration >= max_iter {
true true
@ -43,7 +43,7 @@ impl<const N: usize> Iterator for Blink<N> {
match value { match value {
None => { None => {
if self.is_last_iteration() { if self.is_last_iteration() {
return None; return None;
} }
self.current_iteration += 1; self.current_iteration += 1;
self.fade.current_iteration = 0; self.fade.current_iteration = 0;
@ -53,4 +53,4 @@ impl<const N: usize> Iterator for Blink<N> {
Some(value) => Some(value), Some(value) => Some(value),
} }
} }
} }

View File

@ -1,6 +1,6 @@
use crate::patterns::{Pattern, PixelColor}; use crate::patterns::{Pattern, PixelColor};
use crate::Strip; use crate::Strip;
use serde::{Serialize, Deserialize}; use serde::{Deserialize, Serialize};
/// # Colorwipe pattern /// # Colorwipe pattern
/// every pattern implement the iterator trait /// every pattern implement the iterator trait
@ -33,7 +33,7 @@ impl<const N: usize> Pattern for ColorWipe<N> {
fn is_last_iteration(&self) -> bool { fn is_last_iteration(&self) -> bool {
match self.max_iteration { match self.max_iteration {
None => { false } None => false,
Some(max_iter) => { Some(max_iter) => {
if self.current_iteration >= max_iter { if self.current_iteration >= max_iter {
true true
@ -59,12 +59,10 @@ impl<const N: usize> Iterator for ColorWipe<N> {
} }
let iteration = self.current_iteration % N; let iteration = self.current_iteration % N;
for i in 0..iteration { for i in 0..iteration {
strip[i] = Some(self.color); strip[i] = Some(self.color);
} }
self.current_iteration += 1; self.current_iteration += 1;
Some(strip) Some(strip)
} }
} }

View File

@ -1,6 +1,6 @@
use crate::patterns::{Pattern, PixelColor}; use crate::patterns::{Pattern, PixelColor};
use crate::Strip; use crate::Strip;
use serde::{Serialize, Deserialize}; use serde::{Deserialize, Serialize};
/// # fade pattern /// # fade pattern
/// fade from one color to an other /// fade from one color to an other

View File

@ -1,7 +1,7 @@
use crate::patterns::fade::Fade; use crate::patterns::fade::Fade;
use crate::Strip;
use serde::{Serialize, Deserialize};
use crate::patterns::Pattern; use crate::patterns::Pattern;
use crate::Strip;
use serde::{Deserialize, Serialize};
/// # Blink /// # Blink
/// ///
@ -24,7 +24,7 @@ impl<const N: usize> Pattern for FadeRandom<N> {
fn is_last_iteration(&self) -> bool { fn is_last_iteration(&self) -> bool {
match self.max_iteration { match self.max_iteration {
None => { false } None => false,
Some(max_iter) => { Some(max_iter) => {
if self.current_iteration >= max_iter { if self.current_iteration >= max_iter {
true true
@ -42,20 +42,19 @@ impl<const N: usize> Iterator for FadeRandom<N> {
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
let strip = self.fade.next(); let strip = self.fade.next();
match strip { match strip {
None => { None } None => None,
Some(mut fade) => { Some(mut fade) => {
let rng = rand::thread_rng(); let rng = rand::thread_rng();
for i in 0..N { for i in 0..N {
match fade[i] { match fade[i] {
None => { } None => {}
Some(pixel) => { Some(pixel) => {
fade[i] = Some(pixel.random_delta(self.stability, &mut rng.clone())) fade[i] = Some(pixel.random_delta(self.stability, &mut rng.clone()))
} }
} }
} }
Some(fade) Some(fade)
} }
} }
} }
} }

View File

@ -0,0 +1,54 @@
use crate::patterns::fade::Fade;
use crate::patterns::Pattern;
use crate::Strip;
use serde::{Deserialize, Serialize};
/// # Blink
///
/// fade from one color to an other then go back several times
#[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Copy, Clone)]
pub struct FadeUnstable<const N: usize> {
#[serde(default)]
pub(crate) current_iteration: usize,
pub(crate) max_iteration: Option<usize>,
pub(crate) stability: usize,
fade: Fade<N>,
}
impl<const N: usize> Pattern for FadeUnstable<N> {
type Strip = Strip<N>;
fn init(&mut self) -> Option<Self::Strip> {
None
}
fn is_last_iteration(&self) -> bool {
match self.max_iteration {
None => false,
Some(max_iter) => {
if self.current_iteration >= max_iter {
true
} else {
false
}
}
}
}
}
impl<const N: usize> Iterator for FadeUnstable<N> {
type Item = Strip<N>;
fn next(&mut self) -> Option<Self::Item> {
let strip = self.fade.next();
match strip {
None => None,
Some(fade) => {
let mut rng = rand::thread_rng();
let pixel = fade[0].unwrap().random_delta(self.stability, &mut rng);
Some(Strip::new(pixel))
}
}
}
}

View File

@ -1,6 +1,6 @@
use crate::patterns::{Pattern, PixelColor}; use crate::patterns::{Pattern, PixelColor};
use crate::Strip; use crate::Strip;
use serde::{Serialize, Deserialize}; use serde::{Deserialize, Serialize};
/// # FillRandom /// # FillRandom
/// ///
@ -23,7 +23,7 @@ impl<const N: usize> Pattern for FillRandom<N> {
fn is_last_iteration(&self) -> bool { fn is_last_iteration(&self) -> bool {
match self.max_iteration { match self.max_iteration {
None => { false } None => false,
Some(max_iter) => { Some(max_iter) => {
if self.current_iteration >= max_iter { if self.current_iteration >= max_iter {
true true
@ -52,4 +52,4 @@ impl<const N: usize> Iterator for FillRandom<N> {
self.current_iteration += 1; self.current_iteration += 1;
Some(strip) Some(strip)
} }
} }

View File

@ -1,6 +1,6 @@
use crate::patterns::{Pattern, PixelColor}; use crate::patterns::{Pattern, PixelColor};
use crate::Strip; use crate::Strip;
use serde::{Serialize, Deserialize}; use serde::{Deserialize, Serialize};
/// # FillUnstable /// # FillUnstable
/// ///
@ -23,7 +23,7 @@ impl<const N: usize> Pattern for FillUnstable<N> {
fn is_last_iteration(&self) -> bool { fn is_last_iteration(&self) -> bool {
match self.max_iteration { match self.max_iteration {
None => { false } None => false,
Some(max_iter) => { Some(max_iter) => {
if self.current_iteration >= max_iter { if self.current_iteration >= max_iter {
true true
@ -48,4 +48,4 @@ impl<const N: usize> Iterator for FillUnstable<N> {
self.current_iteration += 1; self.current_iteration += 1;
Some(Strip::<N>::new(unstable_color)) Some(Strip::<N>::new(unstable_color))
} }
} }

View File

@ -1,7 +1,7 @@
use rand::Rng;
use crate::patterns::{Pattern, PixelColor}; use crate::patterns::{Pattern, PixelColor};
use crate::Strip; use crate::Strip;
use serde::{Serialize, Deserialize}; use rand::Rng;
use serde::{Deserialize, Serialize};
/// # rain pattern /// # rain pattern
/// randomly fall colors from top or bottom. /// randomly fall colors from top or bottom.
@ -23,7 +23,7 @@ pub struct Rain<const N: usize> {
pub(crate) stability: usize, pub(crate) stability: usize,
pub(crate) lines: usize, pub(crate) lines: usize,
#[serde(skip)] #[serde(skip)]
drops : Strip<N>, drops: Strip<N>,
} }
impl<const N: usize> Pattern for Rain<N> { impl<const N: usize> Pattern for Rain<N> {
@ -40,7 +40,7 @@ impl<const N: usize> Pattern for Rain<N> {
fn is_last_iteration(&self) -> bool { fn is_last_iteration(&self) -> bool {
match self.max_iteration { match self.max_iteration {
None => { false } None => false,
Some(max_iter) => { Some(max_iter) => {
if self.current_iteration >= max_iter { if self.current_iteration >= max_iter {
true true
@ -58,17 +58,17 @@ impl<const N: usize> Iterator for Rain<N> {
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
let mut strip = Strip::<N>::default(); let mut strip = Strip::<N>::default();
for i in 0..(N-self.lines) { for i in 0..(N - self.lines) {
strip[i+self.lines] = self.drops[i]; strip[i + self.lines] = self.drops[i];
} }
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
for i in 0..self.lines { for i in 0..self.lines {
if rng.gen_bool(self.stability as f64 / 100 as f64) { if rng.gen_bool(self.stability as f64 / 100 as f64) {
strip[i] = Some(self.color); strip[i] = Some(self.color);
} else { } else {
let c = strip[i+self.lines]; let c = strip[i + self.lines];
if self.background_color != c && c != Some(PixelColor::default()) { if self.background_color != c && c != Some(PixelColor::default()) {
strip[i] = Some(strip[i+self.lines].unwrap()/ 2); strip[i] = Some(strip[i + self.lines].unwrap() / 2);
} else { } else {
strip[i] = self.background_color; strip[i] = self.background_color;
} }
@ -79,4 +79,4 @@ impl<const N: usize> Iterator for Rain<N> {
self.current_iteration += 1; self.current_iteration += 1;
Some(strip) Some(strip)
} }
} }

View File

@ -1,6 +1,6 @@
use crate::patterns::{Pattern, PixelColor}; use crate::patterns::{Pattern, PixelColor};
use crate::Strip; use crate::Strip;
use serde::{Serialize, Deserialize}; use serde::{Deserialize, Serialize};
/// # Rainbow pattern /// # Rainbow pattern
/// ///
@ -29,7 +29,7 @@ impl<const N: usize> Pattern for Rainbow<N> {
fn is_last_iteration(&self) -> bool { fn is_last_iteration(&self) -> bool {
match self.max_iteration { match self.max_iteration {
None => { false } None => false,
Some(max_iter) => { Some(max_iter) => {
if self.current_iteration >= max_iter { if self.current_iteration >= max_iter {
true true
@ -92,4 +92,4 @@ fn wheel(index: u8) -> PixelColor {
} }
} }
} }
} }

View File

@ -1,6 +1,6 @@
use crate::patterns::{Pattern, PixelColor}; use crate::patterns::{Pattern, PixelColor};
use crate::Strip; use crate::Strip;
use serde::{Serialize, Deserialize}; use serde::{Deserialize, Serialize};
/// # scanner pattern /// # scanner pattern
/// color one pixel with a color and leave a train of this color fading to black /// color one pixel with a color and leave a train of this color fading to black
@ -18,7 +18,7 @@ pub struct Scanner<const N: usize> {
pub(crate) max_iteration: Option<usize>, pub(crate) max_iteration: Option<usize>,
} }
impl<const N:usize> Pattern for Scanner<N> { impl<const N: usize> Pattern for Scanner<N> {
type Strip = Strip<N>; type Strip = Strip<N>;
fn init(&mut self) -> Option<Self::Strip> { fn init(&mut self) -> Option<Self::Strip> {
@ -31,7 +31,7 @@ impl<const N:usize> Pattern for Scanner<N> {
fn is_last_iteration(&self) -> bool { fn is_last_iteration(&self) -> bool {
match self.max_iteration { match self.max_iteration {
None => { false } None => false,
Some(max_iter) => { Some(max_iter) => {
if self.current_iteration >= max_iter { if self.current_iteration >= max_iter {
true true
@ -51,7 +51,7 @@ impl<const N: usize> Iterator for Scanner<N> {
return None; return None;
} }
let mut strip : Strip<N>; let mut strip: Strip<N>;
if let Some(color) = self.background_color { if let Some(color) = self.background_color {
strip = Strip::new(color); strip = Strip::new(color);
@ -74,4 +74,4 @@ impl<const N: usize> Iterator for Scanner<N> {
self.current_iteration += 1; self.current_iteration += 1;
Some(strip) Some(strip)
} }
} }

View File

@ -1,5 +1,5 @@
use crate::config::Config; use crate::config::Config;
use crate::patterns::{Patterns, PixelColor, Pattern}; use crate::patterns::{Pattern, Patterns, PixelColor};
use crate::Strip; use crate::Strip;
use bluer::Address; use bluer::Address;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -10,9 +10,8 @@ use std::time::Duration;
use tokio::sync::watch::{Receiver, Sender}; use tokio::sync::watch::{Receiver, Sender};
pub(crate) mod period { pub(crate) mod period {
use std::time::Duration;
use serde::{de::Error as _, Deserialize, Deserializer}; use serde::{de::Error as _, Deserialize, Deserializer};
use std::time::Duration;
/// Custom deserializer for period from millisecond value /// Custom deserializer for period from millisecond value
/// ///
@ -23,11 +22,12 @@ pub(crate) mod period {
/// returns: Result<Duration, <D as Deserializer>::Error> /// returns: Result<Duration, <D as Deserializer>::Error>
/// ///
pub fn deserialize<'de, D>(deserializer: D) -> Result<Duration, D::Error> pub fn deserialize<'de, D>(deserializer: D) -> Result<Duration, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
String::deserialize(deserializer)? String::deserialize(deserializer)?
.parse::<u64>().and_then(|d| Ok(Duration::from_millis(d))) .parse::<u64>()
.and_then(|d| Ok(Duration::from_millis(d)))
.map_err(|e| D::Error::custom(format!("{}", e))) .map_err(|e| D::Error::custom(format!("{}", e)))
} }
} }
@ -35,14 +35,12 @@ pub(crate) mod period {
#[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Copy, Clone)] #[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Copy, Clone)]
pub struct Context<const N: usize> { pub struct Context<const N: usize> {
pub(crate) pattern: Patterns<N>, pub(crate) pattern: Patterns<N>,
#[serde(deserialize_with = "period::deserialize")] #[serde(deserialize_with = "period::deserialize")]
pub period: Duration, pub period: Duration,
} }
pub(crate) type DeviceSequence<const N: usize> = Vec<Context<N>>; pub(crate) type DeviceSequence<const N: usize> = Vec<Context<N>>;
pub async fn runner_loop<const N: usize>(runner: DeviceSequence<N>, tx: Sender<Strip<N>>) { pub async fn runner_loop<const N: usize>(runner: DeviceSequence<N>, tx: Sender<Strip<N>>) {
let mut background = Strip::<N>::default(); let mut background = Strip::<N>::default();
for mut context in runner { for mut context in runner {
@ -151,7 +149,6 @@ impl<const N: usize> Spectacle<N> {
} }
joinhandles joinhandles
} }
} }
impl<const N: usize> From<Config<N>> for Spectacle<N> { impl<const N: usize> From<Config<N>> for Spectacle<N> {
@ -178,7 +175,6 @@ impl<const N: usize> From<Config<N>> for Spectacle<N> {
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@ -188,24 +184,24 @@ mod tests {
let pixel_entry = PixelColor { let pixel_entry = PixelColor {
red: 10, red: 10,
green: 10, green: 10,
blue: 10 blue: 10,
}; };
let pixel_mask = PixelColor { let pixel_mask = PixelColor {
red: 20, red: 20,
green: 20, green: 20,
blue: 20 blue: 20,
}; };
let mut entry = Strip::<5>::new(pixel_entry) ; let mut entry = Strip::<5>::new(pixel_entry);
entry[0] = None; entry[0] = None;
entry[1] = None; entry[1] = None;
let mut mask = Strip::<5>::new(pixel_mask) ; let mut mask = Strip::<5>::new(pixel_mask);
mask[0] = None; mask[0] = None;
let mut expected = entry.clone(); let mut expected = entry.clone();
expected[1] = Some(pixel_mask); expected[1] = Some(pixel_mask);
assert_eq!(expected, super::apply_mask(mask, entry)); assert_eq!(expected, super::apply_mask(mask, entry));
} }
} }