[Userscript] Wanikani Review SRS/Level Indicator

Hi all,

I love this script and got sick of not having it. I’ve never written a script before and there’s not much to go off of with the new update, so hopefully I did well. :x

I have absolutely no intention to migrate OP’s script or maintain this hacky one I just wrote, nor have I even used it much to see if it’s buggy or checked it across browsers, but this does something similar. It’s a bit inefficient because the willShowNextQuestion event fires more often than the circles need to be updated, but I think it works?

Add this to your script managers:

// ==UserScript==
// @name         Show SRS Level In Reviews
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Self explanatory
// @author       Whoever can be bothered
// @match        https://www.wanikani.com/*
// @match        https://preview.wanikani.com/*
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    const url_array = window.location.pathname.split("/");
    const url_last = url_array[url_array.length - 1];

    if (url_last != "review") {
        return; // do not run script unless we're on the review page
    }

    const append_css = (css) => {
        const head_element = document.getElementsByTagName("head")[0];
        const style_element = document.createElement("style");
        style_element.setAttribute("type", "text/css");
        style_element.setAttribute("id", "showsrs_css");
        style_element.appendChild(document.createTextNode(css));
        head_element.appendChild(style_element);
    }

    const CONTAINER_CLASSNAME = "showsrs__container";
    const CIRCLE_CLASSNAME = "showsrs__circle";

    const srs_stages = {
        A1: 1,
        A2: 2,
        A3: 3,
        A4: 4,
        G1: 5,
        G2: 6,
        M: 7,
        E: 8,
    };

    const colours = {
        APPRENTICE: "221, 0, 147",
        GURU: "135, 45, 158",
        MASTER: "41, 77, 219",
        ENLIGHTENED: "0, 147, 221",
        DEFAULT: "255, 255, 255",
    }

    const TRANSPARENCY = 1.0;

    // Create object mapping item id to srs stage
    const id_srs_element = document.querySelector("script[data-quiz-queue-target=\"subjectIdsWithSRS\"]");
    const id_srs_array = JSON.parse(id_srs_element.innerHTML);
    const id_to_srs = Object.fromEntries(id_srs_array);

    // Create container for circle indicators
    const meaning_element = document.getElementsByClassName("quiz-input__input-wrapper");
    const container = document.createElement("div");
    container.className = CONTAINER_CLASSNAME;
    meaning_element[0].insertBefore(container, meaning_element[0].firstChild);

    append_css(`
    .${CONTAINER_CLASSNAME} {
        display: flex;
        justify-content: center;
        gap: 5px;
        padding-top: 10px;
    }

    .${CIRCLE_CLASSNAME} {
        width: 10px;
        height: 10px;
        border: 2px solid;
        border-radius: 50%;
    }`);

    // Append and create 8 circles to container

    for (const [key, value] of Object.entries(srs_stages)) {
        const circle = document.createElement("div");
        circle.className = CIRCLE_CLASSNAME;

        if (value <= srs_stages.A4) {
            circle.style.borderColor = `rgba(${colours.APPRENTICE}, ${TRANSPARENCY})`;
        } else if (value <= srs_stages.G2) {
            circle.style.borderColor = `rgba(${colours.GURU}, ${TRANSPARENCY})`;
        } else if (value == srs_stages.M) {
            circle.style.borderColor = `rgba(${colours.MASTER}, ${TRANSPARENCY})`;
        } else if (value == srs_stages.E) {
            circle.style.borderColor = `rgba(${colours.ENLIGHTENED}, ${TRANSPARENCY})`;
        }

        container.appendChild(circle);
    }

    const update_circle = (circle, stage) => {
        if (stage <= srs_stages.A4) {
            circle.style.backgroundColor = `rgba(${colours.APPRENTICE}, ${TRANSPARENCY})`;
        } else if (stage <= srs_stages.G2) {
            circle.style.backgroundColor = `rgba(${colours.GURU}, ${TRANSPARENCY})`;
        } else if (stage == srs_stages.M) {
            circle.style.backgroundColor = `rgba(${colours.MASTER}, ${TRANSPARENCY})`;
        } else if (stage == srs_stages.E) {
            circle.style.backgroundColor = `rgba(${colours.ENLIGHTENED}, ${TRANSPARENCY})`;
        }
    }

    const circles = document.getElementsByClassName(CIRCLE_CLASSNAME);

    window.addEventListener("willShowNextQuestion", (e) => {
        const item_id = e.detail.subject.id;
        const srs_stage = id_to_srs[item_id];
        for (let i = 0; i < circles.length; i++) {
            const corrected_index = i + 1;
            if (corrected_index <= srs_stage) {
                update_circle(circles[i], corrected_index);
            } else {
                circles[i].style.backgroundColor = "";
            }
        }
    });

})();

E: Added check to only run script on the review page.

8 Likes