use rand::Rng; const VOWELS: usize = 5; const CONSONANTS: usize = 11; const OBS: &str = ""; type KanaCharacters<'a> = [[&'a str; VOWELS]; CONSONANTS]; #[derive(Clone)] pub enum Kanas { Romaji, Hiragana, Katakana, } impl std::fmt::Display for Kanas { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, "{}", match self { Kanas::Romaji => "Romaji", Kanas::Hiragana => "Hiragana", Kanas::Katakana => "Katakana", } ) } } pub struct Hieroglyph { syllable: String, row: usize, column: usize, } impl Hieroglyph { pub fn get_kana(&self) -> Kanas { for row in ROMAJI { if row.contains(&(self.syllable).as_str()) { return Kanas::Romaji; } } for row in HIRAGANA { if row.contains(&(self.syllable).as_str()) { return Kanas::Hiragana; } } for row in KATAKANA { if row.contains(&(self.syllable).as_str()) { return Kanas::Katakana; } } Kanas::Romaji // /shrug } } impl std::fmt::Display for Hieroglyph { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.syllable) } } impl std::fmt::Debug for Hieroglyph { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, "Hieroglyph: {} => ({}, {})", self.syllable, self.row, self.column ) } } const ROMAJI: KanaCharacters = [ ["a", "i", "u", "e", "o"], ["ka", "ki", "ku", "ke", "ko"], ["sa", "si", "su", "se", "so"], ["ta", "ti", "tu", "te", "to"], ["na", "ni", "nu", "ne", "no"], ["ha", "hi", "hu", "he", "ho"], ["ma", "mi", "mu", "me", "mo"], ["ya", OBS, "yu", OBS, "yo"], ["ra", "ri", "ru", "re", "ro"], ["wa", OBS, OBS, OBS, "wo"], ["n", OBS, OBS, OBS, OBS], ]; const HIRAGANA: KanaCharacters = [ ["あ", "い", "う", "え", "お"], ["か", "き", "く", "け", "こ"], ["さ", "し", "す", "せ", "そ"], ["た", "ち", "つ", "て", "と"], ["な", "に", "ぬ", "ね", "の"], ["は", "ひ", "ふ", "へ", "ほ"], ["ま", "み", "む", "め", "も"], ["や", OBS, "ゆ", OBS, "よ"], ["ら", "り", "る", "れ", "ろ"], ["わ", OBS, OBS, OBS, "を"], ["ん", OBS, OBS, OBS, OBS], ]; const KATAKANA: KanaCharacters = [ ["ア", "イ", "ウ", "エ", "オ"], ["カ", "キ", "ク", "ケ", "コ"], ["サ", "シ", "ス", "セ", "ソ"], ["タ", "チ", "ツ", "テ", "ト"], ["ナ", "ニ", "ヌ", "ネ", "ノ"], ["ハ", "ヒ", "フ", "ヘ", "ホ"], ["マ", "ミ", "ム", "メ", "モ"], ["ヤ", OBS, "ユ", OBS, "ヨ"], ["ラ", "リ", "ル", "レ", "ロ"], ["ワ", OBS, OBS, OBS, "ヲ"], ["ン", OBS, OBS, OBS, OBS], ]; fn get_characters_for_kana(k: &Kanas) -> KanaCharacters { match k { Kanas::Hiragana => HIRAGANA, Kanas::Katakana => KATAKANA, Kanas::Romaji => ROMAJI, } } pub fn get_kana_pair_for_hieroglyph(k: &Kanas, h: &Hieroglyph) -> Hieroglyph { Hieroglyph { syllable: get_characters_for_kana(&k)[h.row][h.column].to_string(), row: h.row, column: h.column, } } pub fn generate_random_hieroglyph(k: Kanas) -> Hieroglyph { let row: usize = rand::thread_rng().gen_range(0..CONSONANTS); let column: usize = rand::thread_rng().gen_range(0..VOWELS); let syllable: String = get_characters_for_kana(&k)[row][column].to_string(); if syllable == OBS { return generate_random_hieroglyph(k); } Hieroglyph { syllable, row, column, } } pub fn random_kana(hiragana: bool, katakana: bool) -> Hieroglyph { if hiragana && katakana { generate_random_hieroglyph(if rand::thread_rng().gen_bool(0.5) { Kanas::Katakana } else { Kanas::Hiragana }) } else { generate_random_hieroglyph(if hiragana { Kanas::Hiragana } else { Kanas::Katakana }) } } pub fn ask(ktr: bool, rtk: bool, hiragana: bool, katakana: bool) -> Hieroglyph { if ktr && rtk { return if rand::thread_rng().gen_bool(0.5) { random_kana(hiragana, katakana) } else { generate_random_hieroglyph(Kanas::Romaji) }; } else if ktr { return random_kana(hiragana, katakana); } else { return generate_random_hieroglyph(Kanas::Romaji); } } pub fn generate_question_text(question: &Hieroglyph, exact_kana: &Kanas) -> String { return String::from(match question.get_kana() { Kanas::Romaji => match exact_kana { Kanas::Hiragana => { format!("Name corresponding hiragana for {}", question.to_string()) } Kanas::Katakana => { format!("Name corresponding katakana for {}", question.to_string()) } _ => { panic!("HOW DID YOU GET HERE!?"); } }, Kanas::Hiragana => { format!( "Name corresponding romaji for hiragana {}", question.to_string() ) } Kanas::Katakana => { format!( "Name corresponding romaji for katakana {}", question.to_string() ) } }); }