Commit ed1de39d authored by Thomas Dennis's avatar Thomas Dennis

Allow tenses other than past/present for verbs.

Also update the CSS a bit and output a score when the results are shown.
parent 94da24ec
...@@ -2,38 +2,39 @@ ...@@ -2,38 +2,39 @@
var ADJECTIVE_I = { var ADJECTIVE_I = {
about: "~i adjective", about: "~i adjective",
tense_list: ["present", "past"],
word_list: word_list:
[ [
{ "romaji": "takai", "kanji": "高い", "description": "high/expensive" } { "romaji": "takai", "kanji": "高い", "description": "high/expensive" }
], ],
conjugate: function(word, kwargs) conjugate: function(word, tense, affirmative, formal)
{ {
if (kwargs.formal) if (formal)
{ {
if (kwargs.negative) if (!affirmative)
{ {
// TODO: Also allow "~ku nai desu" and "~ku nakatta desu" here. // TODO: Also allow "~ku nai desu" and "~ku nakatta desu" here.
if (kwargs.past_tense) { return word.slice(0, -1) + "ku arimasen deshita"; } if (tense == "past") { return word.slice(0, -1) + "ku arimasen deshita"; }
else { return word.slice(0, -1) + "ku arimasen"; } else { return word.slice(0, -1) + "ku arimasen"; }
} }
else else
{ {
if (kwargs.past_tense) { return word.slice(0, -1) + "katta desu"; } if (tense == "past") { return word.slice(0, -1) + "katta desu"; }
else { return word + " desu"; } else { return word + " desu"; }
} }
} }
else else
{ {
if (kwargs.negative) if (!affirmative)
{ {
if (kwargs.past_tense) { return word.slice(0, -1) + "ku nakatta"; } if (tense == "past") { return word.slice(0, -1) + "ku nakatta"; }
else { return word.slice(0, -1) + "ku nai"; } else { return word.slice(0, -1) + "ku nai"; }
} }
else else
{ {
if (kwargs.past_tense) { return word.slice(0, -1) + "katta"; } if (tense == "past") { return word.slice(0, -1) + "katta"; }
else { return word; } else { return word; }
} }
} }
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
var ADJECTIVE_NA = { var ADJECTIVE_NA = {
about: "~na adjective", about: "~na adjective",
tense_list: ["present", "past"],
word_list: word_list:
[ [
...@@ -25,32 +26,32 @@ var ADJECTIVE_NA = { ...@@ -25,32 +26,32 @@ var ADJECTIVE_NA = {
{ "romaji": "hadena", "kanji": "派手な", "description": "showy" } { "romaji": "hadena", "kanji": "派手な", "description": "showy" }
], ],
conjugate: function(word, kwargs) conjugate: function(word, tense, affirmative, formal)
{ {
word = word.slice(0, -2); // Remove the "na" from the end. word = word.slice(0, -2); // Remove the "na" from the end.
if (kwargs.formal) if (formal)
{ {
if (kwargs.negative) if (!affirmative)
{ {
if (kwargs.past_tense) { return word + " dewa arimasen deshita"; } if (tense == "past") { return word + " dewa arimasen deshita"; }
else { return word + " dewa arimasen"; } else { return word + " dewa arimasen"; }
} }
else else
{ {
if (kwargs.past_tense) { return word + " deshita"; } if (tense == "past") { return word + " deshita"; }
else { return word + " desu"; } else { return word + " desu"; }
} }
} }
else else
{ {
if (kwargs.negative) if (!affirmative)
{ {
if (kwargs.past_tense) { return word + " dewa nakatta"; } if (tense == "past") { return word + " dewa nakatta"; }
else { return word + " dewa nai"; } else { return word + " dewa nai"; }
} }
else else
{ {
if (kwargs.past_tense) { return word + " datta"; } if (tense == "past") { return word + " datta"; }
else { return word + " da"; } else { return word + " da"; }
} }
} }
......
...@@ -13,8 +13,9 @@ ...@@ -13,8 +13,9 @@
<body onload="setup()"> <body onload="setup()">
<h1>Japanese Conjugations Quiz</h1> <h1>Japanese Conjugations Quiz</h1>
<p> <p>
Based on <a href="http://japanese.about.com/library/weekly/aa031101b.htm">this</a> Based on <a href="http://japanese.about.com/library/weekly/aa031101b.htm">this</a>,
and <a href="http://japanese.about.com/library/weekly/aa040101b.htm">this</a>. <a href="http://japanese.about.com/library/weekly/aa040101b.htm">this</a>, and
<a href="http://www.csse.monash.edu.au/~jwb/cgi-bin/wwwjdic.cgi">this</a>.
</p> </p>
<hr> <hr>
<div id="quizarea"> <div id="quizarea">
...@@ -24,6 +25,7 @@ ...@@ -24,6 +25,7 @@
<p> <p>
<a class="jslink" href="#" onclick="check()"><b>Check Results</b></a> <a class="jslink" href="#" onclick="check()"><b>Check Results</b></a>
<a class="jslink" href="#" onclick="reset()">Reset</a> <a class="jslink" href="#" onclick="reset()">Reset</a>
<span id="score"></span>
</p> </p>
<hr> <hr>
<small> <small>
......
...@@ -12,10 +12,8 @@ var QUESTION = [ ...@@ -12,10 +12,8 @@ var QUESTION = [
function setup() function setup()
{ {
var LABEL = ["present", "present_negative", "past", "past_negative"];
var parent = document.getElementById("quizarea");
// Generate some HTML elements for each question. // Generate some HTML elements for each question.
var parent = document.getElementById("quizarea");
for (var n = 0; n < QUESTION.length; ++n) for (var n = 0; n < QUESTION.length; ++n)
{ {
...@@ -26,34 +24,42 @@ function setup() ...@@ -26,34 +24,42 @@ function setup()
// This is the question title, such as "~u verbs". // This is the question title, such as "~u verbs".
var title = root.appendChild(document.createElement('h2')); var title = root.appendChild(document.createElement('h2'));
title.id = QUESTION[n].html_id + "_title"; title.id = QUESTION[n].html_id + "_title";
// This is the actual question text. It changes when a new word is chosen. // This is the actual question text. It changes when a new word is chosen.
var caption = root.appendChild(document.createElement('p')); var caption = root.appendChild(document.createElement('p'));
caption.id = QUESTION[n].html_id + "_caption"; caption.id = QUESTION[n].html_id + "_caption";
// This is the actual "answer grid" where text can be entered. // This is the actual "answer grid" where text can be entered.
var table = root.appendChild(document.createElement('table')); var table = root.appendChild(document.createElement('table'));
for (var y = 0; y < 5; ++y) for (var y = 0; y < (QUESTION[n].dictionary.tense_list.length * 2) + 1; ++y)
{ {
var row = table.appendChild(document.createElement('tr')); var row = table.appendChild(document.createElement('tr'));
for (var x = 0; x < 3; ++x) for (var x = 0; x < 3; ++x)
{ {
var td = row.appendChild(document.createElement(x && y ? "td" : "th")); var td = row.appendChild(document.createElement(x && y ? "td" : "th"));
if (y == 0) if (y > 0)
{
// This is the top row of the table.
td.appendChild(document.createTextNode(["*", "Informal", "Formal"][x]));
}
else if (x == 0)
{ {
// This is the left-hand column.
td.appendChild(document.createTextNode(LABEL[y-1].replace(/_/, " "))); var label = QUESTION[n].dictionary.tense_list[Math.floor((y-1)/2)];
if (y % 2 == 0) { label += "_negative"; }
if (x > 0)
{
// Any other cells are for answers.
var input = td.appendChild(document.createElement("input"));
input.id = QUESTION[n].html_id + "_" + label + (x < 2 ? "" : "_formal");
}
else
{
// This is the left-hand column.
td.appendChild(document.createTextNode(label.replace(/_/g, " ")));
}
} }
else else
{ {
// Any other cells are for answers. // This is the top row of the table.
var input = td.appendChild(document.createElement("input")); td.appendChild(document.createTextNode(["*", "Informal", "Formal"][x]));
input.id = QUESTION[n].html_id + "_" + LABEL[y-1] + (x < 2 ? "" : "_formal");
} }
} }
} }
...@@ -73,6 +79,9 @@ function setup() ...@@ -73,6 +79,9 @@ function setup()
function reset() function reset()
{ {
// Reset the score.
document.getElementById("score").innerHTML = "";
// Reset the answer boxes so that they're all blank again. // Reset the answer boxes so that they're all blank again.
var input = document.getElementsByTagName("input"); var input = document.getElementsByTagName("input");
for (var i = 0; i < input.length; ++i) for (var i = 0; i < input.length; ++i)
...@@ -95,8 +104,8 @@ function reset() ...@@ -95,8 +104,8 @@ function reset()
// Replace the question title. // Replace the question title.
var title = QUESTION[n].dictionary.about + ": " + the_word.kanji; var title = QUESTION[n].dictionary.about + ": " + the_word.kanji;
document.getElementById(QUESTION[n].html_id + "_title").innerHTML = title; document.getElementById(QUESTION[n].html_id + "_title").innerHTML = title;
// Replace the question text. // Replace the question text.
var text = "Conjugate <b>" + QUESTION[n]["current_word"] + '</b> ("'; var text = "Conjugate <b>" + QUESTION[n]["current_word"] + '</b> ("';
text += the_word.description + '") in the grid below.'; text += the_word.description + '") in the grid below.';
...@@ -110,45 +119,54 @@ function reset() ...@@ -110,45 +119,54 @@ function reset()
function check() function check()
{ {
// This maps the HTML element IDs to the correct validation flags. var flags = [
var flag_set = { ["", true, false],
"_present": { "past_tense": false, "negative" : false, "formal": false }, ["_formal", true, true],
"_present_negative": { "past_tense": false, "negative" : true, "formal": false }, ["_negative", false, false],
"_past": { "past_tense": true, "negative" : false, "formal": false }, ["_negative_formal", false, true]
"_past_negative": { "past_tense": true, "negative" : true, "formal": false }, ];
"_present_formal": { "past_tense": false, "negative" : false, "formal": true },
"_present_negative_formal": { "past_tense": false, "negative" : true, "formal": true },
"_past_formal": { "past_tense": true, "negative" : false, "formal": true },
"_past_negative_formal": { "past_tense": true, "negative" : true, "formal": true }
}
// Loop through all answers for each question and validate each one. // Loop through all answers for each question and validate each one.
var score = 0;
var total = 0;
for (var n = 0; n < QUESTION.length; ++n) for (var n = 0; n < QUESTION.length; ++n)
{ {
var errors = []; var errors = [];
for (var a in flag_set) // Loop through each tense, such as "present", "past", etc.
for (var t = 0; t < QUESTION[n].dictionary.tense_list.length; ++t)
{ {
var elem = document.getElementById(QUESTION[n].html_id + a); for (var v = 0; v < flags.length; ++v)
var word = QUESTION[n]["current_word"];
var expected = QUESTION[n].dictionary.conjugate(word, flag_set[a]);
if (elem.value.toLowerCase().replace(/ /g, "") != expected.toLowerCase().replace(/ /g, ""))
{ {
elem.className = "wrong_answer"; var word = QUESTION[n]["current_word"];
var tense = QUESTION[n].dictionary.tense_list[t];
var expected = QUESTION[n].dictionary.conjugate(word, tense, flags[v][1], flags[v][2]);
var elem = document.getElementById(QUESTION[n].html_id + "_" + tense + flags[v][0]);
if (elem.value.toLowerCase().replace(/ /g, "") != expected.toLowerCase().replace(/ /g, ""))
{
elem.className = "wrong_answer";
var message = "The <b>" + (flags[v][2] ? "formal, " : "informal, ");
if (!flags[v][1]) { message += "negative-"; }
message += tense + "</b> conjugation should be <b>" + expected + "</b>."
errors.push(message)
// Explain WHY the answer was considered to be incorrect. }
var message = "The " else
message += flag_set[a].formal ? "formal, " : "informal, "; {
if (flag_set[a].negative) { message += "negative-"; } elem.className = "right_answer";
message += flag_set[a].past_tense ? "past-tense" : "present-tense"; ++score;
message += " conjugation of " + word + " is <b>" + expected + "</b>." }
errors.push(message)
} else { elem.className = "right_answer"; } ++total;
}
} }
...@@ -163,4 +181,7 @@ function check() ...@@ -163,4 +181,7 @@ function check()
} }
// Show the score.
document.getElementById("score").innerHTML = "Score: " + String(score) + "/" + String(total);
} }
body { background: #EEF; font-family: sans; font-size:small; } body { background: #EEF; font-family: sans; font-size:small; }
h1 { margin: 0; text-align: center; } h1 { margin: 0; text-align: center; color:#800; }
h2 { color:#800; }
table table
{ {
...@@ -23,3 +24,11 @@ table ...@@ -23,3 +24,11 @@ table
.blank_answer { background: #FFF; color: #000; } .blank_answer { background: #FFF; color: #000; }
.right_answer { background: #AFA; color: #000; } .right_answer { background: #AFA; color: #000; }
.wrong_answer { background: #FAA; color: #000; } .wrong_answer { background: #FAA; color: #000; }
#score
{
padding: 8px;
color: #008;
font-size: large;
font-weight: bold;
}
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
var VERB_ERU = { var VERB_ERU = {
about: "Group 2 (Ichidan) ~iru/eru verb", about: "Group 2 (Ichidan) ~iru/eru verb",
tense_list: ["present", "past", "potential"],
word_list: word_list:
[ [
...@@ -17,33 +18,50 @@ var VERB_ERU = { ...@@ -17,33 +18,50 @@ var VERB_ERU = {
{ "romaji": "taberu", "kanji": "食べる", "description": "to eat" } { "romaji": "taberu", "kanji": "食べる", "description": "to eat" }
], ],
conjugate: function(word, kwargs) conjugate: function(word, tense, affirmative, formal)
{ {
if (kwargs.formal) switch (tense)
{ {
if (kwargs.negative)
{ case "present":
if (kwargs.past_tense) { return word.slice(0, -2) + "masen deshita"; } if (formal)
else { return word.slice(0, -2) + "masen"; } {
} if (affirmative) { return word.slice(0, -2) + "masu"; }
else else { return word.slice(0, -2) + "masen"; }
{ }
if (kwargs.past_tense) { return word.slice(0, -2) + "mashita"; } else
else { return word.slice(0, -2) + "masu"; } {
} if (affirmative) { return word; }
} else { return word.slice(0, -2) + "nai"; }
else }
{ break;
if (kwargs.negative)
{ case "past":
if (kwargs.past_tense) { return word.slice(0, -2) + "nakatta"; } if (formal)
else { return word.slice(0, -2) + "nai"; } {
} if (affirmative) { return word.slice(0, -2) + "mashita"; }
else else { return word.slice(0, -2) + "masen deshita"; }
{ }
if (kwargs.past_tense) { return word.slice(0, -2) + "ta"; } else
else { return word; } {
} if (affirmative) { return word.slice(0, -2) + "ta"; }
else { return word.slice(0, -2) + "nakatta"; }
}
break;
case "potential":
if (formal)
{
if (affirmative) { return word.slice(0, -2) + "raremasu"; }
else { return word.slice(0, -2) + "raremasen"; }
}
else
{
if (affirmative) { return word.slice(0, -2) + "rareru"; }
else { return word.slice(0, -2) + "rarenai"; }
}
break;
} }
} }
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
var VERB_U = { var VERB_U = {
about: "Group 1 (Godan) ~u verb", about: "Group 1 (Godan) ~u verb",
tense_list: ["present", "past", "potential"],
word_list: word_list:
[ [
...@@ -21,50 +22,71 @@ var VERB_U = { ...@@ -21,50 +22,71 @@ var VERB_U = {
{ "romaji": "yomu", "kanji": "読む", "description": "to read" } { "romaji": "yomu", "kanji": "読む", "description": "to read" }
], ],
conjugate: function(word, kwargs) conjugate: function(word, tense, affirmative, formal)
{ {
if (kwargs.formal)
{ // As a special case, words ending with "[vowel]u" should use WA not A.
if (kwargs.negative) var negative_stem = word.slice(0, -1);
{ if (negative_stem.slice(-1).match(/[AEIOUaeiou]/)) { negative_stem += "w"; }
if (kwargs.past_tense) { return word.slice(0, -1) + "imasen deshita"; }
else { return word.slice(0, -1) + "imasen"; } switch (tense)
}
else
{
if (kwargs.past_tense) { return word.slice(0, -1) + "imashita"; }
else { return word.slice(0, -1) + "imasu"; }
}
}
else
{ {
if (kwargs.negative)
{
// As a special case, words ending with "[vowel]u" should use WA not A.
var verb_stem = word.slice(0, -1);
if (verb_stem.slice(-1).match(/[AEIOUaeiou]/)) { verb_stem += "w"; }
return verb_stem + (kwargs.past_tense ? "anakatta" : "anai");
}
else if (kwargs.past_tense)
{
// Handle "tsu" first - "su" is handled below. case "present":
if (word.slice(-3) == "tsu") { return word.slice(0, -3) + "tta"; } if (formal)
{
if (affirmative) { return word.slice(0, -1) + "imasu"; }
else { return word.slice(0, -1) + "imasen"; }
}
else
{
if (affirmative) { return word; }
else { return negative_stem + "anai"; }
}
break;
// Handle all possible two-character endings. case "past":
switch (word.slice(-2)) if (formal)
{
if (affirmative) { return word.slice(0, -1) + "imashita"; }
else { return word.slice(0, -1) + "imasen deshita"; }
}
else if (affirmative)
{ {
case "ku": return word.slice(0, -2) + "ita";
case "gu": return word.slice(0, -2) + "ida"; // Handle "tsu" first - "su" is handled below.
case "ru": return word.slice(0, -2) + "tta"; if (word.slice(-3) == "tsu") { return word.slice(0, -3) + "tta"; }
case "su": return word.slice(0, -2) + "shita";
case "nu": case "bu": case "mu": return word.slice(0, -2) + "nda"; // Handle all possible two-character endings.
switch (word.slice(-2))
{
case "ku": return word.slice(0, -2) + "ita";
case "gu": return word.slice(0, -2) + "ida";
case "ru": return word.slice(0, -2) + "tta";
case "su": return word.slice(0, -2) + "shita";
case "nu": case "bu": case "mu": return word.slice(0, -2) + "nda";
}
// If all else, fails, assume it ends with "u".
return word.slice(0, -1) + "tta";
} }
else { return negative_stem + "anakatta"; }
break;
// If all else, fails, assume it ends with "u". case "potential":
return word.slice(0, -1) + "tta"; if (formal)
{
if (affirmative) { return word.slice(0, -1) + "emasu"; }
else { return word.slice(0, -1) + "emasen"; }
}
else
{
if (affirmative) { return word.slice(0, -1) + "eru"; }
else { return word.slice(0, -1) + "enai"; }
}
break;
} else { return word; }
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment