Initial commit.
This commit is contained in:
parent
72769f2e7b
commit
586b1f85f7
|
@ -0,0 +1,26 @@
|
|||
#!/usr/bin/env perl
|
||||
use Module::Build;
|
||||
|
||||
my $home = $ENV{HOME};
|
||||
|
||||
my $build = Module::Build->new(
|
||||
module_name => 'JapaChar',
|
||||
license => 'AGPLv3',
|
||||
dist_author => 'Sergio Iglesias <contact@owlcode.tech>',
|
||||
dist_abstract => 'Learn Japanese Characters.',
|
||||
requires => {
|
||||
'DBI' => 0,
|
||||
'DBD::SQLite' => 0,
|
||||
'Cairo::GObject' => 0,
|
||||
'Glib::IO' => 0,
|
||||
'Glib::Object::Introspection' => 0,
|
||||
'JSON' => 0,
|
||||
'Moo' => 0,
|
||||
'YAML::PP' => 0,
|
||||
'Path::Tiny' => 0,
|
||||
'DBIx::Class' => 0,
|
||||
'Pango' => 0,
|
||||
'Crypt::URandom' => 0,
|
||||
},
|
||||
);
|
||||
$build->create_build_script;
|
|
@ -0,0 +1,997 @@
|
|||
[
|
||||
{
|
||||
"kana": "あ",
|
||||
"roumaji": "a",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "い",
|
||||
"roumaji": "i",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "う",
|
||||
"roumaji": "u",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "え",
|
||||
"roumaji": "e",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "お",
|
||||
"roumaji": "o",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "か",
|
||||
"roumaji": "ka",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "き",
|
||||
"roumaji": "ki",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "く",
|
||||
"roumaji": "ku",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "け",
|
||||
"roumaji": "ke",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "こ",
|
||||
"roumaji": "ko",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "さ",
|
||||
"roumaji": "sa",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "し",
|
||||
"roumaji": "shi",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "す",
|
||||
"roumaji": "su",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "せ",
|
||||
"roumaji": "se",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "そ",
|
||||
"roumaji": "so",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "た",
|
||||
"roumaji": "ta",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ち",
|
||||
"roumaji": "chi",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "つ",
|
||||
"roumaji": "tsu",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "て",
|
||||
"roumaji": "te",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "と",
|
||||
"roumaji": "to",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "な",
|
||||
"roumaji": "na",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "に",
|
||||
"roumaji": "ni",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ぬ",
|
||||
"roumaji": "nu",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ね",
|
||||
"roumaji": "ne",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "の",
|
||||
"roumaji": "no",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "は",
|
||||
"roumaji": "ha",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ひ",
|
||||
"roumaji": "hi",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ふ",
|
||||
"roumaji": "fu",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "へ",
|
||||
"roumaji": "he",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ほ",
|
||||
"roumaji": "ho",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ま",
|
||||
"roumaji": "ma",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "み",
|
||||
"roumaji": "mi",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "む",
|
||||
"roumaji": "mu",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "め",
|
||||
"roumaji": "me",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "も",
|
||||
"roumaji": "mo",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "や",
|
||||
"roumaji": "ya",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ゆ",
|
||||
"roumaji": "yu",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "よ",
|
||||
"roumaji": "yo",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ら",
|
||||
"roumaji": "ra",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "り",
|
||||
"roumaji": "ri",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "る",
|
||||
"roumaji": "ru",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "れ",
|
||||
"roumaji": "re",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ろ",
|
||||
"roumaji": "ro",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "わ",
|
||||
"roumaji": "wa",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "を",
|
||||
"roumaji": "wo",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ん",
|
||||
"roumaji": "n",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "が",
|
||||
"roumaji": "ga",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ぎ",
|
||||
"roumaji": "gi",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ぐ",
|
||||
"roumaji": "gu",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "げ",
|
||||
"roumaji": "ge",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ご",
|
||||
"roumaji": "go",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ざ",
|
||||
"roumaji": "za",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "じ",
|
||||
"roumaji": "ji",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ず",
|
||||
"roumaji": "zu",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ぜ",
|
||||
"roumaji": "ze",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ぞ",
|
||||
"roumaji": "zo",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "だ",
|
||||
"roumaji": "da",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ぢ",
|
||||
"roumaji": "ji",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "づ",
|
||||
"roumaji": "zu",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "で",
|
||||
"roumaji": "de",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ど",
|
||||
"roumaji": "do",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ば",
|
||||
"roumaji": "ba",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "び",
|
||||
"roumaji": "bi",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ぶ",
|
||||
"roumaji": "bu",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "べ",
|
||||
"roumaji": "be",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ぼ",
|
||||
"roumaji": "bo",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ぱ",
|
||||
"roumaji": "pa",
|
||||
"type": "handakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ぴ",
|
||||
"roumaji": "pi",
|
||||
"type": "handakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ぷ",
|
||||
"roumaji": "pu",
|
||||
"type": "handakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ぺ",
|
||||
"roumaji": "pe",
|
||||
"type": "handakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ぽ",
|
||||
"roumaji": "po",
|
||||
"type": "handakuon"
|
||||
},
|
||||
{
|
||||
"kana": "っ",
|
||||
"roumaji": "(pause)",
|
||||
"type": "sokuon"
|
||||
},
|
||||
{
|
||||
"kana": "きゃ",
|
||||
"roumaji": "kya",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "きゅ",
|
||||
"roumaji": "kyu",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "きょ",
|
||||
"roumaji": "kyo",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "しゃ",
|
||||
"roumaji": "sha",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "しゅ",
|
||||
"roumaji": "shu",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "しょ",
|
||||
"roumaji": "sho",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ちゃ",
|
||||
"roumaji": "cha",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ちゅ",
|
||||
"roumaji": "chu",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ちょ",
|
||||
"roumaji": "cho",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "にゃ",
|
||||
"roumaji": "nya",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "にゅ",
|
||||
"roumaji": "nyu",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "にょ",
|
||||
"roumaji": "nyo",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ひゃ",
|
||||
"roumaji": "hya",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ひゅ",
|
||||
"roumaji": "hyu",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ひょ",
|
||||
"roumaji": "hyo",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "みゃ",
|
||||
"roumaji": "mya",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "みゅ",
|
||||
"roumaji": "myu",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "みょ",
|
||||
"roumaji": "myo",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "りゃ",
|
||||
"roumaji": "rya",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "りゅ",
|
||||
"roumaji": "ryu",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "りょ",
|
||||
"roumaji": "ryo",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ぎゃ",
|
||||
"roumaji": "gya",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ぎゅ",
|
||||
"roumaji": "gyu",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ぎょ",
|
||||
"roumaji": "gyo",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "じゃ",
|
||||
"roumaji": "ja",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "じゅ",
|
||||
"roumaji": "ju",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "じょ",
|
||||
"roumaji": "jo",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "びゃ",
|
||||
"roumaji": "bya",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "びゅ",
|
||||
"roumaji": "byu",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "びょ",
|
||||
"roumaji": "byo",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ぴゃ",
|
||||
"roumaji": "pya",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ぴゅ",
|
||||
"roumaji": "pyu",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ぴょ",
|
||||
"roumaji": "pyo",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "いぃ",
|
||||
"roumaji": "yi",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "いぇ",
|
||||
"roumaji": "ye",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ゔぁ",
|
||||
"roumaji": "va",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ゔぃ",
|
||||
"roumaji": "vi",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ゔ",
|
||||
"roumaji": "vu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ゔぇ",
|
||||
"roumaji": "ve",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ゔぉ",
|
||||
"roumaji": "vo",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ゔゃ",
|
||||
"roumaji": "vya",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ゔゅ",
|
||||
"roumaji": "vyu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ゔょ",
|
||||
"roumaji": "vyo",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "しぇ",
|
||||
"roumaji": "she",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "じぇ",
|
||||
"roumaji": "je",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ちぇ",
|
||||
"roumaji": "che",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "すぁ",
|
||||
"roumaji": "swa",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "すぃ",
|
||||
"roumaji": "swi",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "すぅ",
|
||||
"roumaji": "swu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "すぇ",
|
||||
"roumaji": "swe",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "すぉ",
|
||||
"roumaji": "swo",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "すゃ",
|
||||
"roumaji": "sya",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "すゅ",
|
||||
"roumaji": "syu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "すょ",
|
||||
"roumaji": "syo",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "せぃ",
|
||||
"roumaji": "si",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ずぁ",
|
||||
"roumaji": "zwa",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ずぃ",
|
||||
"roumaji": "zwi",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ずぅ",
|
||||
"roumaji": "zwu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ずぇ",
|
||||
"roumaji": "zwe",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ずぉ",
|
||||
"roumaji": "zwo",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ずゃ",
|
||||
"roumaji": "zya",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ずゅ",
|
||||
"roumaji": "zyu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ずょ",
|
||||
"roumaji": "zyo",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ゼぃ",
|
||||
"roumaji": "zi",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "つぁ",
|
||||
"roumaji": "tsa",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "つぃ",
|
||||
"roumaji": "tsi",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "つぇ",
|
||||
"roumaji": "tse",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "つぉ",
|
||||
"roumaji": "tso",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "てぁ",
|
||||
"roumaji": "tha",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "てぃ",
|
||||
"roumaji": "ti",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "てぅ",
|
||||
"roumaji": "thu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "てぇ",
|
||||
"roumaji": "tye",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "てぉ",
|
||||
"roumaji": "tho",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "てゃ",
|
||||
"roumaji": "tya",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "てゅ",
|
||||
"roumaji": "tyu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "てょ",
|
||||
"roumaji": "tyo",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "でぁ",
|
||||
"roumaji": "dha",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "でぃ",
|
||||
"roumaji": "di",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "でぅ",
|
||||
"roumaji": "dhu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "でぇ",
|
||||
"roumaji": "dye",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "でぉ",
|
||||
"roumaji": "dho",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "でゃ",
|
||||
"roumaji": "dya",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "でゅ",
|
||||
"roumaji": "dyu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "でょ",
|
||||
"roumaji": "dyo",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "とぁ",
|
||||
"roumaji": "twa",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "とぃ",
|
||||
"roumaji": "twi",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "とぅ",
|
||||
"roumaji": "tu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "とぇ",
|
||||
"roumaji": "twe",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "とぉ",
|
||||
"roumaji": "two",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "どぁ",
|
||||
"roumaji": "dwa",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "どぃ",
|
||||
"roumaji": "dwi",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "どぅ",
|
||||
"roumaji": "du",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "どぇ",
|
||||
"roumaji": "dwe",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "どぉ",
|
||||
"roumaji": "dwo",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ふぁ",
|
||||
"roumaji": "fa",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ふぃ",
|
||||
"roumaji": "fi",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ほぅ",
|
||||
"roumaji": "hu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ふぇ",
|
||||
"roumaji": "fe",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ふぉ",
|
||||
"roumaji": "fo",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ふゃ",
|
||||
"roumaji": "fya",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ふゅ",
|
||||
"roumaji": "fyu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ふょ",
|
||||
"roumaji": "fyo",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "りぃ",
|
||||
"roumaji": "ryi",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "りぇ",
|
||||
"roumaji": "rye",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "うぁ",
|
||||
"roumaji": "(wa)",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "うぃ",
|
||||
"roumaji": "wi",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "うぅ",
|
||||
"roumaji": "(wu)",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "うぇ",
|
||||
"roumaji": "we",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "うぉ",
|
||||
"roumaji": "wo",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "うゃ",
|
||||
"roumaji": "wya",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "うゅ",
|
||||
"roumaji": "wyu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "うょ",
|
||||
"roumaji": "wyo",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "くぁ",
|
||||
"roumaji": "kwa",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "くぃ",
|
||||
"roumaji": "kwi",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "くぅ",
|
||||
"roumaji": "kwu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "くぇ",
|
||||
"roumaji": "kwe",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "くぉ",
|
||||
"roumaji": "kwo",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ぐぁ",
|
||||
"roumaji": "gwa",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ぐぃ",
|
||||
"roumaji": "gwi",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ぐぅ",
|
||||
"roumaji": "gwu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ぐぇ",
|
||||
"roumaji": "gwe",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ぐぉ",
|
||||
"roumaji": "gwe",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "むぁ",
|
||||
"roumaji": "mwa",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "むぃ",
|
||||
"roumaji": "mwi",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "むぅ",
|
||||
"roumaji": "mwu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "むぇ",
|
||||
"roumaji": "mwe",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "むぉ",
|
||||
"roumaji": "mwo",
|
||||
"type": "extended"
|
||||
}
|
||||
]
|
|
@ -0,0 +1,992 @@
|
|||
[
|
||||
{
|
||||
"kana": "ア",
|
||||
"roumaji": "a",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "イ",
|
||||
"roumaji": "i",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ウ",
|
||||
"roumaji": "u",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "エ",
|
||||
"roumaji": "e",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "オ",
|
||||
"roumaji": "o",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "カ",
|
||||
"roumaji": "ka",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "キ",
|
||||
"roumaji": "ki",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ク",
|
||||
"roumaji": "ku",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ケ",
|
||||
"roumaji": "ke",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "コ",
|
||||
"roumaji": "ko",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "サ",
|
||||
"roumaji": "sa",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "シ",
|
||||
"roumaji": "shi",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ス",
|
||||
"roumaji": "su",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "セ",
|
||||
"roumaji": "se",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ソ",
|
||||
"roumaji": "so",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "タ",
|
||||
"roumaji": "ta",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "チ",
|
||||
"roumaji": "chi",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ツ",
|
||||
"roumaji": "tsu",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "テ",
|
||||
"roumaji": "te",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ト",
|
||||
"roumaji": "to",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ナ",
|
||||
"roumaji": "na",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ニ",
|
||||
"roumaji": "ni",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ヌ",
|
||||
"roumaji": "nu",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ネ",
|
||||
"roumaji": "ne",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ノ",
|
||||
"roumaji": "no",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ハ",
|
||||
"roumaji": "ha",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ヒ",
|
||||
"roumaji": "hi",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "フ",
|
||||
"roumaji": "hu",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ヘ",
|
||||
"roumaji": "he",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ホ",
|
||||
"roumaji": "ho",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "マ",
|
||||
"roumaji": "ma",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ミ",
|
||||
"roumaji": "mi",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ム",
|
||||
"roumaji": "mu",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "メ",
|
||||
"roumaji": "me",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "モ",
|
||||
"roumaji": "mo",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ヤ",
|
||||
"roumaji": "ya",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ユ",
|
||||
"roumaji": "yu",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ヨ",
|
||||
"roumaji": "yo",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ラ",
|
||||
"roumaji": "ra",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "リ",
|
||||
"roumaji": "ri",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ル",
|
||||
"roumaji": "ru",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "レ",
|
||||
"roumaji": "re",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ロ",
|
||||
"roumaji": "ro",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ワ",
|
||||
"roumaji": "wa",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ヲ",
|
||||
"roumaji": "wo",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ン",
|
||||
"roumaji": "n",
|
||||
"type": "gojuuon"
|
||||
},
|
||||
{
|
||||
"kana": "ガ",
|
||||
"roumaji": "ga",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ギ",
|
||||
"roumaji": "gi",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "グ",
|
||||
"roumaji": "gu",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ゲ",
|
||||
"roumaji": "ge",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ゴ",
|
||||
"roumaji": "go",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ザ",
|
||||
"roumaji": "za",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ジ",
|
||||
"roumaji": "ji",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ズ",
|
||||
"roumaji": "zu",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ゼ",
|
||||
"roumaji": "ze",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ゾ",
|
||||
"roumaji": "zo",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ダ",
|
||||
"roumaji": "da",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ヂ",
|
||||
"roumaji": "ji",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ヅ",
|
||||
"roumaji": "zu",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "デ",
|
||||
"roumaji": "de",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ド",
|
||||
"roumaji": "do",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "バ",
|
||||
"roumaji": "ba",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ビ",
|
||||
"roumaji": "bi",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ブ",
|
||||
"roumaji": "bu",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ベ",
|
||||
"roumaji": "be",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ボ",
|
||||
"roumaji": "bo",
|
||||
"type": "dakuon"
|
||||
},
|
||||
{
|
||||
"kana": "パ",
|
||||
"roumaji": "pa",
|
||||
"type": "handakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ピ",
|
||||
"roumaji": "pi",
|
||||
"type": "handakuon"
|
||||
},
|
||||
{
|
||||
"kana": "プ",
|
||||
"roumaji": "pu",
|
||||
"type": "handakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ペ",
|
||||
"roumaji": "pe",
|
||||
"type": "handakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ポ",
|
||||
"roumaji": "po",
|
||||
"type": "handakuon"
|
||||
},
|
||||
{
|
||||
"kana": "ッ",
|
||||
"roumaji": "(pause)",
|
||||
"type": "sokuon"
|
||||
},
|
||||
{
|
||||
"kana": "キャ",
|
||||
"roumaji": "kya",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "キュ",
|
||||
"roumaji": "kyu",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "キョ",
|
||||
"roumaji": "kyo",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "シャ",
|
||||
"roumaji": "sha",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "シュ",
|
||||
"roumaji": "shu",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ショ",
|
||||
"roumaji": "sho",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "チャ",
|
||||
"roumaji": "cha",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "チュ",
|
||||
"roumaji": "chu",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "チョ",
|
||||
"roumaji": "cho",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ニャ",
|
||||
"roumaji": "nya",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ニュ",
|
||||
"roumaji": "nyu",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ニョ",
|
||||
"roumaji": "nyo",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ヒャ",
|
||||
"roumaji": "hya",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ヒュ",
|
||||
"roumaji": "hyu",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ヒョ",
|
||||
"roumaji": "hyo",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ミャ",
|
||||
"roumaji": "mya",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ミュ",
|
||||
"roumaji": "myu",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ミョ",
|
||||
"roumaji": "myo",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "リャ",
|
||||
"roumaji": "rya",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "リュ",
|
||||
"roumaji": "ryu",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "リョ",
|
||||
"roumaji": "ryo",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ギャ",
|
||||
"roumaji": "gya",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ギュ",
|
||||
"roumaji": "gyu",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ギョ",
|
||||
"roumaji": "gyo",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ジャ",
|
||||
"roumaji": "ja",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ジュ",
|
||||
"roumaji": "ju",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ジョ",
|
||||
"roumaji": "jo",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ビャ",
|
||||
"roumaji": "bya",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ビュ",
|
||||
"roumaji": "byu",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ビョ",
|
||||
"roumaji": "byo",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ピャ",
|
||||
"roumaji": "pya",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ピュ",
|
||||
"roumaji": "pyu",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "ピョ",
|
||||
"roumaji": "pyo",
|
||||
"type": "youon"
|
||||
},
|
||||
{
|
||||
"kana": "イィ",
|
||||
"roumaji": "yi",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "イェ",
|
||||
"roumaji": "ye",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ヴァ",
|
||||
"roumaji": "va",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ヴィ",
|
||||
"roumaji": "vi",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ヴ",
|
||||
"roumaji": "vu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ヴェ",
|
||||
"roumaji": "ve",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ヴォ",
|
||||
"roumaji": "vo",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ヴャ",
|
||||
"roumaji": "vya",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ヴュ",
|
||||
"roumaji": "vyu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ヴョ",
|
||||
"roumaji": "vyo",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "シェ",
|
||||
"roumaji": "she",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ジェ",
|
||||
"roumaji": "je",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "チェ",
|
||||
"roumaji": "che",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "スァ",
|
||||
"roumaji": "swa",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "スィ",
|
||||
"roumaji": "swi",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "スゥ",
|
||||
"roumaji": "swu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "スェ",
|
||||
"roumaji": "swe",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "スォ",
|
||||
"roumaji": "swo",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "スャ",
|
||||
"roumaji": "sya",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "スュ",
|
||||
"roumaji": "syu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "スョ",
|
||||
"roumaji": "syo",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "セィ",
|
||||
"roumaji": "si",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ズァ",
|
||||
"roumaji": "zwa",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ズィ",
|
||||
"roumaji": "zwi",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ズゥ",
|
||||
"roumaji": "zwu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ズェ",
|
||||
"roumaji": "zwe",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ズォ",
|
||||
"roumaji": "zwo",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ズャ",
|
||||
"roumaji": "zya",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ズュ",
|
||||
"roumaji": "zyu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ズョ",
|
||||
"roumaji": "zyo",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ゼィ",
|
||||
"roumaji": "zi",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ツァ",
|
||||
"roumaji": "tsa",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ツィ",
|
||||
"roumaji": "tsi",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ツェ",
|
||||
"roumaji": "tse",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ツォ",
|
||||
"roumaji": "tso",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "テァ",
|
||||
"roumaji": "tha",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ティ",
|
||||
"roumaji": "ti",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "テゥ",
|
||||
"roumaji": "thu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "テェ",
|
||||
"roumaji": "tye",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "テォ",
|
||||
"roumaji": "tho",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "テャ",
|
||||
"roumaji": "tya",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "テュ",
|
||||
"roumaji": "tyu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "テョ",
|
||||
"roumaji": "tyo",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "デァ",
|
||||
"roumaji": "dha",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ディ",
|
||||
"roumaji": "di",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "デゥ",
|
||||
"roumaji": "dhu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "デェ",
|
||||
"roumaji": "dye",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "デォ",
|
||||
"roumaji": "dho",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "デャ",
|
||||
"roumaji": "dya",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "デュ",
|
||||
"roumaji": "dyu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "デョ",
|
||||
"roumaji": "dyo",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "トァ",
|
||||
"roumaji": "twa",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "トィ",
|
||||
"roumaji": "twi",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "トゥ",
|
||||
"roumaji": "tu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "トェ",
|
||||
"roumaji": "twe",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "トォ",
|
||||
"roumaji": "two",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ドァ",
|
||||
"roumaji": "dwa",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ドィ",
|
||||
"roumaji": "dwi",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ドェ",
|
||||
"roumaji": "dwe",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ドォ",
|
||||
"roumaji": "dwo",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ファ",
|
||||
"roumaji": "fa",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "フィ",
|
||||
"roumaji": "fi",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ホゥ",
|
||||
"roumaji": "hu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "フェ",
|
||||
"roumaji": "fe",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "フォ",
|
||||
"roumaji": "fo",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "フャ",
|
||||
"roumaji": "fya",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "フュ",
|
||||
"roumaji": "fyu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "フョ",
|
||||
"roumaji": "fyo",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "リィ",
|
||||
"roumaji": "ryi",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "リェ",
|
||||
"roumaji": "rye",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ウァ",
|
||||
"roumaji": "(wa)",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ウィ",
|
||||
"roumaji": "wi",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ウゥ",
|
||||
"roumaji": "(wu)",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ウェ",
|
||||
"roumaji": "we",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ウォ",
|
||||
"roumaji": "wo",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ウャ",
|
||||
"roumaji": "wya",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ウュ",
|
||||
"roumaji": "wyu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ウョ",
|
||||
"roumaji": "wyo",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "クァ",
|
||||
"roumaji": "kwa",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "クィ",
|
||||
"roumaji": "kwi",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "クゥ",
|
||||
"roumaji": "kwu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "クェ",
|
||||
"roumaji": "kwe",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "クォ",
|
||||
"roumaji": "kwo",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "グァ",
|
||||
"roumaji": "gwa",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "グィ",
|
||||
"roumaji": "gwi",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "グゥ",
|
||||
"roumaji": "gwu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "グェ",
|
||||
"roumaji": "gwe",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "グォ",
|
||||
"roumaji": "gwe",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ムァ",
|
||||
"roumaji": "mwa",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ムィ",
|
||||
"roumaji": "mwi",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ムゥ",
|
||||
"roumaji": "mwu",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ムェ",
|
||||
"roumaji": "mwe",
|
||||
"type": "extended"
|
||||
},
|
||||
{
|
||||
"kana": "ムォ",
|
||||
"roumaji": "mwo",
|
||||
"type": "extended"
|
||||
}
|
||||
]
|
|
@ -0,0 +1,231 @@
|
|||
package JapaChar;
|
||||
|
||||
use v5.38.2;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use feature 'signatures';
|
||||
|
||||
use Moo;
|
||||
use Path::Tiny;
|
||||
use Glib::Object::Introspection;
|
||||
use YAML::PP;
|
||||
use JapaChar::DB;
|
||||
use JapaChar::Characters;
|
||||
use Pango;
|
||||
use Crypt::URandom qw( urandom );
|
||||
|
||||
use Glib::IO;
|
||||
|
||||
use constant PANGO_SCALE => 1024;
|
||||
|
||||
Glib::Object::Introspection->setup(
|
||||
basename => 'Gtk',
|
||||
version => '4.0',
|
||||
package => 'Gtk',
|
||||
);
|
||||
|
||||
Glib::Object::Introspection->setup(
|
||||
basename => 'Gdk',
|
||||
version => '4.0',
|
||||
package => 'Gtk::Gdk',
|
||||
);
|
||||
|
||||
Glib::Object::Introspection->setup(
|
||||
basename => 'Gsk',
|
||||
version => '4.0',
|
||||
package => 'Gtk::Gsk',
|
||||
);
|
||||
|
||||
has _counter => (
|
||||
is => 'rw',
|
||||
);
|
||||
|
||||
sub config($class) {
|
||||
my $ypp = YAML::PP->new;
|
||||
$ypp->load_file(''.path(__FILE__)->parent->parent->child('config.yml'));
|
||||
}
|
||||
|
||||
sub _start_lesson($self, $window, $type = undef) {
|
||||
$self->_counter(11);
|
||||
$self->_new_challenge($window, $type);
|
||||
}
|
||||
|
||||
sub _new_challenge($self, $window, $type = undef) {
|
||||
$self->_counter($self->_counter - 1);
|
||||
if ($self->_counter < 1) {
|
||||
$self->_create_main_menu($window);
|
||||
return;
|
||||
}
|
||||
my $rng = urandom(4);
|
||||
$rng = unpack 'L', $rng;
|
||||
$rng = ($rng % 100) + 1;
|
||||
if ($rng > 50) {
|
||||
$self->_new_challenge_romanji($window, $type);
|
||||
return;
|
||||
}
|
||||
$self->_new_challenge_kana($window, $type);
|
||||
}
|
||||
|
||||
sub _new_challenge_romanji($self, $window, $type = undef) {
|
||||
my $show = 'romanji';
|
||||
my $guess = 'kana';
|
||||
$self->_new_challenge_generic_code($window, $type, $show, $guess);
|
||||
}
|
||||
|
||||
sub _new_challenge_generic_code($self, $window, $type, $show, $guess) {
|
||||
my $grid = $self->_create_grid_challenge;
|
||||
my $char = JapaChar::Characters->new->next_char($type);
|
||||
my $kana_label = $self->_get_label_featured_character($char->get($show));
|
||||
$kana_label->set_halign('center');
|
||||
$kana_label->set_valign('center');
|
||||
$grid->attach($kana_label, 0, 0, 12, 1);
|
||||
$window->set_child($grid);
|
||||
my $incorrect_chars = JapaChar::Characters->new->get_4_incorrect_answers($char);
|
||||
my @buttons;
|
||||
my $continue_button = Gtk::Button->new_with_label('Continue');
|
||||
$continue_button->set_valign('center');
|
||||
$continue_button->set_halign('end');
|
||||
$continue_button->set_sensitive(0);
|
||||
my $on_answer = sub {
|
||||
$continue_button->set_sensitive(1);
|
||||
};
|
||||
my $correct_answer_button = Gtk::ToggleButton->new_with_label($char->get($guess));
|
||||
my $final_answer;
|
||||
$correct_answer_button->signal_connect('clicked', sub {
|
||||
$final_answer = $char->get($guess);
|
||||
$on_answer->();
|
||||
});
|
||||
push @buttons, $correct_answer_button;
|
||||
for my $char (@$incorrect_chars) {
|
||||
my $incorrect_button = Gtk::ToggleButton->new_with_label($char->get($guess));
|
||||
$incorrect_button->set_group($correct_answer_button);
|
||||
$incorrect_button->signal_connect('clicked', sub {
|
||||
$final_answer = $char->get($guess);
|
||||
$on_answer->();
|
||||
});
|
||||
push @buttons, $incorrect_button;
|
||||
}
|
||||
@buttons = sort { rand() <=> rand() } @buttons;
|
||||
my $box = Gtk::Box->new('horizontal', 10);
|
||||
$box->set_valign('center');
|
||||
$box->set_halign('center');
|
||||
for my $button (@buttons) {
|
||||
my $attr_list = Pango::AttrList->new;
|
||||
my $size = Pango::AttrSize->new(42 * PANGO_SCALE);
|
||||
$attr_list->insert($size);
|
||||
$button->get_child->set_attributes($attr_list);
|
||||
$box->append($button);
|
||||
}
|
||||
my $first_press_continue = 1;
|
||||
$continue_button->signal_connect('clicked', sub {
|
||||
if (!$first_press_continue) {
|
||||
$self->_new_challenge($window, $type);
|
||||
return;
|
||||
}
|
||||
$first_press_continue = 0;
|
||||
my $label_feedback;
|
||||
{
|
||||
if ($final_answer eq $char->get($guess)) {
|
||||
$label_feedback = Gtk::Label->new('You are doing it great.');
|
||||
$label_feedback->add_css_class('success');
|
||||
$char->success;
|
||||
next;
|
||||
}
|
||||
$label_feedback = Gtk::Label->new('Meck!! The correct answer is ' . $char->get($guess));
|
||||
$label_feedback->add_css_class('error');
|
||||
$char->fail;
|
||||
}
|
||||
my $attr_list = Pango::AttrList->new;
|
||||
my $size = Pango::AttrSize->new(18 * PANGO_SCALE);
|
||||
$attr_list->insert($size);
|
||||
$label_feedback->set_attributes($attr_list);
|
||||
$grid->attach($label_feedback, 0, 2, 7, 1);
|
||||
});
|
||||
$grid->attach($box, 0, 1, 12, 1);
|
||||
my $attr_list = Pango::AttrList->new;
|
||||
my $size = Pango::AttrSize->new(25 * PANGO_SCALE);
|
||||
$attr_list->insert($size);
|
||||
$continue_button->get_child->set_attributes($attr_list);
|
||||
$grid->attach($continue_button, 6, 2, 5, 1);
|
||||
}
|
||||
|
||||
sub _new_challenge_kana($self, $window, $type = undef) {
|
||||
my $show = 'kana';
|
||||
my $guess = 'romanji';
|
||||
$self->_new_challenge_generic_code($window, $type, $show, $guess);
|
||||
}
|
||||
|
||||
sub _create_grid_challenge($self) {
|
||||
my $grid = Gtk::Grid->new;
|
||||
$grid->set_column_homogeneous(1);
|
||||
$grid->set_row_homogeneous(1);
|
||||
return $grid;
|
||||
}
|
||||
|
||||
sub _get_label_featured_character($self, $text) {
|
||||
my $label = Gtk::Label->new($text);
|
||||
my $attr_list = Pango::AttrList->new;
|
||||
my $size = Pango::AttrSize->new(72 * PANGO_SCALE);
|
||||
$attr_list->insert($size);
|
||||
$label->set_attributes($attr_list);
|
||||
$label->set_halign('center');
|
||||
return $label;
|
||||
}
|
||||
|
||||
sub _create_main_menu($self, $window) {
|
||||
my $grid = Gtk::Grid->new;
|
||||
my $button_start_basic_lesson = Gtk::Button->new_with_label('Basic Characters');
|
||||
$button_start_basic_lesson->signal_connect('clicked', sub {
|
||||
$self->_start_lesson($window);
|
||||
});
|
||||
$grid->set_column_homogeneous(1);
|
||||
$grid->set_row_homogeneous(1);
|
||||
my $button_start_hiragana_lesson = Gtk::Button->new_with_label('Hiragana');
|
||||
$button_start_hiragana_lesson->signal_connect('clicked', sub {
|
||||
$self->_start_lesson($window, 'hiragana');
|
||||
});
|
||||
my $button_start_katakana_lesson = Gtk::Button->new_with_label('Katakana');
|
||||
$button_start_katakana_lesson->signal_connect('clicked', sub {
|
||||
$self->_start_lesson($window, 'katakana');
|
||||
});
|
||||
for my $button ($button_start_basic_lesson, $button_start_hiragana_lesson, $button_start_katakana_lesson) {
|
||||
my $attr_list = Pango::AttrList->new;
|
||||
my $size = Pango::AttrSize->new(25 * PANGO_SCALE);
|
||||
$attr_list->insert($size);
|
||||
$button->get_child->set_attributes($attr_list);
|
||||
}
|
||||
my $box = Gtk::Box->new('horizontal', 10);
|
||||
$grid->attach($button_start_basic_lesson, 0, 0, 5, 1);
|
||||
$button_start_basic_lesson->set_valign('end');
|
||||
$button_start_basic_lesson->set_halign('center');
|
||||
$box->set_margin_top(40);
|
||||
$box->append($button_start_hiragana_lesson);
|
||||
$box->append($button_start_katakana_lesson);
|
||||
$box->set_valign('start');
|
||||
$box->set_halign('center');
|
||||
$grid->attach($box, 0, 1, 5, 1);
|
||||
$window->set_child($grid);
|
||||
}
|
||||
|
||||
sub _application_start($self, $app) {
|
||||
my $main_window = Gtk::ApplicationWindow->new($app);
|
||||
$main_window->set_title('JapaChar');
|
||||
$main_window->set_default_size(600, 600);
|
||||
my $display = $main_window->get_property('display');
|
||||
my $css_provider = Gtk::CssProvider->new;
|
||||
$css_provider->load_from_path(path(__FILE__)->parent->parent->child('styles.css')->absolute);
|
||||
Gtk::StyleContext::add_provider_for_display($display, $css_provider, 'priority-fallback');
|
||||
$self->_create_main_menu($main_window);
|
||||
$main_window->present;
|
||||
}
|
||||
|
||||
sub start($self) {
|
||||
my $app = Gtk::Application->new('me.sergiotarxz.japchar', 'default-flags');
|
||||
$app->signal_connect('activate' => sub {
|
||||
$self->_application_start($app);
|
||||
});
|
||||
$app->run;
|
||||
}
|
||||
1;
|
|
@ -0,0 +1,146 @@
|
|||
package JapaChar::Characters;
|
||||
|
||||
use v5.38.2;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Moo;
|
||||
use Path::Tiny;
|
||||
use JSON;
|
||||
use Data::Dumper;
|
||||
|
||||
my $option_populated = 'populated_basic_characters';
|
||||
require JapaChar::DB;
|
||||
require JapaChar::Schema;
|
||||
|
||||
sub populate_basic_characters($self) {
|
||||
my $dbh = JapaChar::DB->connect;
|
||||
my $result = $dbh->selectrow_hashref(
|
||||
'SELECT value
|
||||
FROM options
|
||||
WHERE name = ?', {}, $option_populated
|
||||
);
|
||||
if ( defined $result && $result->{value} ) {
|
||||
return;
|
||||
}
|
||||
$self->_populate_type('hiragana');
|
||||
$self->_populate_type('katakana');
|
||||
$dbh->do( 'INSERT INTO options (name, value) VALUES (?, ?);',
|
||||
undef, $option_populated, 1 );
|
||||
}
|
||||
|
||||
sub _populate_type( $self, $type ) {
|
||||
my $basic_character_resultset =
|
||||
JapaChar::Schema->Schema->resultset('BasicCharacter');
|
||||
for my $char ( @{ $self->_get_characters_of_type($type) } ) {
|
||||
my $kana = $char->{kana};
|
||||
my $romanji = $char->{roumaji};
|
||||
next if $romanji =~ /pause/i;
|
||||
$basic_character_resultset->new(
|
||||
{ value => $kana, romanji => $romanji, type => $type, } )->insert;
|
||||
}
|
||||
}
|
||||
|
||||
sub _get_characters_of_type( $self, $type ) {
|
||||
my $current_file = path __FILE__;
|
||||
my $array =
|
||||
from_json( $current_file->parent->parent->parent->child("$type.json")
|
||||
->slurp_utf8 );
|
||||
return $array;
|
||||
}
|
||||
|
||||
sub get_4_incorrect_answers( $self, $char ) {
|
||||
my $basic_character_resultset =
|
||||
JapaChar::Schema->Schema->resultset('BasicCharacter');
|
||||
my @bad_answers = $basic_character_resultset->search(
|
||||
{
|
||||
type => $char->type,
|
||||
value => { '!=', $char->value },
|
||||
romanji => { '!=', $char->romanji },
|
||||
-bool => 'started',
|
||||
},
|
||||
{
|
||||
order_by => { -asc => \'RANDOM()' },
|
||||
rows => 4,
|
||||
}
|
||||
);
|
||||
return \@bad_answers;
|
||||
}
|
||||
|
||||
sub next_review_char( $self, $type = undef ) {
|
||||
my $basic_character_resultset =
|
||||
JapaChar::Schema->Schema->resultset('BasicCharacter');
|
||||
my @chars = $basic_character_resultset->search(
|
||||
{
|
||||
score => { '>=' => 100 },
|
||||
(
|
||||
( defined $type ) ? ( type => $type, ) : ()
|
||||
)
|
||||
},
|
||||
{
|
||||
order_by => { -asc => \'RANDOM()' },
|
||||
rows => 1
|
||||
}
|
||||
);
|
||||
if ( !@chars ) {
|
||||
return;
|
||||
}
|
||||
return $chars[0];
|
||||
}
|
||||
|
||||
sub next_char( $self, $type = undef ) {
|
||||
my $next_review = $self->next_review_char($type);
|
||||
my $next_learning = $self->next_learning_char($type);
|
||||
if ( !defined $next_review ) {
|
||||
return $next_learning;
|
||||
}
|
||||
my $rng = int( rand(100) ) + 1;
|
||||
if ( $rng > 20 ) {
|
||||
return $next_learning;
|
||||
}
|
||||
return $next_review;
|
||||
}
|
||||
|
||||
sub next_learning_char( $self, $type = undef ) {
|
||||
$self->populate_basic_characters;
|
||||
my $basic_character_resultset =
|
||||
JapaChar::Schema->Schema->resultset('BasicCharacter');
|
||||
my @candidate_chars = $self->_retrieve_started_chars_not_finished($type);
|
||||
if ( @candidate_chars < 5 ) {
|
||||
my @new_chars = $basic_character_resultset->search(
|
||||
{
|
||||
-not_bool => 'started',
|
||||
(
|
||||
( defined $type ) ? ( type => $type, ) : ()
|
||||
)
|
||||
},
|
||||
{
|
||||
order_by => { -asc => 'id' },
|
||||
rows => 5 - scalar @candidate_chars,
|
||||
}
|
||||
);
|
||||
for my $char (@new_chars) {
|
||||
$char->update( { started => 1 } );
|
||||
}
|
||||
@candidate_chars = $self->_retrieve_started_chars_not_finished($type);
|
||||
}
|
||||
my $char = $candidate_chars[ int( rand( scalar @candidate_chars ) ) ];
|
||||
return $char;
|
||||
}
|
||||
|
||||
sub _retrieve_started_chars_not_finished( $self, $type ) {
|
||||
my $basic_character_resultset =
|
||||
JapaChar::Schema->Schema->resultset('BasicCharacter');
|
||||
return $basic_character_resultset->search(
|
||||
{
|
||||
(
|
||||
( defined $type ) ? ( type => $type, ) : ()
|
||||
),
|
||||
score => { '<' => 100 },
|
||||
-bool => 'started',
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
1;
|
|
@ -0,0 +1,109 @@
|
|||
package JapaChar::DB;
|
||||
|
||||
use v5.38.2;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use feature 'signatures';
|
||||
|
||||
use DBI;
|
||||
use DBD::SQLite;
|
||||
|
||||
use JapaChar::DB::Migrations;
|
||||
use Path::Tiny;
|
||||
use Data::Dumper;
|
||||
|
||||
my $dbh;
|
||||
|
||||
sub connect {
|
||||
if ( defined $dbh ) {
|
||||
return $dbh;
|
||||
}
|
||||
my $class = shift;
|
||||
require JapaChar;
|
||||
my $app = JapaChar->new;
|
||||
my $config = $app->config;
|
||||
my $db_path = $class->_db_path;
|
||||
$dbh = DBI->connect(
|
||||
'dbi:SQLite:dbname='.$db_path,
|
||||
undef, undef,
|
||||
{
|
||||
RaiseError => 1,
|
||||
},
|
||||
);
|
||||
$class->_migrate($dbh);
|
||||
return $dbh;
|
||||
}
|
||||
|
||||
sub _db_path($class) {
|
||||
my $home = $ENV{HOME};
|
||||
my $db_path = '';
|
||||
$db_path = $home . '/' if $home;
|
||||
$db_path .= '.japachar/db.sqlite';
|
||||
path($db_path)->parent->mkpath;
|
||||
return $db_path;
|
||||
}
|
||||
|
||||
sub _migrate {
|
||||
my $class = shift;
|
||||
my $dbh = shift;
|
||||
local $dbh->{RaiseError} = 0;
|
||||
local $dbh->{PrintError} = 0;
|
||||
my @migrations = JapaChar::DB::Migrations::MIGRATIONS();
|
||||
if ( $class->get_current_migration($dbh) > @migrations ) {
|
||||
warn "Something happened there, wrong migration number.";
|
||||
}
|
||||
if ( $class->get_current_migration($dbh) >= @migrations ) {
|
||||
say STDERR "Migrations already applied.";
|
||||
return;
|
||||
}
|
||||
$class->_apply_migrations( $dbh, \@migrations );
|
||||
}
|
||||
|
||||
sub _apply_migrations {
|
||||
my $class = shift;
|
||||
my $dbh = shift;
|
||||
my $migrations = shift;
|
||||
for (
|
||||
my $i = $class->get_current_migration($dbh) ;
|
||||
$i < @$migrations ;
|
||||
$i++
|
||||
)
|
||||
{
|
||||
local $dbh->{RaiseError} = 1;
|
||||
my $current_migration = $migrations->[$i];
|
||||
my $migration_number = $i + 1;
|
||||
$class->_apply_migration( $dbh, $current_migration, $migration_number );
|
||||
}
|
||||
}
|
||||
|
||||
sub _apply_migration {
|
||||
my $class = shift;
|
||||
my $dbh = shift;
|
||||
my $current_migration = shift;
|
||||
my $migration_number = shift;
|
||||
{
|
||||
if (ref $current_migration eq 'CODE') {
|
||||
$current_migration->($dbh);
|
||||
next;
|
||||
}
|
||||
$dbh->do($current_migration);
|
||||
}
|
||||
$dbh->do( <<'EOF', undef, 'current_migration', $migration_number );
|
||||
INSERT INTO options
|
||||
VALUES ($1, $2)
|
||||
ON CONFLICT (name) DO
|
||||
UPDATE SET value = $2;
|
||||
EOF
|
||||
}
|
||||
|
||||
sub get_current_migration {
|
||||
my $class = shift;
|
||||
my $dbh = shift;
|
||||
my $result = $dbh->selectrow_hashref( <<'EOF', undef, 'current_migration' );
|
||||
select value from options where name = ?;
|
||||
EOF
|
||||
return int( $result->{value} // 0 );
|
||||
}
|
||||
1;
|
|
@ -0,0 +1,28 @@
|
|||
package JapaChar::DB::Migrations;
|
||||
|
||||
use v5.34.1;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use utf8;
|
||||
|
||||
use feature 'signatures';
|
||||
|
||||
sub MIGRATIONS {
|
||||
return (
|
||||
'CREATE TABLE options (
|
||||
name TEXT PRIMARY KEY,
|
||||
value TEXT
|
||||
)',
|
||||
'CREATE TABLE basic_characters (
|
||||
id INTEGER PRIMARY KEY,
|
||||
value TEXT NOT NULL UNIQUE,
|
||||
romanji TEXT NOT NULL,
|
||||
type TEXT NOT NULL,
|
||||
started BOOLEAN NOT NULL DEFAULT 0,
|
||||
score INTEGER NOT NULL DEFAULT 0,
|
||||
consecutive_success INTEGER NOT NULL DEFAULT 0
|
||||
);',
|
||||
);
|
||||
}
|
||||
1;
|
|
@ -0,0 +1,32 @@
|
|||
package JapaChar::Schema;
|
||||
|
||||
use v5.36.0;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use feature 'signatures';
|
||||
|
||||
use parent 'DBIx::Class::Schema';
|
||||
|
||||
__PACKAGE__->load_namespaces();
|
||||
|
||||
my $schema;
|
||||
|
||||
sub Schema ($class) {
|
||||
if ( !defined $schema ) {
|
||||
require JapaChar::DB;
|
||||
JapaChar::DB->connect;
|
||||
my $db_path = JapaChar::DB->_db_path;
|
||||
my $user = undef;
|
||||
my $password = undef;
|
||||
# Undef is perfectly fine for username and password.
|
||||
$schema = $class->connect(
|
||||
'dbi:SQLite:dbname='.$db_path, $user, $password,
|
||||
{
|
||||
}
|
||||
);
|
||||
}
|
||||
return $schema;
|
||||
}
|
||||
1;
|
|
@ -0,0 +1,96 @@
|
|||
package JapaChar::Schema::Result::BasicCharacter;
|
||||
|
||||
use v5.38.2;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use feature 'signatures';
|
||||
|
||||
use parent 'DBIx::Class::Core';
|
||||
|
||||
use Encode qw/decode/;
|
||||
|
||||
__PACKAGE__->table('basic_characters');
|
||||
|
||||
__PACKAGE__->add_columns(
|
||||
id => {
|
||||
data_type => 'INTEGER',
|
||||
is_auto_increment => 1,
|
||||
},
|
||||
value => {
|
||||
data_type => 'TEXT',
|
||||
is_nullable => 0,
|
||||
accessor => '_value',
|
||||
},
|
||||
romanji => {
|
||||
data_type => 'TEXT',
|
||||
is_nullable => 0,
|
||||
},
|
||||
type => {
|
||||
data_type => 'TEXT',
|
||||
is_nullable => 0,
|
||||
},
|
||||
started => {
|
||||
data_type => 'BOOLEAN',
|
||||
is_nullable => 1,
|
||||
},
|
||||
score => {
|
||||
data_type => 'INTEGER',
|
||||
is_nullable => 1,
|
||||
},
|
||||
consecutive_success => {
|
||||
data_type => 'INTEGER',
|
||||
is_nullable => 1,
|
||||
},
|
||||
);
|
||||
|
||||
sub value($self, $value = undef) {
|
||||
if (defined $value) {
|
||||
$self->_value($value);
|
||||
}
|
||||
return decode 'utf-8', $self->_value;
|
||||
}
|
||||
|
||||
__PACKAGE__->set_primary_key('id');
|
||||
|
||||
sub fail($self) {
|
||||
my $score = $self->score;
|
||||
my $consecutive_success = 0;
|
||||
$score -= 25;
|
||||
if ( $score < 0 ) {
|
||||
$score = 0;
|
||||
}
|
||||
$self->update(
|
||||
{
|
||||
score => $score,
|
||||
consecutive_success => 0
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
sub get($self, $what) {
|
||||
if ($what eq 'kana') {
|
||||
return $self->value;
|
||||
}
|
||||
if ($what eq 'romanji') {
|
||||
return $self->romanji;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
sub success($self) {
|
||||
my $score = $self->score;
|
||||
my $consecutive_success = $self->consecutive_success + 1;
|
||||
$score += 5 + 10 * $consecutive_success;
|
||||
if ( $score > 130 ) {
|
||||
$score = 130;
|
||||
}
|
||||
$self->update(
|
||||
{
|
||||
score => $score,
|
||||
consecutive_success => $consecutive_success,
|
||||
}
|
||||
);
|
||||
}
|
||||
1;
|
|
@ -0,0 +1,11 @@
|
|||
#!/usr/bin/env perl
|
||||
|
||||
use v5.38.2;
|
||||
|
||||
use File::Basename;
|
||||
|
||||
use lib dirname(dirname(__FILE__)).'/lib';
|
||||
|
||||
use JapaChar;
|
||||
|
||||
JapaChar->new->start;
|
|
@ -0,0 +1,7 @@
|
|||
.error {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.success {
|
||||
color: green;
|
||||
}
|
Loading…
Reference in New Issue