您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Show "Apprentice 3" instead of "Apprentice", etc.
// ==UserScript== // @name WaniKani Show Specific SRS 2 // @namespace https://www.wanikani.com // @description Show "Apprentice 3" instead of "Apprentice", etc. // @author Gijsc1 // @version 2.1.0 // @match https://www.wanikani.com/* // @license MIT; http://opensource.org/licenses/MIT // @grant none // ==/UserScript== (async function(){ document.documentElement.addEventListener('turbo:load', ()=>{console.log("DEBUG: caught a page load")}); // taken from doublecheck function get_controller(name) { return Stimulus.getControllerForElementAndIdentifier(document.querySelector(`[data-controller~="${name}"]`),name); } let script_name = 'WaniKani Show Specific SRS 2'; let wkof_version_needed = '1.2.2'; if (!window.wkof) { if (confirm(script_name+' requires Wanikani Open Framework.\nDo you want to be forwarded to the installation instructions?')) { window.location.href = 'https://community.wanikani.com/t/instructions-installing-wanikani-open-framework/28549'; } return; } if (wkof.version.compare_to(wkof_version_needed) === 'older') { if (confirm(script_name+' requires Wanikani Open Framework version '+wkof_version_needed+'.\nDo you want to be forwarded to the update page?')) { window.location.href = 'https://gf.qytechs.cn/en/scripts/38582-wanikani-open-framework'; } return; } let target_path = '/subjects/review'; //console.log('registering specific srs listener'); wkof.on_pageload([target_path], () => setTimeout(load_script, 0)); //Hopefully temporary code to deal with registering after the load event has already fired. setTimeout(()=>{ if(!srs_manager && window.location.pathname == target_path) { load_script(); console.log('Specific SRS initialized'); } } , 500) let DidChangeSRSEvent; let quiz_queue; let srs_manager; async function load_script() { //console.log('Specific SRS initialization started'); // This seems like a weird way to import something, but doublecheck does it this way and it just works. DidChangeSRSEvent = (await importShim('events/did_change_srs_event')).default; quiz_queue = await grab_queue(); srs_manager = quiz_queue.quizQueue.srsManager; //console.log('actual srs_manager:',srs_manager); // swap out method with updated one below. srs_manager.updateSRS = new_updateSRS; console.log('Specific SRS initialized'); } // Waits for both stimulus and the quiz_queue to be defined, which happens after some unkown precondition is met somewhere else. async function grab_queue(){ let temp_queue; for (let i = 0; i < 50; i++) { // Probably the worst line of code I have ever written. //console.log('Stimulus status in iteration ',i,' :',typeof Stimulus); if (typeof Stimulus !== 'undefined' && (temp_queue = get_controller('quiz-queue'))) {return temp_queue;} // apparantly this is what passes for a sleep function in javascript. await new Promise(r => setTimeout(r, 100)); } console.error("Failed to load stimulus, script will probably crash later."); return temp_queue } let updatedSrsNames = ["invalid srs index","Apprentice 1","Apprentice 2","Apprentice 3","Apprentice 4","Guru 1","Guru 2","Master","Enlighten","Burn"] // A copy of the updateSRS method of the controllers/quiz_queue/srs_manager class. // Apparantly it is not possible to override static methods, so I override the method that calls the static method to instead call updateSrsNames. // I don't know if monkeypatching a method with the keyword 'this' in it will work, and what 'this' will then refer to. // I sidestep the issue by replacing 'this' with the specific srs_manager object. function new_updateSRS({subject, stats}) { if (!srs_manager.subjectIdSRSMap.has(subject.id)) { return; } const {srsId, srsPosition} = srs_manager.subjectIdSRSMap.get(subject.id) const totalIncorrect = stats.meaning.incorrect + stats.reading.incorrect if (totalIncorrect === 0) { window.dispatchEvent(new DidChangeSRSEvent({wentUp: true, newLevelText: updatedSrsNames[srsPosition+1] })) } else { const srsDropCoeffecient = srsPosition >= 5 ? 2 : 1; const newSRSStagePosition = Math.max(1, srsPosition - (srsDropCoeffecient * Math.round(totalIncorrect / 2))) window.dispatchEvent(new DidChangeSRSEvent({wentUp: false, newLevelText: updatedSrsNames[newSRSStagePosition] })) } } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址