From 8e47dc24d7041d0ca1d5ed23c453e2aa633d59c0 Mon Sep 17 00:00:00 2001 From: Bill Rossi Date: Mon, 18 Aug 2025 05:05:27 -0400 Subject: [PATCH] Initial commit --- .gitignore | 1 + Rakefile | 3 + ika_conjugations.gemspec | 13 ++ lib/ika_conjugations.rb | 5 + lib/ika_conjugations/kana_kanji.rb | 43 +++++ lib/ika_conjugations/verb.rb | 181 +++++++++++++++++++ test/ika_conjugations/test_kana_kanji.rb | 117 +++++++++++++ test/ika_conjugations/test_verb.rb | 212 +++++++++++++++++++++++ 8 files changed, 575 insertions(+) create mode 100644 .gitignore create mode 100644 Rakefile create mode 100644 ika_conjugations.gemspec create mode 100644 lib/ika_conjugations.rb create mode 100644 lib/ika_conjugations/kana_kanji.rb create mode 100644 lib/ika_conjugations/verb.rb create mode 100644 test/ika_conjugations/test_kana_kanji.rb create mode 100644 test/ika_conjugations/test_verb.rb diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..86339a0 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.gem \ No newline at end of file diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..b0ec822 --- /dev/null +++ b/Rakefile @@ -0,0 +1,3 @@ +require "minitest/test_task" + +Minitest::TestTask.create diff --git a/ika_conjugations.gemspec b/ika_conjugations.gemspec new file mode 100644 index 0000000..09ae19f --- /dev/null +++ b/ika_conjugations.gemspec @@ -0,0 +1,13 @@ +Gem::Specification.new do |s| + s.name = "ika_conjugations" + s.version = "0.0.1" + s.summary = "Japanese conjugations" + s.description = "A gem with conjugation rules for Japanese grammar" + s.authors = ["Bill Rossi"] + s.email = "bassguitarbill@gmail.com" + s.homepage = + "http://whatguns.ddns.net:3000/bassguitarbill/ika_conjugations" + s.license = "GPL-3.0-only" + + s.files = Dir["{lib}/**/*.rb", "bin/*", "LICENSE", "*.md"] +end diff --git a/lib/ika_conjugations.rb b/lib/ika_conjugations.rb new file mode 100644 index 0000000..422d70e --- /dev/null +++ b/lib/ika_conjugations.rb @@ -0,0 +1,5 @@ +require "ika_conjugations/verb" + +module IkaConjugations + VERSION = "0.0.1" +end diff --git a/lib/ika_conjugations/kana_kanji.rb b/lib/ika_conjugations/kana_kanji.rb new file mode 100644 index 0000000..9099242 --- /dev/null +++ b/lib/ika_conjugations/kana_kanji.rb @@ -0,0 +1,43 @@ +module IkaConjugations + U_VOWEL_CHANGES = { + "る" => { "a" => "ら", "i" => "り", "u" => "る", "e" => "れ", "o" => "ろ" }, + "う" => { "a" => "あ", "i" => "い", "u" => "う", "e" => "え", "o" => "お" }, + "つ" => { "a" => "た", "i" => "ち", "u" => "つ", "e" => "て", "o" => "と" }, + "す" => { "a" => "さ", "i" => "し", "u" => "す", "e" => "せ", "o" => "そ" }, + "く" => { "a" => "か", "i" => "き", "u" => "く", "e" => "け", "o" => "こ" }, + "ぐ" => { "a" => "が", "i" => "ぎ", "u" => "ぐ", "e" => "げ", "o" => "ご" }, + "ぶ" => { "a" => "ば", "i" => "び", "u" => "ぶ", "e" => "べ", "o" => "ぼ" }, + "む" => { "a" => "ま", "i" => "み", "u" => "む", "e" => "め", "o" => "も" }, + "ぬ" => { "a" => "な", "i" => "に", "u" => "ぬ", "e" => "ね", "o" => "の" }, + } + + class KanaKanji + attr_reader :kana, :kanji + def initialize(kana, kanji=nil) + @kana = kana + @kanji = kanji || kana + end + + def [](index) + self.class.new kana[index], kanji[index] + end + + def +(other) + case other + when String + self.class.new kana + other, kanji + other + when KanaKanji + self.class.new kana + other.kana, kanji + other.kanji + end + end + + def last_character(new_form=nil) + return kana[-1] unless new_form + U_VOWEL_CHANGES[kana[-1]][new_form] + end + + def all_but_last_character + self.class.new kana[0...-1], kanji[0...-1] + end + end +end diff --git a/lib/ika_conjugations/verb.rb b/lib/ika_conjugations/verb.rb new file mode 100644 index 0000000..c4eb1d5 --- /dev/null +++ b/lib/ika_conjugations/verb.rb @@ -0,0 +1,181 @@ +module IkaConjugations + class Verb + TE_TA_DE_DA = { + "て" => "た", "で" => "だ" + } + + attr_reader :dict_kanji, :dict_kana, :definition, :dict + + def initialize(dict_kanji, dict_kana, definition) + @dict_kanji = dict_kanji || dict_kana + @dict_kana = dict_kana + @dict = KanaKanji.new dict_kana, dict_kanji + @definition = definition + end + + def last_character(new_form=nil) + dict.last_character(new_form) + end + + def all_but_last_character + dict.all_but_last_character + end + + def dictionary + dict + end + + def long_form_present_positive + stem + "ます" + end + + def long_form_present_negative + stem + "ません" + end + + def long_form_past_positive + stem + "ました" + end + + def long_form_past_negative + long_form_present_negative + "でした" + end + + def short_form_present_positive + dictionary + end + + def short_form_present_negative + negative_stem + "ない" + end + + def short_form_past_positive + te.all_but_last_character + TE_TA_DE_DA[te.last_character] + end + + def short_form_past_negative + short_form_present_negative.all_but_last_character + "かった" + end + + def desire + stem + "たい" + end + + def potential + Ichidan.new(potential_starter.kanji, potential_starter.kana, "to be able #{definition}") + end + class Ichidan < Verb + def stem + all_but_last_character + end + + def negative_stem + stem + end + + def te + all_but_last_character + "て" + end + + def potential_starter + stem + "られる" + end + end + + class Godan < Verb + def iku? + dict.kanji == "行く" + end + + def aru? + dict.kanji == "ある" + end + + def stem + all_but_last_character + last_character("i") + end + + def short_form_present_negative + return KanaKanji.new("ない") if aru? + + super + end + + def negative_stem + all_but_last_character + last_character("a") + end + + def potential_starter + all_but_last_character + last_character("e") + "る" + end + + def te + all_but_last_character + case last_character + when "う" + "って" + when "る" + "って" + when "つ" + "って" + when "す" + "して" + when "く" + iku? ? "って" : "いて" + when "ぐ" + "いで" + when "ぶ" + "んで" + when "む" + "んで" + when "ぬ" + "んで" + end + end + end + + class Suru < Verb + def prefix + dict[..-3] + end + + def stem + prefix + "し" + end + + def negative_stem + prefix + "し" + end + + def te + prefix + "して" + end + + def potential_starter + prefix + "できる" + end + end + + class Kuru < Verb + def prefix + dict[..-3] + end + + def te + stem + "て" + end + + def stem + prefix + KanaKanji.new("き", "来") + end + + def negative_stem + prefix + KanaKanji.new("こ", "来") + end + + def potential_starter + negative_stem + "られる" + end + end + end +end + diff --git a/test/ika_conjugations/test_kana_kanji.rb b/test/ika_conjugations/test_kana_kanji.rb new file mode 100644 index 0000000..0bae5ab --- /dev/null +++ b/test/ika_conjugations/test_kana_kanji.rb @@ -0,0 +1,117 @@ +require "ika_conjugations/kana_kanji" +require "minitest/autorun" + +module IkaConjugations + class TestKanaKanji < Minitest::Test + def test_initialize + with_kanji = KanaKanji.new("a", "b") + assert_equal "a", with_kanji.kana + assert_equal "b", with_kanji.kanji + + without_kanji = KanaKanji.new("c") + assert_equal "c", without_kanji.kana + assert_equal "c", without_kanji.kanji + end + + def test_array_index + example = KanaKanji.new("kana", "kanji") + assert_equal "a", example[-1].kana + assert_equal "i", example[-1].kanji + assert_equal "kan", example[0..2].kana + assert_equal "ji", example[-2..].kanji + end + + def test_add + prefix = KanaKanji.new("kana_prefix", "kanji_prefix") + add_string = prefix + "_single_suffix" + assert_equal "kana_prefix_single_suffix", add_string.kana + assert_equal "kanji_prefix_single_suffix", add_string.kanji + + suffix = KanaKanji.new("_kana_suffix", "_kanji_suffix") + add_kana_kanji = prefix + suffix + assert_equal "kana_prefix_kana_suffix", add_kana_kanji.kana + assert_equal "kanji_prefix_kanji_suffix", add_kana_kanji.kanji + end + + def test_last_character + toru = KanaKanji.new("取る", "とる") + assert_equal "る", toru.last_character + assert_equal "ら", toru.last_character("a") + assert_equal "り", toru.last_character("i") + assert_equal "る", toru.last_character("u") + assert_equal "れ", toru.last_character("e") + assert_equal "ろ", toru.last_character("o") + + au = KanaKanji.new("会う", "あう") + assert_equal "う", au.last_character + assert_equal "あ", au.last_character("a") + assert_equal "い", au.last_character("i") + assert_equal "う", au.last_character("u") + assert_equal "え", au.last_character("e") + assert_equal "お", au.last_character("o") + + matsu = KanaKanji.new("待つ", "まつ") + assert_equal "つ", matsu.last_character + assert_equal "た", matsu.last_character("a") + assert_equal "ち", matsu.last_character("i") + assert_equal "つ", matsu.last_character("u") + assert_equal "て", matsu.last_character("e") + assert_equal "と", matsu.last_character("o") + + hanasu = KanaKanji.new("話す", "はなす") + assert_equal "す", hanasu.last_character + assert_equal "さ", hanasu.last_character("a") + assert_equal "し", hanasu.last_character("i") + assert_equal "す", hanasu.last_character("u") + assert_equal "せ", hanasu.last_character("e") + assert_equal "そ", hanasu.last_character("o") + + iku = KanaKanji.new("行く", "いく") + assert_equal "く", iku.last_character + assert_equal "か", iku.last_character("a") + assert_equal "き", iku.last_character("i") + assert_equal "く", iku.last_character("u") + assert_equal "け", iku.last_character("e") + assert_equal "こ", iku.last_character("o") + + oyogu = KanaKanji.new("泳ぐ", "およぐ") + assert_equal "ぐ", oyogu.last_character + assert_equal "が", oyogu.last_character("a") + assert_equal "ぎ", oyogu.last_character("i") + assert_equal "ぐ", oyogu.last_character("u") + assert_equal "げ", oyogu.last_character("e") + assert_equal "ご", oyogu.last_character("o") + + asobu = KanaKanji.new("遊ぶ", "あそぶ") + assert_equal "ぶ", asobu.last_character + assert_equal "ば", asobu.last_character("a") + assert_equal "び", asobu.last_character("i") + assert_equal "ぶ", asobu.last_character("u") + assert_equal "べ", asobu.last_character("e") + assert_equal "ぼ", asobu.last_character("o") + + sumu = KanaKanji.new("住む", "すむ") + assert_equal "む", sumu.last_character + assert_equal "ま", sumu.last_character("a") + assert_equal "み", sumu.last_character("i") + assert_equal "む", sumu.last_character("u") + assert_equal "め", sumu.last_character("e") + assert_equal "も", sumu.last_character("o") + + shinu = KanaKanji.new("死ぬ", "しぬ") + assert_equal "ぬ", shinu.last_character + assert_equal "な", shinu.last_character("a") + assert_equal "に", shinu.last_character("i") + assert_equal "ぬ", shinu.last_character("u") + assert_equal "ね", shinu.last_character("e") + assert_equal "の", shinu.last_character("o") + end + + def test_all_but_last_character + unsure = KanaKanji.new("yes?", "please?") + sure = unsure.all_but_last_character + assert_equal "yes", sure.kana + assert_equal "please", sure.kanji + end + end +end diff --git a/test/ika_conjugations/test_verb.rb b/test/ika_conjugations/test_verb.rb new file mode 100644 index 0000000..9c45d90 --- /dev/null +++ b/test/ika_conjugations/test_verb.rb @@ -0,0 +1,212 @@ +require "ika_conjugations/verb" +require "minitest/autorun" + +module IkaConjugations + class TestVerb < Minitest::Test + def setup + @miru = Verb::Ichidan.new("見る", "みる", "to look") + @nomu = Verb::Godan.new("飲む", "のむ", "to drink") + @au = Verb::Godan.new("会う", "あう", "to meet") + @matsu = Verb::Godan.new("待つ", "まつ", "to wait") + @toru = Verb::Godan.new("取る", "とる", "to take") + @yomu = Verb::Godan.new("読む", "よむ", "to read") + @asobu = Verb::Godan.new("遊ぶ", "あそぶ", "to play") + @shinu = Verb::Godan.new("死ぬ", "しぬ", "to die") + @kaku = Verb::Godan.new("書く", "かく", "to write") + @iku = Verb::Godan.new("行く", "いく", "to go") + @oyogu = Verb::Godan.new("泳ぐ", "およぐ", "to swim") + @hanasu = Verb::Godan.new("話す", "はなす", "to speak") + @suru = Verb::Suru.new("する", "する", "to do") + @benkyousuru = Verb::Suru.new("勉強する", "べんきょうする", "to study") + @kuru = Verb::Kuru.new("来る", "くる", "to come") + @tsuretekuru = Verb::Kuru.new("連れて来る", "つれてくる", "to bring somebody along") + @aru = Verb::Godan.new("ある", "ある", "to be") + end + + def test_te_form + assert_equal "見て", @miru.te.kanji + assert_equal "みて", @miru.te.kana + assert_equal "飲んで", @nomu.te.kanji + assert_equal "のんで", @nomu.te.kana + assert_equal "して", @suru.te.kanji + assert_equal "して", @suru.te.kana + assert_equal "勉強して", @benkyousuru.te.kanji + assert_equal "べんきょうして", @benkyousuru.te.kana + assert_equal "会って", @au.te.kanji + assert_equal "待って", @matsu.te.kanji + assert_equal "取って", @toru.te.kanji + assert_equal "読んで", @yomu.te.kanji + assert_equal "遊んで", @asobu.te.kanji + assert_equal "死んで", @shinu.te.kanji + assert_equal "書いて", @kaku.te.kanji + assert_equal "行って", @iku.te.kanji + assert_equal "泳いで", @oyogu.te.kanji + assert_equal "話して", @hanasu.te.kanji + assert_equal "来て", @kuru.te.kanji + assert_equal "きて", @kuru.te.kana + assert_equal "連れて来て", @tsuretekuru.te.kanji + assert_equal "つれてきて", @tsuretekuru.te.kana + assert_equal "あって", @aru.te.kana + end + + def test_long_form_present_positive + assert_equal "見ます", @miru.long_form_present_positive.kanji + assert_equal "みます", @miru.long_form_present_positive.kana + assert_equal "飲みます", @nomu.long_form_present_positive.kanji + assert_equal "のみます", @nomu.long_form_present_positive.kana + assert_equal "します", @suru.long_form_present_positive.kanji + assert_equal "します", @suru.long_form_present_positive.kana + assert_equal "勉強します", @benkyousuru.long_form_present_positive.kanji + assert_equal "べんきょうします", @benkyousuru.long_form_present_positive.kana + assert_equal "来ます", @kuru.long_form_present_positive.kanji + assert_equal "きます", @kuru.long_form_present_positive.kana + assert_equal "連れて来ます", @tsuretekuru.long_form_present_positive.kanji + assert_equal "つれてきます", @tsuretekuru.long_form_present_positive.kana + assert_equal "あります", @aru.long_form_present_positive.kana + end + + def test_long_form_present_negative + assert_equal "見ません", @miru.long_form_present_negative.kanji + assert_equal "みません", @miru.long_form_present_negative.kana + assert_equal "飲みません", @nomu.long_form_present_negative.kanji + assert_equal "のみません", @nomu.long_form_present_negative.kana + assert_equal "しません", @suru.long_form_present_negative.kanji + assert_equal "しません", @suru.long_form_present_negative.kana + assert_equal "勉強しません", @benkyousuru.long_form_present_negative.kanji + assert_equal "べんきょうしません", @benkyousuru.long_form_present_negative.kana + assert_equal "来ません", @kuru.long_form_present_negative.kanji + assert_equal "きません", @kuru.long_form_present_negative.kana + assert_equal "連れて来ません", @tsuretekuru.long_form_present_negative.kanji + assert_equal "つれてきません", @tsuretekuru.long_form_present_negative.kana + assert_equal "ありません", @aru.long_form_present_negative.kana + end + + def test_short_form_present_positive + assert_equal "見る", @miru.short_form_present_positive.kanji + assert_equal "みる", @miru.short_form_present_positive.kana + assert_equal "飲む", @nomu.short_form_present_positive.kanji + assert_equal "のむ", @nomu.short_form_present_positive.kana + assert_equal "する", @suru.short_form_present_positive.kanji + assert_equal "する", @suru.short_form_present_positive.kana + assert_equal "勉強する", @benkyousuru.short_form_present_positive.kanji + assert_equal "べんきょうする", @benkyousuru.short_form_present_positive.kana + assert_equal "来る", @kuru.short_form_present_positive.kanji + assert_equal "くる", @kuru.short_form_present_positive.kana + assert_equal "連れて来る", @tsuretekuru.short_form_present_positive.kanji + assert_equal "つれてくる", @tsuretekuru.short_form_present_positive.kana + assert_equal "ある", @aru.short_form_present_positive.kana + end + + def test_short_form_present_negative + assert_equal "見ない", @miru.short_form_present_negative.kanji + assert_equal "みない", @miru.short_form_present_negative.kana + assert_equal "飲まない", @nomu.short_form_present_negative.kanji + assert_equal "のまない", @nomu.short_form_present_negative.kana + assert_equal "しない", @suru.short_form_present_negative.kanji + assert_equal "しない", @suru.short_form_present_negative.kana + assert_equal "勉強しない", @benkyousuru.short_form_present_negative.kanji + assert_equal "べんきょうしない", @benkyousuru.short_form_present_negative.kana + assert_equal "来ない", @kuru.short_form_present_negative.kanji + assert_equal "こない", @kuru.short_form_present_negative.kana + assert_equal "連れて来ない", @tsuretekuru.short_form_present_negative.kanji + assert_equal "つれてこない", @tsuretekuru.short_form_present_negative.kana + assert_equal "ない", @aru.short_form_present_negative.kana + end + + def test_long_form_past_positive + assert_equal "見ました", @miru.long_form_past_positive.kanji + assert_equal "みました", @miru.long_form_past_positive.kana + assert_equal "飲みました", @nomu.long_form_past_positive.kanji + assert_equal "のみました", @nomu.long_form_past_positive.kana + assert_equal "しました", @suru.long_form_past_positive.kanji + assert_equal "しました", @suru.long_form_past_positive.kana + assert_equal "勉強しました", @benkyousuru.long_form_past_positive.kanji + assert_equal "べんきょうしました", @benkyousuru.long_form_past_positive.kana + assert_equal "来ました", @kuru.long_form_past_positive.kanji + assert_equal "きました", @kuru.long_form_past_positive.kana + assert_equal "連れて来ました", @tsuretekuru.long_form_past_positive.kanji + assert_equal "つれてきました", @tsuretekuru.long_form_past_positive.kana + assert_equal "ありました", @aru.long_form_past_positive.kana + end + + def test_long_form_past_negative + assert_equal "見ませんでした", @miru.long_form_past_negative.kanji + assert_equal "みませんでした", @miru.long_form_past_negative.kana + assert_equal "飲みませんでした", @nomu.long_form_past_negative.kanji + assert_equal "のみませんでした", @nomu.long_form_past_negative.kana + assert_equal "しませんでした", @suru.long_form_past_negative.kanji + assert_equal "しませんでした", @suru.long_form_past_negative.kana + assert_equal "勉強しませんでした", @benkyousuru.long_form_past_negative.kanji + assert_equal "べんきょうしませんでした", @benkyousuru.long_form_past_negative.kana + assert_equal "来ませんでした", @kuru.long_form_past_negative.kanji + assert_equal "きませんでした", @kuru.long_form_past_negative.kana + assert_equal "連れて来ませんでした", @tsuretekuru.long_form_past_negative.kanji + assert_equal "つれてきませんでした", @tsuretekuru.long_form_past_negative.kana + assert_equal "ありませんでした", @aru.long_form_past_negative.kana + end + + def test_short_form_past_positive + assert_equal "見た", @miru.short_form_past_positive.kanji + assert_equal "みた", @miru.short_form_past_positive.kana + assert_equal "飲んだ", @nomu.short_form_past_positive.kanji + assert_equal "のんだ", @nomu.short_form_past_positive.kana + assert_equal "した", @suru.short_form_past_positive.kanji + assert_equal "した", @suru.short_form_past_positive.kana + assert_equal "勉強した", @benkyousuru.short_form_past_positive.kanji + assert_equal "べんきょうした", @benkyousuru.short_form_past_positive.kana + assert_equal "来た", @kuru.short_form_past_positive.kanji + assert_equal "きた", @kuru.short_form_past_positive.kana + assert_equal "連れて来た", @tsuretekuru.short_form_past_positive.kanji + assert_equal "つれてきた", @tsuretekuru.short_form_past_positive.kana + assert_equal "あった", @aru.short_form_past_positive.kana + end + + def test_short_form_past_negative + assert_equal "見なかった", @miru.short_form_past_negative.kanji + assert_equal "みなかった", @miru.short_form_past_negative.kana + assert_equal "飲まなかった", @nomu.short_form_past_negative.kanji + assert_equal "のまなかった", @nomu.short_form_past_negative.kana + assert_equal "しなかった", @suru.short_form_past_negative.kanji + assert_equal "しなかった", @suru.short_form_past_negative.kana + assert_equal "勉強しなかった", @benkyousuru.short_form_past_negative.kanji + assert_equal "べんきょうしなかった", @benkyousuru.short_form_past_negative.kana + assert_equal "来なかった", @kuru.short_form_past_negative.kanji + assert_equal "こなかった", @kuru.short_form_past_negative.kana + assert_equal "連れて来なかった", @tsuretekuru.short_form_past_negative.kanji + assert_equal "つれてこなかった", @tsuretekuru.short_form_past_negative.kana + assert_equal "なかった", @aru.short_form_past_negative.kana + end + + def test_desire + assert_equal "見たい", @miru.desire.kanji + assert_equal "みたい", @miru.desire.kana + assert_equal "飲みたい", @nomu.desire.kanji + assert_equal "のみたい", @nomu.desire.kana + assert_equal "したい", @suru.desire.kanji + assert_equal "したい", @suru.desire.kana + assert_equal "勉強したい", @benkyousuru.desire.kanji + assert_equal "べんきょうしたい", @benkyousuru.desire.kana + assert_equal "来たい", @kuru.desire.kanji + assert_equal "きたい", @kuru.desire.kana + assert_equal "連れて来たい", @tsuretekuru.desire.kanji + assert_equal "つれてきたい", @tsuretekuru.desire.kana + assert_equal "ありたい", @aru.desire.kana + end + + def test_potential + assert_equal "見られる", @miru.potential.dictionary.kanji + assert_equal "みられる", @miru.potential.dictionary.kana + assert_equal "飲める", @nomu.potential.dictionary.kanji + assert_equal "のめる", @nomu.potential.dictionary.kana + assert_equal "できる", @suru.potential.dictionary.kanji + assert_equal "できる", @suru.potential.dictionary.kana + assert_equal "勉強できる", @benkyousuru.potential.dictionary.kanji + assert_equal "べんきょうできる", @benkyousuru.potential.dictionary.kana + assert_equal "来られる", @kuru.potential.dictionary.kanji + assert_equal "こられる", @kuru.potential.dictionary.kana + assert_equal "連れて来られる", @tsuretekuru.potential.dictionary.kanji + assert_equal "つれてこられる", @tsuretekuru.potential.dictionary.kana + assert_equal "あれる", @aru.potential.dictionary.kana + end + end +end