1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
use std::collections::HashMap;
use wasm_bindgen::prelude::*;
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug)]
pub struct Triad {
    pub notes: [String; 3],
    pub kind: String,
}

pub fn get_triad(mut note: String) -> Triad {
    let tones = [
        "c", "cis", "d", "dis", "e", "f", "fis", "g", "gis", "a", "ais", "h",
    ];
    let mut replacements = HashMap::new();
    replacements.insert("des".to_string(), "cis".to_string());
    replacements.insert("es".to_string(), "dis".to_string());
    replacements.insert("ges".to_string(), "fis".to_string());
    replacements.insert("as".to_string(), "gis".to_string());
    replacements.insert("b".to_string(), "ais".to_string());

    note = note.to_lowercase();

    let mut base = note.to_string().to_lowercase();
    // let mut temp = base.clone();
    let is_major: bool;
    if base.chars().last().unwrap().to_lowercase().to_string() == "m" {
        base.pop();
        is_major = false
    } else {
        is_major = true
    }
    if replacements.contains_key(&base) {
        base = replacements.get(&base).unwrap().to_string();
    }

    return if !is_major {
        let original_index = tones.iter().position(|&r| r == base).unwrap();
        let mut note1 = note.to_string().to_lowercase();
        note1.pop().unwrap().to_string();
        let note2 = String::from(tones[(original_index + 3) % tones.len()]);
        let note3 = String::from(tones[(original_index + 3 + 4) % tones.len()]);
        Triad { notes: [note1, note2, note3], kind: String::from("minor") }
    } else {
        let original_index = tones.iter().position(|&r| r == base).unwrap();
        let note1 = note.to_string().to_lowercase();
        let note2 = String::from(tones[(original_index + 4) % tones.len()]);
        let note3 = String::from(tones[(original_index + 4 + 3) % tones.len()]);
        Triad { notes: [note1, note2, note3], kind: String::from("major") }
    };
}

#[wasm_bindgen]
pub fn get_triad_json(note: String) -> String {
    return String::from(serde_json::to_string(&get_triad(note)).unwrap());
}

#[test]
fn test_c_major() {
    let triad = get_triad(String::from("c"));
    assert_eq!(triad.kind, "major");
    assert_eq!(triad.notes[0], "c");
    assert_eq!(triad.notes[1], "e");
    assert_eq!(triad.notes[2], "g");
}

#[test]
fn test_g_major() {
    let triad = get_triad(String::from("g"));
    assert_eq!(triad.kind, "major");
    assert_eq!(triad.notes[0], "g");
    assert_eq!(triad.notes[1], "h");
    assert_eq!(triad.notes[2], "d");
}

#[test]
fn test_g_major_capital() {
    let triad = get_triad(String::from("G"));
    assert_eq!(triad.kind, "major");
    assert_eq!(triad.notes[0], "g");
    assert_eq!(triad.notes[1], "h");
    assert_eq!(triad.notes[2], "d");
}

#[test]
fn test_h_minor() {
    let triad = get_triad(String::from("gm"));
    assert_eq!(triad.kind, "minor");
    assert_eq!(triad.notes[0], "g");
    assert_eq!(triad.notes[1], "ais");
    assert_eq!(triad.notes[2], "d");
}

#[test]
fn test_e_minor() {
    let triad = get_triad(String::from("em"));
    assert_eq!(triad.kind, "minor");
    assert_eq!(triad.notes[0], "e");
    assert_eq!(triad.notes[1], "g");
    assert_eq!(triad.notes[2], "h");
}

#[test]
fn test_e_minor_capital() {
    let triad = get_triad(String::from("EM"));
    assert_eq!(triad.kind, "minor");
    assert_eq!(triad.notes[0], "e");
    assert_eq!(triad.notes[1], "g");
    assert_eq!(triad.notes[2], "h");
}