[Japanese] Memrise Kana Detection

Warns whether to answer in Hiragana or Katakana on Japanese kana tests

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name           [Japanese] Memrise Kana Detection
// @description    Warns whether to answer in Hiragana or Katakana on Japanese kana tests
// @author         Kai Krause <[email protected]>
// @match          http://*.memrise.com/*
// @match          https://*.memrise.com/*
// @version        1.5
// @grant          none
// @run-at         document-end
// @namespace      https://greasyfork.org/users/3656
// ==/UserScript==

var onLoad = function() {
	// Get all questions and answers in the queue
	var questionsAnswers = MEMRISE.garden.screens;
	var getCurrentItem = function(displayedQuestion) {
		for (var id in questionsAnswers) {
			var expectedQuestion = questionsAnswers[id].typing.prompt.text.value.trim();
			if (displayedQuestion === expectedQuestion) {
				var expectedAnswer = questionsAnswers[id].typing.answer.value;
				if (expectedQuestion && expectedAnswer) {
					return {
						question : expectedQuestion,
						answer   : expectedAnswer
					};
				}
			}
		}
	};

	var displayError = function(msg) {
		var kanaError = document.getElementById('kanaError');
		if (kanaError && !msg) {
			kanaError.parentNode.removeChild(kanaError);
			return;
		}

		if (!kanaError) {
			var elem = document.createElement("div");
			elem.id = "kanaError";
			elem.align = "center";
			elem.style = "font-weight: bold; font-size:34px; color:#FF0000;";
			elem.textContent = msg;
			document.body.append(elem);
		}
	};

	var enterKeyDisabler = function(event){
		var keycode = event.which || event.keycode;
		var kanaError = document.getElementById('kanaError');
		if (kanaError && keycode == 13) {
			event.preventDefault();
		}
	};
	window.addEventListener("keypress", enterKeyDisabler);

	var isAnswerHiragana = false;
	var isAnswerKatakana = false;
	var calculateKanaType = function(answer) {
		for (var i = 0; i < answer.length; ++i) {
			//Hiragana check
			if (answer.charCodeAt(i) >= 12353 && answer.charCodeAt(i) <= 12435 ) {
				isAnswerHiragana = true;
			}
			//Katakana check
			else if (answer.charCodeAt(i) >= 12443 && answer.charCodeAt(i) <= 12532 ) {
				isAnswerKatakana = true;
			}
		}
	};

	var compareAnswer = function(given) {
		var givenhiragana = 0;
		var givenkatakana = 0;
		var givenenglish = 0;

		if (!given || given.length === 0) return;

		for (var i = 0; i < given.length; ++i) {
			//Calculate user's answer for Kana type
			if (given.charCodeAt(i) >= 12353 && given.charCodeAt(i) <= 12435) {
				++givenhiragana;
			}
			else if (given.charCodeAt(i) >= 12443 && given.charCodeAt(i) <= 12532 ) {
				++givenkatakana;
			}
			//Actual English || Kana inputted English
			else if (given.charCodeAt(i) >= 65 && given.charCodeAt(i) <= 122 || given.charCodeAt(i) >= 65346 && given.charCodeAt(i) <= 65370) {
				++givenenglish;
			}

			//Compare our two kana types, the expected answer and the user's
			if (isAnswerHiragana && isAnswerKatakana){
				if (givenhiragana === 0 || givenkatakana === 0 || givenenglish > 0){
					displayError("Hiragana & Katakana!");
				}
				else if (givenhiragana > 0 && givenkatakana > 0 && givenenglish === 0){
					displayError("");
				}
			}
			else if (isAnswerHiragana){
				if (givenhiragana === 0 || givenkatakana > 0 || givenenglish > 0){
					displayError("Hiragana!");
				}
				else if (givenhiragana > 0 && givenkatakana === 0 && givenenglish === 0){
					displayError("");
				}
			}
			else if (isAnswerKatakana){
				if (givenkatakana === 0 || givenhiragana > 0 || givenenglish > 0){
					displayError("Katakana!");
				}
				else if (givenkatakana > 0 && givenhiragana === 0 && givenenglish === 0){
					displayError("");
				}
			}
		}
	};

	var cachedQuestion = "";
	var checkAnswer = function() {
		var displayedQuestion = document.getElementsByClassName("qquestion")[0].childNodes[0].nodeValue.trim();
		var givenAnswer = document.getElementsByClassName("typing-type-here")[0].value;
		var expectedAnswer = getCurrentItem(displayedQuestion).answer;

		//Evaluate kana type of the expectedAnswer
		if (displayedQuestion != cachedQuestion) {
			cachedQuestion = displayedQuestion;
			calculateKanaType(expectedAnswer);
		}

		if (givenAnswer) {
			compareAnswer(givenAnswer);
		}
	};
	window.addEventListener("keyup", checkAnswer);
};

window.addEventListener('load',
function() {
	onLoad();
}, false);