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
use std::collections::HashMap;

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();
    if replacements.contains_key(&base) {
        base = replacements.get(&base).unwrap().to_string()
    }
    return if note.chars().last().unwrap().to_lowercase().to_string() == "m" {
        base.pop();
        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") }
    };

}

#[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");
}