AnkiWeb Quiz

Shows quiz on ankiweb

目前為 2017-06-24 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name        AnkiWeb Quiz
// @namespace   https://greasyfork.org/users/102866
// @description Shows quiz on ankiweb
// @include     https://ankiweb.net/*
// @include     http://ankiweb.net/*
// @require     https://code.jquery.com/jquery-3.1.1.min.js
// @author      TiLied
// @version     0.2.3
// @grant       GM_getResourceText
// @grant       GM_listValues
// @grant       GM_deleteValue
// @grant       GM_getValue
// @grant       GM_setValue
// @resource    ankiDeck Japanese.txt
// @resource    ankiDeck1 JLPTN5.txt
// @resource    ankiDeck2 TheKodanshaKanjiLearnersCourse.txt
// ==/UserScript==

//not empty val
var originAnkiDeck = GM_getResourceText("ankiDeck"),
	std = window.eval("require('study').default;"),
	defaultDeck = new Deck("question default", "answer default", 10001, 20002),
	defaultDecks =
	{
		defaultId:
			{
				cards: defaultDeck,
				updateDeck: false
			}
	};

//const
const inBstring = "<awq>",
	inEstring = "</awq>",
	inBegAnswer = "<awq_answer>",
	inEndAnswer = "</awq_answer>",
	textDefault = "You need to use this deck more to get more variations";

//arrays
var stringArray = [],
	tempStrings = [],
	falseAnswers = [],
	inB = [],
	inE = [],
	buttons = [],
	tempArr = [];

//empty val
var searchFor,
	trueAnswer,
	trueId,
	id,
	rubyVal,
	deck;

//prefs
var amountButtons,
	debug,
	decks;

Main();

function Main()
{
	inB = FindIndexes(inBstring, originAnkiDeck);
	inE = FindIndexes(inEstring, originAnkiDeck);
	console.log(inB);
	console.log(inE);

	for (var i = 0; i < inB.length; i++)
	{
		tempStrings[i] = originAnkiDeck.slice(inB[i] + 5, inE[i]);
		//console.log(tempStrings[i]);
	}
	console.log(tempStrings);
	CssAdd();
	SetSettings();
}

//Settings
function SetSettings()
{
	const settings = $("<li class=nav-item></li>").html("<a id=awq_settings class=nav-link>Settings Ankiweb Quiz " + GM_info.script.version + "</a> \
		<div id=awq_settingsPanel class=awq_settingsP>\
		<form> \
		<br> \
		Debug: <input type=checkbox name=debug id=awq_debug></input>\
		</form>\
		<button id=hideButton class=awq_style>Hide</button>\
		</div>\
		");

	$(".navbar-nav:first").append(settings);
	$("#awq_settings").addClass("awq_settings");
	$("#awq_settingsPanel").hide();
	SetEventSettings();
	LoadSettings();
}

function LoadSettings()
{
	//THIS IS ABOUT DEBUG
	if (HasValue("awq_debug", false))
	{
		debug = GM_getValue("awq_debug");
		$("#awq_debug").prop("checked", debug);
	}

	//THIS IS ABOUT DECKS
	if (HasValue("awq_decks", JSON.stringify(defaultDecks)))
	{
		decks = JSON.parse(GM_getValue("awq_decks"));
	}

	//THIS IS ABOUT BUTTONS
	if (HasValue("awq_amountButtons", 8))
	{
		amountButtons = GM_getValue("awq_amountButtons");
	}

	//Console log prefs with value
	console.log("*prefs:");
	console.log("*-----*");
	var vals = [];
	for (var i = 0; i < GM_listValues().length; i++)
	{
		vals[i] = GM_listValues()[i];
	}
	for (var i = 0; i < vals.length; i++)
	{
		console.log("*" + vals[i] + ":" + GM_getValue(vals[i]));
	}
	console.log("*-----*");
}

