use crate::types::ChordLabel;
pub struct ProgressionAnalyzer;
impl ProgressionAnalyzer {
#[must_use]
pub fn new() -> Self {
Self
}
#[must_use]
pub fn analyze(&self, chords: &[ChordLabel]) -> Vec<String> {
let mut progressions = Vec::new();
for window in chords.windows(4) {
let pattern = self.classify_progression(window);
if !pattern.is_empty() {
progressions.push(pattern);
}
}
progressions
}
fn classify_progression(&self, chords: &[ChordLabel]) -> String {
let labels: Vec<&str> = chords.iter().map(|c| c.label.as_str()).collect();
if self.is_twelve_bar_blues(&labels) {
"12-bar blues".to_string()
} else if self.is_ii_v_i(&labels) {
"II-V-I".to_string()
} else if self.is_i_iv_v(&labels) {
"I-IV-V".to_string()
} else {
labels.join(" - ")
}
}
fn is_twelve_bar_blues(&self, _chords: &[&str]) -> bool {
false
}
fn is_ii_v_i(&self, chords: &[&str]) -> bool {
chords.len() >= 3 && {
chords.len() == 3
}
}
fn is_i_iv_v(&self, chords: &[&str]) -> bool {
chords.len() >= 3 && {
chords.len() == 3
}
}
}
impl Default for ProgressionAnalyzer {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_progression_analyzer_creation() {
let _analyzer = ProgressionAnalyzer::new();
}
}