That’s fine, I still have to find some time to use better practices. Like I said I don’t like the way I’m fetching answerChecker at the moment (hoping the controllers show up within 10 seconds and searching them for the answerChecker object) and I’m sure all my other scripts are dead now too thanks to the update. A welcome update to be sure and I always knew many of my scripts were built on shifting sands, but it does mean my scripts need some love I can’t really afford to give them right now.
The Easter long weekend has ended and I have work in the morning. I don’t know what the time is in your part of the world but here it is just past 11pm.
I’m glad it is working again for you, let me know if you have any more trouble.
Same issue here. This script just broke for me too. When using this script, I’m unable to submit an answer in a review. Hitting Enter does nothing. Everything works fine when this script is disabled.
Crummy 0.12.0 update uploaded, might work now? might not.
Don’t have time to do any robust testing yet. Feel free to post bugs for me to squash tonight… or later in the week idk.
// ==UserScript==
// @name WK Do You Even Kana?
// @namespace WKDYEK
// @version 0.12.1
// @description check that the okurigana matches the answer.
// @author Ethan
// @include http*://www.wanikani.com/subjects/*
// @grant none
// @license MIT
// ==/UserScript==
//patchy patch. 9-5-2023
var alertText = "Bro, Do you even Kana?";
// Hook into App Store
try { $('.app-store-menu-item').remove(); $('<li class="app-store-menu-item"><a href="https://community.wanikani.com/t/there-are-so-many-user-scripts-now-that-discovering-them-is-hard/20709">App Store</a></li>').insertBefore($('.navbar .dropdown-menu .nav-header:contains("Account")')); window.appStoreRegistry = window.appStoreRegistry || {}; window.appStoreRegistry[GM_info.script.uuid] = GM_info; localStorage.appStoreRegistry = JSON.stringify(appStoreRegistry); } catch (e) {}
//Create regex profiles (katakana matches need hiragana counterparts included)
/** Prepends Hiragana counterpart to any Katakana string input
* @param {String} char - A one character long string that may be a Katakana character
* @returns {String} A single character if the input is Hiragana or "ー"; A two character string of (hopefully) Hiragana-Katakana pairs in square brackets (that can form a regex) if not.
* @bug Will attempt to pair any character that is not Hiragana or "ー"
*/
function pairKatakana(char){
if (/^[\u3040-\u309fー]$/.test(char)){//is char hiragana or "ー"?
return char;
}else{
//set up pairs
var offset = -6*16; //katakana block: 30a0-30ff
var katakana = String.fromCharCode(char.charCodeAt(0) + offset);
return "["+char+katakana+"]";
}
}
/** Returns true if the character is Kana
*/
function isKana(char){
return /^[\u3040-\u30ff]$/.test(char);
}
/** Creates regex from a vocabulary item that matches the Kana in that item.
*/
function makeRegex(cV){
var r = "^"; //start the regex string
for (var c = 0; c < cV.length; c++){
if (isKana(cV[c])){
r += pairKatakana(cV[c]);
}
else{//we have a non-kana character
if (cV[c] !== "〜"){ //I doubt WK will be adding Kana suffixes but just covering all the bases to be safe.
r += "(.+)"; // unknown number of characters in reading (corresponding to kanji), capturing in groups for versatility
while ((c < cV.length)&&!isKana(cV[c+1])){
c++;//skip non-kana characters (already have ".+" in our regex, do not need to add more)
}
}
}
}
r += "$";// End of regex
return new RegExp(r);
}
//Get answerChecker Object
//Stimulus.controllers.filter((x)=>{return x.answerChecker;})[0]
var getAnswerChecker = function(timeout) {
var start = Date.now();
function waitForAnswerChecker(resolve, reject) {
if (typeof Stimulus !=='undefined' && Stimulus.controllers.filter((x)=>{return x.answerChecker;})[0]){
var answerChecker = Stimulus.controllers.filter((x)=>{return x.answerChecker;})[0].answerChecker;
resolve(answerChecker);
}
else if (timeout && (Date.now() - start) >= timeout)
reject(new Error("timeout"));
else
setTimeout(waitForAnswerChecker.bind(this, resolve, reject), 30);
}
return new Promise(waitForAnswerChecker);
};
/** @typedef Evaluation
* @property {boolean} [accurate] - If true, the answer matched one of the possible answers
* @property {boolean} [exception] - If true, the exception animation will run and the answer will not be processed.
* @property {boolean} [multipleAnswers] - If true, Wanikani has more than one correct answer for the ReviewItem, a notification will be shown saying this.
* @property {boolean} [passed] - If true, The answer is determined to be close enough to pass. In the case that accurate is false, the answer will pass with a notification to check your answer.
*/
/** Can be either a meaning or a reading
* @typedef Assignment
* @property {string}
*/
var dyek = function(answerChecker){
//console.log("main function loading");
//Get the answerChecker object out of Stimulus Controllers
//var quizController = Stimulus.controllers.filter((x)=>{return x.answerChecker;})[0];
//var answerChecker = quizController&&quizController.answerChecker;
//Boy, I do love to wrap this function don't I?
answerChecker.oldEvaluate = answerChecker.evaluate.bind(answerChecker);
/** New evaluate function to send an exception if it doesn't meet our requirements
* @param
* @param
* @returns {Evaluation}
*/
/* April 2023 evaluate now takes an object as its only argument
{
questionType: this.currentQuestionType,
response: e,
item: this.currentSubject,
userSynonyms: t,
inputChars: this.inputChars
}
*/
answerChecker.evaluate = function(e,n,i,t){
var getQuestionType = function(){
return e.questionType; //this.currentQuestionType?
//return $(".quiz-input__question-type").innerHTML.toLowerCase();
};
var getQuestionCategory = function(){
return e.item.type.toLowerCase();
//return i.subject_category.toLowerCase();
//return $(".quiz-input__question-category").innerHTML.toLowerCase();
};
var isVoc = (() => {return getQuestionCategory() === 'vocabulary';})();
var getCurrentItem = function(){
return e.item.characters;
//return answerChecker.currentSubject.characters;
};
var getResponse = function(){
return e.response;
};
//jStorage no longer used in WaniKani
/** @type {string} */
var questionType = getQuestionType();
/** @type {ReviewItem} */
var cI = getCurrentItem();
// If cI is vocabulary
if (isVoc&&
// is a reading
questionType === "reading"&&
// and doesn't pass regex
!makeRegex(cI).test(getResponse())){
//If it's a reading and it doesn't pass regex
return {
action: 'retry',
message: {
text: alertText,
type: 'answerException',
},
};
}else{
return answerChecker.oldEvaluate(e,n,i,t);
}
};
};
getAnswerChecker(60000).then(dyek);
//import('lib/answer_checker/answer_checker').then(dyek);
//window.addEventListener('load', dyek, false);
Changes
Change Line 158 (return {exception: alertText};) to
This script has been really helpful, thank you for writing it! I noticed that it seems to have trouble with the new vocab word 〜ヶ月 - the reading is かげつ, but it won’t let me enter it, presumably because that doesn’t contain ケ.