//Check if value exists or not.  optValue = Optional
function HasValue(nameVal, optValue)
{
	var vals = [];
	for (var i = 0; i < GM_listValues().length; i++)
	{
		vals[i] = GM_listValues()[i];
	}

	if (vals.length === 0)
	{
		if (optValue != undefined)
		{
			GM_setValue(nameVal, optValue);
			return true;
		} else
		{
			return false;
		}
	}

	for (var i = 0; i < vals.length; i++)
	{
		if (vals[i] === nameVal)
		{
			return true;
		}
	}

	if (optValue != undefined)
	{
		GM_setValue(nameVal, optValue);
		return true;
	} else
	{
		return false;
	}
}

//Delete Values
function DeleteValues(nameVal)
{
	var vals = [];
	for (var i = 0; i < GM_listValues().length; i++)
	{
		vals[i] = GM_listValues()[i];
	}

	if (vals.length === 0 || typeof nameVal != "string")
	{
		return;
	}

	switch (nameVal)
	{
		case "all":
			for (var i = 0; i < vals.length; i++)
			{
				GM_deleteValue(vals[i]);
			}
			break;
		case "old":
			for (var i = 0; i < vals.length; i++)
			{
				if (vals[i] === "debug" || vals[i] === "debugA")
				{
					GM_deleteValue(vals[i]);
				}
			}
			break;
		default:
			for (var i = 0; i < vals.length; i++)
			{
				if (vals[i] === nameVal)
				{
					GM_deleteValue(nameVal);
				}
			}
			break;
	}
}

//Construction of Deck
function Deck(question, answer, idTimeOne, idTimeTwo)
{
	this.question = [question];
	this.answer = [answer];
	this.idTimeOne = [idTimeOne];
	this.IdTimeTwo = [idTimeTwo];
}

function SetEventSettings()
{
	$("#awq_settings").click(function ()
	{
		$("#awq_settingsPanel").toggle(1000);
	});

	$("#hideButton").click(function ()
	{
		$("#awq_settingsPanel").toggle(1000);
	});

	$("#awq_debug").change(function ()
	{
		GM_setValue("awq_debug", $(this).prop("checked"));
		debug = $(this).prop("checked");
		alert("Settings has been changed. Please reload the page.");
	});
}

function FindIndexes(searchStr, str, caseSensitive)
{
	var searchStrLen = searchStr.length;
	if (searchStrLen == 0) {
		return [];
	}
	var startIndex = 0, index, indices = [];
	if (!caseSensitive) {
		str = str.toLowerCase();
		searchStr = searchStr.toLowerCase();
	}
	while ((index = str.indexOf(searchStr, startIndex)) > -1) {
		indices.push(index);
		startIndex = index + searchStrLen;
	}
	return indices;
}

//css styles adds
function CssAdd()
{
	$("head").append($("<!--Start of AnkiWeb Quiz v" + GM_info.script.version + " CSS-->"));

	$("head").append($("<style type=text/css></style>").text("button.awq_btn { \
		 \
		}"));

	$("head").append($("<style type=text/css></style>").text("a.awq_settings { \
		cursor: pointer;\
		}"));

	$("head").append($("<style type=text/css></style>").text("div.awq_settingsP { \
		position:absolute; width:300px; background-color: #fff; border-color: #eee!important; border-radius: .3rem; border: 2px solid transparent; z-index: 150;\
		}"));

	$("head").append($("<style type=text/css></style>").text("button.awq_style { \
		cursor: pointer; color: #fff; background-color: #0275d8; border-color: #0275d8; padding: .75rem 1.5rem; font-size: 1rem; border-radius: .3rem; border: 1px solid transparent; max-width:200px; margin:5px;\
		}"));

	$("head").append($("<style type=text/css></style>").text("button.awq_style:hover { \
		cursor: pointer; color: #fff; background-color: #025aa5; border-color: #01549b; padding: .75rem 1.5rem; font-size: 1rem; border-radius: .3rem; border: 1px solid transparent;\
		}"));

	$("head").append($("<style type=text/css></style>").text("div.awq_rstyle { \
		width:100%; margin-top:30px; z-index: 100;\
		}"));

	$("head").append($("<style type=text/css></style>").text("button.awq_true { \
		background-color: #75d802; border-color: #75d802;\
		}"));

	$("head").append($("<style type=text/css></style>").text("button.awq_true:hover { \
		background-color: #5aa502; border-color: #5aa502;\
		}"));

	$("head").append($("<style type=text/css></style>").text("button.awq_false { \
		background-color: #d80275; border-color: #d80275;\
		}"));

	$("head").append($("<style type=text/css></style>").text("button.awq_false:hover { \
		background-color: #a5025a; border-color: #a5025a;\
		}"));

	$("head").append($("<!--End of AnkiWeb Quiz v" + GM_info.script.version + " CSS-->"));
}

