hapsi 0.0.3

A music theory package
Documentation
use crate::prelude::*;

#[derive(Debug)]
pub struct Diatonic {
    key: Tone,
    quality: Quality,
    distances: [usize; 7],
}

impl Diatonic {
    pub fn major(key: &Tone) -> Diatonic {
        Self {
            key: *key,
            quality: Quality::Major,
            distances: [0, 2, 4, 5, 7, 9, 11],
        }
    }

    pub fn minor(key: &Tone) -> Diatonic {
        Self {
            key: *key,
            quality: Quality::Minor,
            distances: [0, 2, 3, 5, 7, 8, 10],
        }
    }

    pub fn quality(&self) -> Quality {
        self.quality
    }
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Quality {
    Major,
    Minor,
}

impl Scale for Diatonic {
    fn convert(&self, number: impl Number) -> usize {
        let i: usize = self.key.into();
        i + self.distances.get(number.value()).unwrap().clone()
    }

    fn len(&self) -> usize {
        7
    }
}

#[cfg(test)]
mod tests {
    use crate::prelude::*;

    #[test]
    fn major() {
        let scale = super::Diatonic::major(&Tone::new(C, Natural));
        let scaled = Scaled::new(scale, Twelve);
        let keyboard = Keyboard::new(scaled);
        let mut tones = keyboard.class_iter();
        assert_eq!(tones.next(), Some(&Tone::new(C, Natural)));
        assert_eq!(tones.next(), Some(&Tone::new(D, Natural)));
        assert_eq!(tones.next(), Some(&Tone::new(E, Natural)));
        assert_eq!(tones.next(), Some(&Tone::new(F, Natural)));
        assert_eq!(tones.next(), Some(&Tone::new(G, Natural)));
        assert_eq!(tones.next(), Some(&Tone::new(A, Natural)));
        assert_eq!(tones.next(), Some(&Tone::new(B, Natural)));
        assert_eq!(tones.next(), None);
    }

    #[test]
    fn minor() {
        let scale = super::Diatonic::minor(&Tone::new(A, Natural));
        let scaled = Scaled::new(scale, Twelve);
        let keyboard = Keyboard::new(scaled);
        let mut tones = keyboard.class_iter();
        assert_eq!(tones.next(), Some(&Tone::new(A, Natural)));
        assert_eq!(tones.next(), Some(&Tone::new(B, Natural)));
        assert_eq!(tones.next(), Some(&Tone::new(C, Natural)));
        assert_eq!(tones.next(), Some(&Tone::new(D, Natural)));
        assert_eq!(tones.next(), Some(&Tone::new(E, Natural)));
        assert_eq!(tones.next(), Some(&Tone::new(F, Natural)));
        assert_eq!(tones.next(), Some(&Tone::new(G, Natural)));
        assert_eq!(tones.next(), None);
    }
}