use std::collections::HashMap;
use std::time::Duration;
use super::color::Color;
use super::tempo_aware::{TempoAwareFrequency, TempoAwareSpeed};
#[derive(Debug, Clone)]
pub enum EffectType {
Static {
parameters: HashMap<String, f64>,
duration: Duration,
},
ColorCycle {
colors: Vec<Color>,
speed: TempoAwareSpeed, direction: CycleDirection,
transition: CycleTransition, duration: Duration,
},
Strobe {
frequency: TempoAwareFrequency, duration: Duration,
},
Dimmer {
start_level: f64,
end_level: f64,
duration: Duration,
curve: DimmerCurve,
},
Chase {
pattern: ChasePattern,
speed: TempoAwareSpeed, direction: ChaseDirection,
transition: CycleTransition, duration: Duration,
},
Rainbow {
speed: TempoAwareSpeed, saturation: f64,
brightness: f64,
duration: Duration,
},
Pulse {
base_level: f64,
pulse_amplitude: f64,
frequency: TempoAwareFrequency, duration: Duration,
},
}
impl EffectType {
pub fn duration(&self) -> Duration {
match self {
EffectType::Static { duration, .. }
| EffectType::Strobe { duration, .. }
| EffectType::Pulse { duration, .. }
| EffectType::Dimmer { duration, .. }
| EffectType::ColorCycle { duration, .. }
| EffectType::Chase { duration, .. }
| EffectType::Rainbow { duration, .. } => *duration,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum CycleDirection {
Forward,
Backward,
PingPong,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum CycleTransition {
Snap,
Fade,
}
#[derive(Debug, Clone, PartialEq)]
pub enum ChasePattern {
Linear,
Snake,
Random,
}
#[derive(Debug, Clone, Copy)]
pub enum ChaseDirection {
LeftToRight,
RightToLeft,
TopToBottom,
BottomToTop,
Clockwise,
CounterClockwise,
}
#[derive(Debug, Clone)]
pub enum DimmerCurve {
Linear,
Exponential,
Logarithmic,
Sine,
Cosine,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum EffectLayer {
Background = 0, Midground = 1, Foreground = 2, }
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum BlendMode {
Replace,
Multiply,
Add,
Overlay,
Screen,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn effect_type_static_duration() {
let effect = EffectType::Static {
parameters: HashMap::new(),
duration: Duration::from_secs(5),
};
assert_eq!(effect.duration(), Duration::from_secs(5));
}
#[test]
fn effect_type_strobe_duration() {
let effect = EffectType::Strobe {
frequency: TempoAwareFrequency::Fixed(10.0),
duration: Duration::from_millis(500),
};
assert_eq!(effect.duration(), Duration::from_millis(500));
}
#[test]
fn effect_type_pulse_duration() {
let effect = EffectType::Pulse {
base_level: 0.0,
pulse_amplitude: 1.0,
frequency: TempoAwareFrequency::Fixed(2.0),
duration: Duration::from_secs(3),
};
assert_eq!(effect.duration(), Duration::from_secs(3));
}
#[test]
fn effect_type_dimmer_duration() {
let effect = EffectType::Dimmer {
start_level: 0.0,
end_level: 1.0,
duration: Duration::from_secs(2),
curve: DimmerCurve::Linear,
};
assert_eq!(effect.duration(), Duration::from_secs(2));
}
#[test]
fn effect_type_color_cycle_duration() {
let effect = EffectType::ColorCycle {
colors: vec![Color::new(255, 0, 0), Color::new(0, 0, 255)],
speed: TempoAwareSpeed::Fixed(1.0),
direction: CycleDirection::Forward,
transition: CycleTransition::Fade,
duration: Duration::from_secs(10),
};
assert_eq!(effect.duration(), Duration::from_secs(10));
}
#[test]
fn effect_type_chase_duration() {
let effect = EffectType::Chase {
pattern: ChasePattern::Linear,
speed: TempoAwareSpeed::Fixed(1.0),
direction: ChaseDirection::LeftToRight,
transition: CycleTransition::Snap,
duration: Duration::from_secs(5),
};
assert_eq!(effect.duration(), Duration::from_secs(5));
}
#[test]
fn effect_type_rainbow_duration() {
let effect = EffectType::Rainbow {
speed: TempoAwareSpeed::Fixed(0.5),
saturation: 1.0,
brightness: 1.0,
duration: Duration::from_secs(8),
};
assert_eq!(effect.duration(), Duration::from_secs(8));
}
#[test]
fn effect_layer_ordering() {
assert!(EffectLayer::Background < EffectLayer::Midground);
assert!(EffectLayer::Midground < EffectLayer::Foreground);
}
#[test]
fn cycle_direction_equality() {
assert_eq!(CycleDirection::Forward, CycleDirection::Forward);
assert_ne!(CycleDirection::Forward, CycleDirection::Backward);
assert_ne!(CycleDirection::Backward, CycleDirection::PingPong);
}
#[test]
fn cycle_transition_equality() {
assert_eq!(CycleTransition::Snap, CycleTransition::Snap);
assert_ne!(CycleTransition::Snap, CycleTransition::Fade);
}
#[test]
fn blend_mode_equality() {
assert_eq!(BlendMode::Replace, BlendMode::Replace);
assert_ne!(BlendMode::Replace, BlendMode::Multiply);
assert_ne!(BlendMode::Add, BlendMode::Screen);
}
}