Modifiable answer checker in reviews and lessons
Dieses Skript sollte nicht direkt installiert werden. Es handelt sich hier um eine Bibliothek für andere Skripte, welche über folgenden Befehl in den Metadaten eines Skriptes eingebunden wird // @require https://update.greasyfork.org/scripts/470201/1215595/WaniKani%20Answer%20Checker.js
// ==UserScript==
// @name WaniKani Answer Checker
// @namespace http://www.wanikani.com
// @version 0.1.0
// @description Modifiable answer checker in reviews and lessons
// @author polv
// @match https://www.wanikani.com/*
// @match https://preview.wanikani.com/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=wanikani.com
// @license MIT
// @source https://github.com/patarapolw/wanikani-userscript/blob/master/userscripts/answer-checker.user.js
// @grant none
// ==/UserScript==
// @ts-check
/// <reference path="./types/answer-checker.d.ts" />
(function () {
class ModAnswerChecker {
/**
* @type {TryEvaluationFunction[]}
*/
mods = [];
/**
* @type {{
* oldEvaluate?: EvaluationFunction
* evaluate: EvaluationFunction
* } | null}
*/
answerChecker = null;
/**
*
* @param {TryEvaluationFunction} fn
*/
register(fn) {
this.mods.push(fn);
}
constructor() {
// Automatically init on new instance
window.addEventListener('turbo:load', (e) => {
// @ts-ignore
const url = e.detail.url;
if (!url) return;
/**
* e.g.
* https://www.wanikani.com/subjects/lesson/quiz?queue=${subjectIds.join('-')}
* https://www.wanikani.com/subjects/review
* https://www.wanikani.com/subjects/extra_study?queue_type=${queueType}
*/
if (/(session|quiz|review|extra_study)/.test(url)) {
// @ts-ignore
const Stimulus = window.Stimulus;
if (!Stimulus) return;
const startDate = +new Date();
const intervalId = setInterval(() => {
this.answerChecker =
Stimulus.controllers.find((x) => {
return x.answerChecker;
})?.answerChecker || null;
if (this.answerChecker) {
clearInterval(intervalId);
if (this.answerChecker.oldEvaluate) return;
const answerChecker = this.answerChecker;
console.log('Found new answerChecker');
const oldEvaluate = answerChecker.evaluate.bind(answerChecker);
answerChecker.oldEvaluate = oldEvaluate;
/** @type {(fns: TryEvaluationFunction[]) => EvaluationFunction} */
const evaluateWith = (fns) => {
return (e) => {
for (const fn of fns) {
const r = fn(
e,
evaluateWith(fns.filter((it) => it !== fn)),
);
if (r) return r;
}
return oldEvaluate(e);
};
};
answerChecker.evaluate = evaluateWith(this.mods);
}
if (startDate + 5000 < +new Date()) {
clearInterval(intervalId);
}
}, 500);
}
});
}
}
window.modAnswerChecker = window.modAnswerChecker || new ModAnswerChecker();
})();