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 = Arc::new(Mutex::new(spectacle));
let adapter = bluetooth::create_session().await?;
let (tx_scan, rx_scan) = mpsc::channel(3);

View File

@ -1,27 +1,29 @@
mod scanner;
mod fade;
mod blink;
mod color_wipe;
mod rainbow;
mod fade;
mod fade_random;
mod fade_unstable;
mod fill_random;
mod fill_unstable;
mod blink;
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::color_wipe::ColorWipe;
use crate::patterns::fade::Fade;
use crate::patterns::fade_random::FadeRandom;
use crate::patterns::fade_unstable::FadeUnstable;
use crate::patterns::fill_random::FillRandom;
use crate::patterns::fill_unstable::FillUnstable;
use crate::patterns::rain::Rain;
use crate::patterns::rainbow::Rainbow;
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)]
#[serde(tag = "type")]
@ -34,10 +36,11 @@ pub(crate) enum Patterns<const N: usize> {
FillUnstable(FillUnstable<N>),
Blink(Blink<N>),
Rain(Rain<N>),
FadeRandom(FadeRandom<N>)
FadeRandom(FadeRandom<N>),
FadeUnstable(FadeUnstable<N>),
}
pub trait Pattern : Iterator {
pub trait Pattern: Iterator {
type 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::Rain(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::Rain(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::Rain(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);
blue = self.blue.saturating_sub(blue_delta);
}
PixelColor {
red,
green,
blue
}
PixelColor { red, green, blue }
}
}
@ -210,10 +212,12 @@ impl<const N: usize> 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) {
self.0.fill(Some(color));
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
use crate::patterns::{Pattern, PixelColor};
use crate::Strip;
use serde::{Serialize, Deserialize};
use serde::{Deserialize, Serialize};
/// # scanner pattern
/// 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>,
}
impl<const N:usize> Pattern for Scanner<N> {
impl<const N: usize> Pattern for Scanner<N> {
type Strip = Strip<N>;
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 {
match self.max_iteration {
None => { false }
None => false,
Some(max_iter) => {
if self.current_iteration >= max_iter {
true
@ -51,7 +51,7 @@ impl<const N: usize> Iterator for Scanner<N> {
return None;
}
let mut strip : Strip<N>;
let mut strip: Strip<N>;
if let Some(color) = self.background_color {
strip = Strip::new(color);
@ -74,4 +74,4 @@ impl<const N: usize> Iterator for Scanner<N> {
self.current_iteration += 1;
Some(strip)
}
}
}

View File

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