From 6804d03c273b9f34ad00bc97684cfe6533850359 Mon Sep 17 00:00:00 2001 From: doncr Date: Sat, 12 Aug 2017 19:04:09 +0100 Subject: [PATCH] Added support for multiple answers and added question pool counter. --- conjugation/drill.html | 7 +- conjugation/drill.js | 189 +++++++++++++++++++++++++++++------------ conjugation/words.js | 82 +++++++++--------- 3 files changed, 176 insertions(+), 102 deletions(-) diff --git a/conjugation/drill.html b/conjugation/drill.html index 792e1ec..1024cdc 100644 --- a/conjugation/drill.html +++ b/conjugation/drill.html @@ -21,6 +21,8 @@ +
Question pool size: Calculating...
+

Conjugation types

@@ -62,14 +64,9 @@
-
- When the test refers to negative て forms, they are assumed to be ~なくて and not ~ないで . -
-
- 終わり
diff --git a/conjugation/drill.js b/conjugation/drill.js index 5918035..66b6a8b 100755 --- a/conjugation/drill.js +++ b/conjugation/drill.js @@ -153,18 +153,51 @@ new function ($) { } }(jQuery); +function commaList(items, conjunction) { + + if (conjunction == undefined) { + conjunction = "and"; + } + + var result = ""; + + for (var i = 0; i < items.length; i++) { + result = result + items[i]; + + if (i < (items.length - 2)) { + result += ", "; + } + + if (i == (items.length - 2)) { + result += " " + conjunction + " "; + } + } + + return result; +} + function resetLog() { log = { "history": [] }; } function getVerbForms(entry) { - function kanaForm(word) { - return word.split(/.\[([^\]]*)\]/).join(""); + function kanaForm(words) { + + if (words.constructor !== Array) { + words = [words]; + } + + return words.map(function (word) { return word.split(/.\[([^\]]*)\]/).join(""); } ); } - function kanjiForm(word) { - return word.split(/(.)\[[^\]]*\]/).join(""); + function kanjiForm(words) { + + if (words.constructor !== Array) { + words = [words]; + } + + return words.map(function (word) { return word.split(/(.)\[[^\]]*\]/).join(""); } ); } var result = { @@ -182,16 +215,23 @@ function getVerbForms(entry) { return result; } -function wordWithFurigana(word) { +function wordWithFurigana(words) { - var bits = word.split(/(.)\[([^\]]*)\]/); - - while (bits.length > 1) { - bits[0] = bits[0] + "" + bits[1] + "" + bits[3]; - bits.splice(1, 3); + if (words.constructor !== Array) { + words = [words]; } - return bits[0]; + return words.map(function (word) { + + var bits = word.split(/(.)\[([^\]]*)\]/); + + while (bits.length > 1) { + bits[0] = bits[0] + "" + bits[1] + "" + bits[3]; + bits.splice(1, 3); + } + + return bits[0]; + }); } function processAnswerKey() { @@ -285,6 +325,29 @@ function processAnswerKey() { } } +function validQuestion(entry, forms, transformation, options) { + + var valid = true; + + transformation.tags.forEach(function (type) { + if (options[type] == false) { + valid = false; + } + }); + + if (options[words[entry].group] == false) { + valid = false; + } + + if (!forms["furigana"][transformation.from]) + valid = false; + + if (!forms["furigana"][transformation.to]) + valid = false; + + return valid; +} + function generateQuestion() { var entry; @@ -309,42 +372,38 @@ function generateQuestion() { forms = getVerbForms(entry); - var valid = true; + var valid = validQuestion(entry, forms, transformation, getOptions()); - transformation.tags.forEach(function (type) { - if ($('#' + type).is(':checked') == false) { + // Modify the chance of trick questions so that they appear on average 25% + // of the time. When trick questions are active then 50% of the + // transformation structure are trick questions and so a 33% filter here + // will achieve the 25% because this test is only performed when a trick + // question has been selected. + + if (transformation.tags.indexOf('trick') != -1) { + if (Math.random() > 0.333) { valid = false; } - }); - - if ($('#' + words[entry].group).is(':checked') == false) { - valid = false; } - if (!forms["furigana"][from_form]) - valid = false; - - if (!forms["furigana"][to_form]) - valid = false; - if (valid) { break; } } - var word = forms["word"]; var kanjiForms = forms["kanji"]; var kanaForms = forms["hiragana"]; var furiganaForms = forms["furigana"]; - var question = "What is the " + transformation.phrase + " form of " + wordWithFurigana(furiganaForms[from_form]) + "?"; + var question = "What is the " + transformation.phrase + " form of " + + wordWithFurigana(furiganaForms[from_form]).randomElement() + "?"; + var answer = kanjiForms[to_form]; var answer2 = kanaForms[to_form]; $('#question').html(question); window.question = question; - window.word = word; window.answer = kanjiForms[to_form]; window.answerWithFurigana = wordWithFurigana(furiganaForms[to_form]); window.answer2 = answer2; @@ -358,10 +417,6 @@ function generateQuestion() { $('#answer').focus(); $('#answer').on('input', processAnswerKey); - - if (log.start == undefined) { - log.start = Date.now(); - } } function processAnswer() { @@ -371,7 +426,8 @@ function processAnswer() { if (response == "") return; - var correct = ((response == window.answer) || (response == window.answer2)); + var correct = ((window.answer.indexOf(response) != -1) || (window.answer2.indexOf(response) != -1)); + var klass = correct ? "correct" : "incorrect"; log.history.push({ @@ -386,20 +442,16 @@ function processAnswer() { $('#response').prop('class', klass).text(response); $('#next').prop('disabled', false); - if ((response == window.answer) || (response == window.answer2)) { + if (correct) { $('#message').html(""); } else { - $('#message').html("
The correct answer is " + window.answerWithFurigana + "
"); + $('#message').html("
The correct answer was " + commaList(window.answerWithFurigana, "or") + "
"); } $('#input').hide(); $('#proceed').show(); $('#proceed button').focus(); - if (log.end == undefined) { - log.end = Date.now(); - } - updateHistoryView(log); } @@ -433,7 +485,7 @@ function updateHistoryView(log) { var td3 = $(''); td1.html(entry.question); - td2.html(entry.answer); + td2.html(commaList(entry.answer, "or")); td3.text(entry.response); tr.append(td1); @@ -451,7 +503,6 @@ function updateHistoryView(log) { $('#history').empty().append(review); $('#history').append("

" + correct + " of " + total + " correct.

"); - $('#history').append("

" + ((log.end - log.start) / 1000.0) + " seconds.

"); } function proceed() { @@ -487,14 +538,6 @@ function endQuiz() { $('#backToStart').focus(); } -function updateTeNotice() { - if ($('#te-form').is(':checked')) { - $('#te-notice').show(); - } else { - $('#te-notice').hide(); - } -} - function arrayDifference(a, b) { // From http://stackoverflow.com/a/1723220 return a.filter(function (x) { return b.indexOf(x) < 0 }); @@ -585,17 +628,49 @@ function calculateTransitions() { phrase: transformation.phrase, tags: transformation.tags.concat(["trick"]) }); - - // Cheap trick to make trick questions appear on average 25% of the time - // instead of 50%. I'll fix this later *cough*. - - trick_forms.push(transformation); - trick_forms.push(transformation); }); transformations = transformations.concat(trick_forms); } +function updateOptionSummary() { + + // Calculate how many questions will apply + + var options = getOptions(); + var applicable = 0; + + Object.keys(words).forEach(function (word) { + + var forms = getVerbForms(word); + + transformations.forEach(function (transformation) { + + if (validQuestion(word, forms, transformation, options)) { + applicable++; + } + }); + }); + + $("#questionCount").text(applicable); +} + +function getOptions() { + + var options = ["plain", "polite", "negative", "past", "te-form", + "progressive", "potential", "imperative", "passive", "causative", + "godan", "ichidan", "iku", "kuru", "suru", "i-adjective", "na-adjective", + "trick"]; + + var result = {}; + + options.forEach(function (option) { + result[option] = $('#' + option).is(':checked') != false; + }); + + return result; +} + $('window').ready(function () { calculateTransitions(); @@ -603,8 +678,10 @@ $('window').ready(function () { $('#go').click(startQuiz); $('#backToStart').click(showSplash); - $('#te-form').click(updateTeNotice); - updateTeNotice(); + $('div.options input').click(updateOptionSummary); + $('input#trick').click(updateOptionSummary); + + updateOptionSummary(); showSplash(); }); diff --git a/conjugation/words.js b/conjugation/words.js index 16877f9..8788f4f 100644 --- a/conjugation/words.js +++ b/conjugation/words.js @@ -17,7 +17,7 @@ var words = { "polite past": "走[はし]りました", "polite past negative": "走[はし]りませんでした", "te-form": "走[はし]って", - "te-form negative": "走[はし]らなくて", + "te-form negative": ["走[はし]らなくて", "走[はし]らないで"], "potential": "走[はし]れる", "potential negative": "走[はし]れない", "passive": "走[はし]られる", @@ -54,7 +54,7 @@ var words = { "polite past": "死[し]にました", "polite past negative": "死[し]にませんでした", "te-form": "死[し]んで", - "te-form negative": "死[し]ななくて", + "te-form negative": ["死[し]ななくて", "死[し]なないで"], "potential": "死[し]ねる", "potential negative": "死[し]ねない", "passive": "死[し]なれる", @@ -91,7 +91,7 @@ var words = { "polite past": "上[あ]げました", "polite past negative": "上[あ]げませんでした", "te-form": "上[あ]げて", - "te-form negative": "上[あ]げなくて", + "te-form negative": ["上[あ]げなくて", "上[あ]げないで"], "potential": "上[あ]げられる", "potential negative": "上[あ]げられない", "passive": "上[あ]げられる", @@ -128,7 +128,7 @@ var words = { "polite past": "上[のぼ]りました", "polite past negative": "上[のぼ]りませんでした", "te-form": "上[のぼ]って", - "te-form negative": "上[のぼ]らなくて", + "te-form negative": ["上[のぼ]らなくて", "上[のぼ]らないで"], "potential": "上[のぼ]れる", "potential negative": "上[のぼ]れない", "passive": "上[のぼ]られる", @@ -165,7 +165,7 @@ var words = { "polite past": "聞[き]きました", "polite past negative": "聞[き]きませんでした", "te-form": "聞[き]いて", - "te-form negative": "聞[き]かなくて", + "te-form negative": ["聞[き]かなくて", "聞[き]かないで"], "potential": "聞[き]ける", "potential negative": "聞[き]けない", "passive": "聞[き]かれる", @@ -202,7 +202,7 @@ var words = { "polite past": "書[か]きました", "polite past negative": "書[か]きませんでした", "te-form": "書[か]いて", - "te-form negative": "書[か]かなくて", + "te-form negative": ["書[か]かなくて", "書[か]かないで"], "potential": "書[か]ける", "potential negative": "書[か]けない", "passive": "書[か]かれる", @@ -239,7 +239,7 @@ var words = { "polite past": "消[け]しました", "polite past negative": "消[け]しませんでした", "te-form": "消[け]して", - "te-form negative": "消[け]さなくて", + "te-form negative": ["消[け]さなくて", "消[け]さないで"], "potential": "消[け]せる", "potential negative": "消[け]せない", "passive": "消[け]される", @@ -276,7 +276,7 @@ var words = { "polite past": "着[き]ました", "polite past negative": "着[き]ませんでした", "te-form": "着[き]て", - "te-form negative": "着[き]なくて", + "te-form negative": ["着[き]なくて", "着[き]ないで"], "potential": "着[き]られる", "potential negative": "着[き]られない", "passive": "着[き]られる", @@ -313,7 +313,7 @@ var words = { "polite past": "育[そだ]てました", "polite past negative": "育[そだ]てませんでした", "te-form": "育[そだ]てて", - "te-form negative": "育[そだ]てなくて", + "te-form negative": ["育[そだ]てなくて", "育[そだ]てないで"], "potential": "育[そだ]てられる", "potential negative": "育[そだ]てられない", "passive": "育[そだ]てられる", @@ -350,7 +350,7 @@ var words = { "polite past": "遊[あそ]びました", "polite past negative": "遊[あそ]びませんでした", "te-form": "遊[あそ]んで", - "te-form negative": "遊[あそ]ばなくて", + "te-form negative": ["遊[あそ]ばなくて", "遊[あそ]ばないで"], "potential": "遊[あそ]べる", "potential negative": "遊[あそ]べない", "passive": "遊[あそ]ばれる", @@ -387,7 +387,7 @@ var words = { "polite past": "褒[ほ]めました", "polite past negative": "褒[ほ]めませんでした", "te-form": "褒[ほ]めて", - "te-form negative": "褒[ほ]めなくて", + "te-form negative": ["褒[ほ]めなくて", "褒[ほ]めないで"], "potential": "褒[ほ]められる", "potential negative": "褒[ほ]められない", "passive": "褒[ほ]められる", @@ -424,7 +424,7 @@ var words = { "polite past": "学[まな]びました", "polite past negative": "学[まな]びませんでした", "te-form": "学[まな]んで", - "te-form negative": "学[まな]ばなくて", + "te-form negative": ["学[まな]ばなくて", "学[まな]ばないで"], "potential": "学[まな]べる", "potential negative": "学[まな]べない", "passive": "学[まな]ばれる", @@ -461,7 +461,7 @@ var words = { "polite past": "喜[よころ]びました", "polite past negative": "喜[よころ]びませんでした", "te-form": "喜[よころ]んで", - "te-form negative": "喜[よころ]ばなくて", + "te-form negative": ["喜[よころ]ばなくて", "喜[よころ]ばないで"], "potential": "喜[よころ]べる", "potential negative": "喜[よころ]べない", "passive": "喜[よころ]ばれる", @@ -498,7 +498,7 @@ var words = { "polite past": "泳[およ]ぎました", "polite past negative": "泳[およ]ぎませんでした", "te-form": "泳[およ]いで", - "te-form negative": "泳[およ]がなくて", + "te-form negative": ["泳[およ]がなくて", "泳[およ]がないで"], "potential": "泳[およ]げる", "potential negative": "泳[およ]げない", "passive": "泳[およ]がれる", @@ -535,7 +535,7 @@ var words = { "polite past": "注[そそ]ぎました", "polite past negative": "注[そそ]ぎませんでした", "te-form": "注[そそ]いで", - "te-form negative": "注[そそ]がなくて", + "te-form negative": ["注[そそ]がなくて", "注[そそ]がないで"], "potential": "注[そそ]げる", "potential negative": "注[そそ]げない", "passive": "注[そそ]がれる", @@ -572,7 +572,7 @@ var words = { "polite past": "急[いそ]ぎました", "polite past negative": "急[いそ]ぎませんでした", "te-form": "急[いそ]いで", - "te-form negative": "急[いそ]がなくて", + "te-form negative": ["急[いそ]がなくて", "急[いそ]がないで"], "potential": "急[いそ]げる", "potential negative": "急[いそ]げない", "passive": "急[いそ]がれる", @@ -609,7 +609,7 @@ var words = { "polite past": "立[た]ちました", "polite past negative": "立[た]ちませんでした", "te-form": "立[た]って", - "te-form negative": "立[た]たなくて", + "te-form negative": ["立[た]たなくて", "立[た]たないで"], "potential": "立[た]てる", "potential negative": "立[た]てない", "passive": "立[た]たれる", @@ -646,7 +646,7 @@ var words = { "polite past": "打[う]ちました", "polite past negative": "打[う]ちませんでした", "te-form": "打[う]って", - "te-form negative": "打[う]たなくて", + "te-form negative": ["打[う]たなくて", "打[う]たないで"], "potential": "打[う]てる", "potential negative": "打[う]てない", "passive": "打[う]たれる", @@ -683,7 +683,7 @@ var words = { "polite past": "待[ま]ちました", "polite past negative": "待[ま]ちませんでした", "te-form": "待[ま]って", - "te-form negative": "待[ま]たなくて", + "te-form negative": ["待[ま]たなくて", "待[ま]たないで"], "potential": "待[ま]てる", "potential negative": "待[ま]てない", "passive": "待[ま]たれる", @@ -720,7 +720,7 @@ var words = { "polite past": "持[も]ちました", "polite past negative": "持[も]ちませんでした", "te-form": "持[も]って", - "te-form negative": "持[も]たなくて", + "te-form negative": ["持[も]たなくて", "持[も]たないで"], "potential": "持[も]てる", "potential negative": "持[も]てない", "passive": "持[も]たれる", @@ -757,7 +757,7 @@ var words = { "polite past": "行[い]きました", "polite past negative": "行[い]きませんでした", "te-form": "行[い]って", - "te-form negative": "行[い]かなくて", + "te-form negative": ["行[い]かなくて", "行[い]かないで"], "potential": "行[い]ける", "potential negative": "行[い]けない", "imperative": "行[い]け", @@ -794,7 +794,7 @@ var words = { "polite past": "飲[の]みました", "polite past negative": "飲[の]みませんでした", "te-form": "飲[の]んで", - "te-form negative": "飲[の]まなくて", + "te-form negative": ["飲[の]まなくて", "飲[の]まないで"], "potential": "飲[の]める", "potential negative": "飲[の]めない", "imperative": "飲[の]め", @@ -831,7 +831,7 @@ var words = { "polite past": "作[つく]りました", "polite past negative": "作[つく]りませんでした", "te-form": "作[つく]って", - "te-form negative": "作[つく]らなくて", + "te-form negative": ["作[つく]らなくて", "作[つく]らないで"], "potential": "作[つく]れる", "potential negative": "作[つく]れない", "imperative": "作[つく]れ", @@ -868,7 +868,7 @@ var words = { "polite past": "買[か]い戻[もど]しました", "polite past negative": "買[か]い戻[もど]しませんでした", "te-form": "買[か]い戻[もど]して", - "te-form negative": "買[か]い戻[もど]さなくて", + "te-form negative": ["買[か]い戻[もど]さなくて", "買[か]い戻[もど]さないで"], "potential": "買[か]い戻[もど]せる", "potential negative": "買[か]い戻[もど]せない", "imperative": "買[か]い戻[もど]せ", @@ -905,7 +905,7 @@ var words = { "polite past": "見[み]ました", "polite past negative": "見[み]ませんでした", "te-form": "見[み]て", - "te-form negative": "見[み]なくて", + "te-form negative": ["見[み]なくて", "見[み]ないで"], "potential": "見[み]られる", "potential negative": "見[み]られない", "imperative": "見[み]ろ", @@ -942,7 +942,7 @@ var words = { "polite past": "食[た]べました", "polite past negative": "食[た]べませんでした", "te-form": "食[た]べて", - "te-form negative": "食[た]べなくて", + "te-form negative": ["食[た]べなくて", "食[た]べないで"], "potential": "食[た]べられる", "potential negative": "食[た]べられない", "imperative": "食[た]べろ", @@ -979,7 +979,7 @@ var words = { "polite past": "起[お]きました", "polite past negative": "起[お]きませんでした", "te-form": "起[お]きて", - "te-form negative": "起[お]きなくて", + "te-form negative": ["起[お]きなくて", "起[お]きないで"], "potential": "起[お]きられる", "potential negative": "起[お]きられない", "imperative": "起[お]きろ", @@ -1016,7 +1016,7 @@ var words = { "polite past": "買[か]い換[か]えました", "polite past negative": "買[か]い換[か]えませんでした", "te-form": "買[か]い換[か]えて", - "te-form negative": "買[か]い換[か]えなくて", + "te-form negative": ["買[か]い換[か]えなくて", "買[か]い換[か]えないで"], "potential": "買[か]い換[か]えられる", "potential negative": "買[か]い換[か]えられない", "imperative": "買[か]い換[か]えろ", @@ -1053,7 +1053,7 @@ var words = { "polite past": "来[き]ました", "polite past negative": "来[き]ませんでした", "te-form": "来[き]て", - "te-form negative": "来[こ]なくて", + "te-form negative": ["来[こ]なくて", "来[こ]ないで"], "potential": "来[こ]られる", "potential negative": "来[こ]られない", "imperative": "来[こ]い", @@ -1090,7 +1090,7 @@ var words = { "polite past": "しました", "polite past negative": "しませんでした", "te-form": "して", - "te-form negative": "しなくて", + "te-form negative": ["しなくて", "しないで"], "imperative": "しろ", "imperative negative": "さるな", "progressive": "している", @@ -1119,7 +1119,7 @@ var words = { "polite past": "勉[べん]強[きょう]しました", "polite past negative": "勉[べん]強[きょう]しませんでした", "te-form": "勉[べん]強[きょう]して", - "te-form negative": "勉[べん]強[きょう]しなくて", + "te-form negative": ["勉[べん]強[きょう]しなくて", "勉[べん]強[きょう]しないで"], "imperative": "勉[べん]強[きょう]しろ", "imperative negative": "勉[べん]強[きょう]さるな", "progressive": "勉[べん]強[きょう]している", @@ -1148,7 +1148,7 @@ var words = { "polite past": "電[でん]話[わ]しました", "polite past negative": "電[でん]話[わ]しませんでした", "te-form": "電[でん]話[わ]して", - "te-form negative": "電[でん]話[わ]しなくて", + "te-form negative": ["電[でん]話[わ]しなくて", "電[でん]話[わ]しないで"], "imperative": "電[でん]話[わ]しろ", "imperative negative": "電[でん]話[わ]さるな", "progressive": "電[でん]話[わ]している", @@ -1177,7 +1177,7 @@ var words = { "polite past": "開[かい]発[はつ]しました", "polite past negative": "開[かい]発[はつ]しませんでした", "te-form": "開[かい]発[はつ]して", - "te-form negative": "開[かい]発[はつ]しなくて", + "te-form negative": ["開[かい]発[はつ]しなくて", "開[かい]発[はつ]しないで"], "imperative": "開[かい]発[はつ]しろ", "imperative negative": "開[かい]発[はつ]さるな", "progressive": "開[かい]発[はつ]している", @@ -1206,7 +1206,7 @@ var words = { "polite past": "計[けい]算[さん]しました", "polite past negative": "計[けい]算[さん]しませんでした", "te-form": "計[けい]算[さん]して", - "te-form negative": "計[けい]算[さん]しなくて", + "te-form negative": ["計[けい]算[さん]しなくて", "計[けい]算[さん]しないで"], "imperative": "計[けい]算[さん]しろ", "imperative negative": "計[けい]算[さん]さるな", "progressive": "計[けい]算[さん]している", @@ -1235,7 +1235,7 @@ var words = { "polite past": "読[よ]みました", "polite past negative": "読[よ]みませんでした", "te-form": "読[よ]んで", - "te-form negative": "読[よ]まなくて", + "te-form negative": ["読[よ]まなくて", "読[よ]まないで"], "potential": "読[よ]める", "potential negative": "読[よ]めない", "imperative": "読[よ]め", @@ -1272,7 +1272,7 @@ var words = { "polite past": "思[おも]いました", "polite past negative": "思[おも]いませんでした", "te-form": "思[おも]って", - "te-form negative": "思[おも]わなくて", + "te-form negative": ["思[おも]わなくて", "思[おも]わないで"], "potential": "思[おも]える", "potential negative": "思[おも]えない", "imperative": "思[おも]え", @@ -1309,7 +1309,7 @@ var words = { "polite past": "買[か]い与[あた]えました", "polite past negative": "買[か]い与[あた]えませんでした", "te-form": "買[か]い与[あた]えて", - "te-form negative": "買[か]い与[あた]えなくて", + "te-form negative": ["買[か]い与[あた]えなくて", "買[か]い与[あた]えないで"], "potential": "買[か]い与[あた]えられる", "potential negative": "買[か]い与[あた]えられない", "imperative": "買[か]い与[あた]えろ", @@ -1346,7 +1346,7 @@ var words = { "polite past": "座[すわ]りました", "polite past negative": "座[すわ]りませんでした", "te-form": "座[すわ]って", - "te-form negative": "座[すわ]らなくて", + "te-form negative": ["座[すわ]らなくて", "座[すわ]らないで"], "potential": "座[すわ]れる", "potential negative": "座[すわ]れない", "imperative": "座[すわ]れ", @@ -1383,7 +1383,7 @@ var words = { "polite past": "休[やす]みました", "polite past negative": "休[やす]みませんでした", "te-form": "休[やす]んで", - "te-form negative": "休[やす]まなくて", + "te-form negative": ["休[やす]まなくて", "休[やす]まないで"], "potential": "休[やす]める", "potential negative": "休[やす]めない", "imperative": "休[やす]め", @@ -1420,7 +1420,7 @@ var words = { "polite past": "足[た]しました", "polite past negative": "足[た]しませんでした", "te-form": "足[た]して", - "te-form negative": "足[た]さなくて", + "te-form negative": ["足[た]さなくて", "足[た]さないで"], "potential": "足[た]せる", "potential negative": "足[た]せない", "imperative": "足[た]せ", @@ -1457,7 +1457,7 @@ var words = { "polite past": "歌[うた]いました", "polite past negative": "歌[うた]いませんでした", "te-form": "歌[うた]って", - "te-form negative": "歌[うた]わなくて", + "te-form negative": ["歌[うた]わなくて", "歌[うた]わないで"], "potential": "歌[うた]える", "potential negative": "歌[うた]えない", "imperative": "歌[うた]え",