$(document).ready(function () {

	// Append some text to the element with id someText using the jQuery library.
	//$("#studynow").append(" more text...................");

	$("#studynow").click(function () {
		setTimeout(function ()
		{
			SetUI();
			searchFor = SearchQuestion();
			if (debug)
			{
				console.log("searchFor:" + searchFor);
			}
			GetTrueAnswer(searchFor);
			if (debug) {
				console.log('Study Click');
			}
		}, 1500);
	});

	function SetUI()
	{
		const buttonP = $("<button id=awq_quiz class=btn style=margin-left:4px></button>").text("Quiz");
		const button = $("<div class=awq_rstyle></div>").html("<button class=awq_btn></button><button class=awq_btn></button><button class=awq_btn></button><button class=awq_btn></button><button class=awq_btn></button><button class=awq_btn></button><button class=awq_btn></button><button class=awq_btn></button>");

		$(".pt-1").before("<br>");
		$(".pt-1").before(button);

		$("#leftStudyMenu").after(buttonP);

		SettingsEvents();

		$("#awq_quiz").addClass("btn-secondary");
		$(".awq_btn").addClass("awq_style");
		$(".awq_rstyle").hide();
	}

	function SettingsEvents()
	{

		$("#awq_quiz").click(function () {
			$(".awq_rstyle").toggle();
		});

		$("#ansbuta").click(function ()
		{
			setTimeout(function ()
			{
				if (debug)
				{
					console.log("Button check");
				}
				$("#ease1").click(function ()
				{
					OtherEvent();
				});
				$("#ease2").click(function ()
				{
					OtherEvent();
				});
				$("#ease3").click(function ()
				{
					OtherEvent();
				});
				$("#ease4").click(function ()
				{
					OtherEvent();
				});
			}, 500);
		});

		$(".awq_btn").click(function ()
		{
			if (debug)
			{
				if ($(this).attr("title"))
				{
					console.log("html:" + $(this).attr("title"));
					console.log("true:" + trueAnswer);
				} else
				{
					console.log("html:" + $(this).html());
					console.log("text:" + $(this).text());
					console.log("------------------------");
					console.log("true:" + trueAnswer);
					console.log("************************");
				}
			}

			if ($(this).attr("title"))
			{
				if (trueAnswer == $(this).attr("title"))
				{
					$(this).addClass("awq_true");
				} else
				{
					$(this).addClass("awq_false");
				}
			} else
			{
				if (trueAnswer == $(this).html() || trueAnswer == $(this).text())
				{
					$(this).addClass("awq_true");
				} else
				{
					$(this).addClass("awq_false");
				}
			}
		});
	}

	function EscapeRegExp(string)
	{
		return string.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
	}

	function SearchQuestion()
	{
		if (debug)
		{
			console.log("span: ");
			console.log($("awq_question").has("span"));
		}
		if ($("awq_question").has("span").length >= 1)
		{
			var contentText = $("awq_question").contents().filter(function ()
			{
				return this.nodeType == 3;
			});

			var contentSpan = $("awq_question").contents().filter("span");

			if (debug)
			{
				console.log(contentText);
				console.log(contentSpan);
			}

			rubyVal = "";
			var x = 0;
			if (contentText >= contentSpan)
			{
				for (var i = 0; i < contentText.length; i++)
				{
					rubyVal += $.trim(contentText[i].nodeValue);
					if (x < contentSpan.length)
					{
						rubyVal += "<ruby><rb>";
						rubyVal += $.trim($(contentSpan[x]).contents().filter(function ()
						{
							return this.nodeType == 3;
						})[0].nodeValue) + "</rb><rt>";
						rubyVal += $(contentSpan[x]).contents()[0].innerHTML + "</rt></ruby>";
						x++;
					}
				}
			} else
			{
				for (var i = 0; i < contentSpan.length; i++)
				{
					if (x < contentText.length)
					{
						rubyVal += $.trim(contentText[x].nodeValue);
						x++;
					}
					rubyVal += "<ruby><rb>";
					rubyVal += $.trim($(contentSpan[i]).contents().filter(function ()
					{
						return this.nodeType == 3;
					})[0].nodeValue) + "</rb><rt>";
					rubyVal += $(contentSpan[i]).contents()[0].innerHTML + "</rt></ruby>";
				}
			}
			return rubyVal;
		} else
		{
			return $.trim($("awq_question").text());
		}
	}

	//Replace wrong <br>'s or other html tags, should work perfectly but it isn't >:( Fixed(probably)
	function ReplaceString(str)
	{
		var trueString = str;

		while (trueString.search("<br />") !== -1)
		{
			trueString = str.replace(/<br \/>/g, "<br>");
		}

		return trueString;
	}

	function GetTrueAnswer(sFor)
	{
		var regex = '(^|\\s|\\b|(n\\>))';
		var tempQuestion;
		var strQ;
		regex += EscapeRegExp(sFor);
		regex += '($|\\s|\\b|(\\<\\/a))';

		if (debug)
		{
			console.log(regex);
		}

		for (var i = 0; i < tempStrings.length; i++) {
			//console.log('sFor =' + sFor + " leng " + sFor.length + " debug : " + new RegExp(regex, "g").test(tempStrings[i]));
			//contains = tempStrings[i].matches(".*\\bram\\b.*");
			//tempQuestion = '';
			//strQ = '';
			//strQ = tempStrings[i].toString();
			//tempQuestion = $.trim(str.slice(str.indexOf("<awq_question>") + 14, str.indexOf("</awq_question>")));
			//console.log(tempQuestion);
			if (new RegExp(regex, "g").test(tempStrings[i]))
			{
				const str = tempStrings[i].toString();
				trueAnswer = ReplaceString($.trim(str.slice(str.indexOf(inBegAnswer) + 12, str.indexOf(inEndAnswer))));
				trueId = i;
				if (debug)
				{
					//console.log(tempStrings[i - 1]);
					console.log(str);
					//console.log(tempQuestion);
					//console.log(tempStrings[i + 1]);
					console.log("True answer : " + trueAnswer + " id trueAnsw = " + trueId);
				}
				GetFalseAnswers(trueId);
				break;
			}
		}
	}

	function GetFalseAnswers(trueId) {
		tempArr.length = 0;
		for (var i = 0; i < 7; i++) {
			id = GetRand(tempStrings);
			if (id != trueId) {
				if (debug) {
					console.log(tempStrings[id]);
				}
				const str = tempStrings[id].toString();
				falseAnswers[i] = str.slice(str.indexOf(inBegAnswer) + 12, str.indexOf(inEndAnswer));
				if (debug) {
					console.log("***False answer " + i + " : " + falseAnswers[i] + " id: " + id);
					//console.log("inBegAnswer: " + str.indexOf(inBegAnswer) + " : " + str.indexOf(inEndAnswer) + " inEndAnswer");
				}
			} else {
				id = GetRand(tempStrings);
				i--;
			}
		}
		RamdomButton();
	}

	function OtherEvent()
	{
		if (debug) {
			console.log("Button click");
			console.log("---------------");
		}
		searchFor = "";
		//searchFor = $("awq_question").html();
		searchFor = SearchQuestion();
		if (debug) {
			console.log("searchFor:" + searchFor);
			console.log($("awq").text().length);
		}
		$(".awq_rstyle").hide();
		if (searchFor == "") {
			setTimeout(function () {
				if ($("awq").text().length === 0) {
					setTimeout(function () {
						//searchFor = $("awq_question").html();
						searchFor = SearchQuestion();
						if (debug) {
							console.log("searchFor:::" + searchFor);
						}
						GetTrueAnswer(searchFor);
					}, 3000);
				} else {
					//searchFor = $("awq_question").html();
					searchFor = SearchQuestion();
					if (debug) {
						console.log("searchFor::" + searchFor);
					}
					GetTrueAnswer(searchFor);
				}
			}, 1000);
		} else {
			GetTrueAnswer(searchFor);
		}
	}

	//random functions
	function InArray(array, el) {
		for (var i = 0 ; i < array.length; i++)
			if (array[i] == el) return true;
		return false;
	}

	function GetRand(array) {
		var rand = Math.floor(Math.random() * array.length);
		if (!InArray(tempArr, rand)) {
			tempArr.push(rand);
			return rand;
		}
		return GetRand(array);
	}
	//end of random functions

	function RamdomButton()
	{
		buttons.length = 0;
		tempArr.length = 0;
		var allAnswers = [];
		allAnswers[0] = trueAnswer;
		for (var i = 1; i <= falseAnswers.length; i++) {
			allAnswers[i] = falseAnswers[i - 1];
		}
		if (debug) {
			console.log("False answers :");
			console.log(falseAnswers);
			console.log("ALL answers :");
			console.log(allAnswers);
		}
		for (var i = 0; i < allAnswers.length; i++) {
			buttons[i] = $.trim(allAnswers[GetRand(allAnswers)]);
		}
		if (debug) {
			console.log("Random order :) = " + buttons);
			// console.log($(".awq_LeftSide").html());
		}
		UiButtons();
	}

	function UiButtons()
	{
		const sel = document.querySelectorAll("button.awq_btn");
		if (debug)
		{
			console.log("*HERE UI BUTTONS :");
		}

		for (var i = 0; i < buttons.length; i++)
		{
			//Delete arttribute
			if ($(sel[i]).attr("title"))
			{
				$(sel[i]).removeAttr("title");
			}

			if (buttons[i].length <= 40 || buttons[i].includes("</ruby>"))
			{
				$(sel[i]).html(buttons[i]);
			} else
			{
				$(sel[i]).html(buttons[i].slice(0, 40) + "...");
				$(sel[i]).attr("title", buttons[i]);
			}
			
			if (debug)
			{
				//console.log(sel[i]);
				console.log(buttons[i] + " Length: " + buttons[i].length);
				console.log(buttons[i].includes("</ruby>"));
			}
		}

		CheckPresedButtons();
	}

	function CheckPresedButtons()
	{ 
		$(".awq_btn").removeClass("awq_true");
		$(".awq_btn").removeClass("awq_false");
	}

	console.log("AnkiWeb Quiz v" + GM_info.script.version + " Initialized"); 
});


// ------------
//  TODO
// ------------

/* TODO STARTS
	0)REWRITE EVERYTHING WITHOUT USING GETRESOURCE AND CHANGING CODE
✓    1)Make it only one element of buttons  //DONE 0.0.9
		1.1)Increase numbers of buttons to 10-12(optional through settings???)
✓    2)Make it limit of length answer and put whole in attribute title  //DONE 0.1.0
✓    3)Make it settings, almost done in 0.1.0	//DONE 0.2.0
✓        3.1)Debug   //DONE 0.1.0 
		3.2)Add txt file ***RESEARCH NEEDED***
			3.2.1)Choose them
		3.3)Make it always show quiz
✓    4)Make it full functionality of Japanese deck, partial done in 0.0.8    //DONE 0.0.9 Happy with that :)
	5)Search question in between tags <awq_question> and </awq_question> not in whole sentence, almost done in 0.1.2
✓    6)TODO for loop in finding question NEED TEST IT    //DONE 0.1.7 BROKEN     //DONE 0.1.9
TODO ENDS */