[Userscript] Self-Study Quiz

Safari. Yes, the header as @GrumpyPanda said correctly.

I’m not sure if this one is the one you want though.

Before:

After:

Ahh, okay.
I’m able to replicate this in Safari.

It seems like a rendering bug in Safari, because if you resize the window at all (which forces it to redraw), it renders okay. It doesn’t seem to be related to the actual window size.

Also, I noticed that every 2nd time that I open Self-Study, it appears correct.
It’s still possible that it’s related to something that Open Framework does when closing menus after clicking on the Self-Study link. I can check it in a few days, but I have to work 14hrs today.

3 Likes

大丈夫。Take your time.

1 Like

:sob: my condolences :sob:

2 Likes

I’m considering augmenting this with a source for all JLPT vocabulary (to add to what Wanikani already has). What exactly would be involved? Does it already handle the SRS piece?

Not sure what you’re looking for, but it sounds like you want to study vocab with a seperate SRS system? Self-Study Quiz isn’t made for that kind of thing.
There are plenty systems out there that include JLPT options.

Thanks for the reply, but I was actually referring to this I think:

It looks like wkof was designed to allow for additional item sources:
“Allows client scripts to register additional data sources (such as an external set of Core10k vocabulary).”

And according to the source of this, it looks like it can use those added sources. Mainly wondering if anyone has tried and how involved it is. I am working now on adding a source to wkof

I don’t believe anyone has tried this yet (at least not shared publicly). And to answer your earlier question, it would not allow for SRS.

I have an example you can use. I’ll post it the next time I’m at my computer (I’m on tablet right now). It’s actually the start of a JLPT items plugin, and only needs the actual item data inserted. It includes filters for item type and JLPT level.

Right now, it’s set up to include the item data in the script itself, which will cause a delay every time a WK page is loaded, so it needs to be modified to fetch the item data from an external source (e.g. a second GreasyFork-hosted script) only when the user opens a Self-Study session.

2 Likes

[Userscript] Wanikani JLPT Items (for Self-Study Quiz)

Here’s the sample script I mentioned.

I modified the script a little so it now fetches the item data from an external file only when needed, so it’s pretty light-weight when not in use.

The external item data file needs to be on a server that grants CORS access to wanikani (or "*").
I’ve set up a sample with about 20 items on [https://www.wkstats.com/cors/wanikani/jlpt_items_v0.0.1.js]

Here’s the script source:

Source code
// ==UserScript==
// @name        Wanikani JLPT Items (for Self-Study Quiz)
// @namespace   rfindley
// @description Source for JLPT items in Self-Study Quiz
// @version     1.0.0
// @include     https://www.wanikani.com/*
// @copyright   2018+, Robin Findley
// @license     MIT; http://opensource.org/licenses/MIT
// @run-at      document-end
// @grant       none
// ==/UserScript==

window.jlpt_items = {};

(function(gobj) {

    /* global $, wkof */
    /* eslint no-multi-spaces: "off" */

    var jlpt_items_file = 'https://www.wkstats.com/cors/wanikani/jlpt_items_v0.0.1.js';

    //===================================================================
    // Initialization of the Wanikani Open Framework.
    //-------------------------------------------------------------------
    var script_name = 'JLPT Items (for Self-Study Quiz)';
    var wkof_version_needed = '1.0.45';
    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://greasyfork.org/en/scripts/38582-wanikani-open-framework';
        }
        return;
    }

    wkof.include('ItemData');
    wkof.ready('ItemData').then(startup);

    //===================================================================
    function jlpt_fetcher() {
        if (gobj.jlpt_items !== undefined) return Promise.resolve(gobj.jlpt_items);
        return wkof.load_script(jlpt_items_file, true /* use_cache */)
            .then(parse_items);
    }

    //===================================================================
    function parse_items() {
        var jlpt_items = {};
        var jlpt_level, items, item, idx;
        var id_cnt = 0;

        //------------------
        for (jlpt_level in gobj.kanji) {
            items = gobj.kanji[jlpt_level];
            for (idx in items) {
                item = items[idx];
                jlpt_items['jlpt_' + id_cnt++] = {
                    object: 'kanji',
                    data: {
                        jlpt_level: jlpt_level,
                        characters: item[0],
                        meanings: to_meanings(item[1]),
                        readings: to_yomi(item[2], item[3])
                    }
                };
            }
        }

        //------------------
        for (jlpt_level in gobj.vocabulary) {
            items = gobj.vocabulary[jlpt_level];
            for (idx in items) {
                item = items[idx];
                jlpt_items['jlpt_' + id_cnt++] = {
                    object: 'vocabulary',
                    data: {
                        jlpt_level: jlpt_level,
                        characters: item[0],
                        meanings: to_meanings(item[1]),
                        readings: to_readings(item[2], item[3])
                    }
                };
            }
        }

        //-------------------------------------------------------------------
        function to_meanings(text) {
            return split_list(text).map(function(meaning){return {meaning:meaning, primary:true, accepted_answer:true};});
        }
        //-------------------------------------------------------------------
        function to_yomi(kunyomi, onyomi) {
            return split_list(kunyomi).map(function(reading){return {type:'kunyomi', reading:reading, primary:true, accepted_answer:true};}).concat(
                split_list(onyomi).map(function(reading){return {type:'onyomi', reading:reading, primary:true, accepted_answer:true};})
            );
        }
        //-------------------------------------------------------------------
        function to_readings(text) {
            return split_list(text).map(function(reading){return {reading:reading, primary:true, accepted_answer:true};});
        }
        //-------------------------------------------------------------------

        return jlpt_items;
    }

    //-------------------------------------------------------------------
    function split_list(str) {return str.replace(/^\s+|\s*(,)\s*|\s+$/g, '$1').split(',').filter(function(name) {return (name.length > 0);});}

    //===================================================================
    var item_type_filter = {
        type: 'multi',
        label: 'Item type',
        default: [],
        content: {kanji:'Kanji',vocabulary:'Vocabulary'},
        filter_func: function(filter_value, item){return filter_value[item.object] === true;},
        hover_tip: 'Filter by item type (kanji, vocabulary)'
	};

    //===================================================================
    var jlpt_level_filter = {
        type: 'multi',
        label: 'JLPT Level',
        default: [],
        content: {N5:'N5',N4:'N4',N3:'N3',N2:'N2',N1:'N1'},
        filter_func: function(filter_value, item){return filter_value[item.data.jlpt_level] === true;},
        hover_tip: 'Filter by JLPT Level (N5, N4, N3, N2, N1)'
	};

    //===================================================================
    function startup() {
        wkof.ItemData.registry.sources.jlpt_items = {
            description:"JLPT",
            fetcher:jlpt_fetcher,
            filters:{
                item_type:item_type_filter,
                jlpt_level:jlpt_level_filter,
            },
            options:{}
        };
    }

})(window.jlpt_items);

(ping: @seanblue)

1 Like

Hello, I’m curious if this script is only meant to be used on desktop(or maybe my screen is just too small)
But I can’t use the script properly on mobile(I use Firefox) , it comes up like this and I can’t zoom out on it.


I wonder if there is a way to fix this.
Thank you.

It wasn’t designed with mobile in mind, partly because I don’t think there was a way to run scripts on mobile back when it was written.

I’m sure some CSS changes could improve it, but it really needs to be wide enough to handle some fairly long vocabulary, so doing landscape mode would be recommended… though I’m not sure how well that would do with the onscreen keyboard :thinking:.

I don’t have time to work on it, but if you can talk someone into coming up with a good solution for mobile, I’d be happy to integrate the changes into the script.

1 Like

Thank you for making this! It’s definitely helpful to brush up on the items that have been moved to apprentice so I can get better at them :hugs:

1 Like

Thanks so much for posting this! I am gonna mess around with it, although a lack of SRS support is a bit of a dealbreaker for my uses… :frowning:

What settings do you recommend to use if you want to get rid of a lot of leeches that doesn’t want to go away from Guru?

I created a preset that shows Guru-only elements with Leech Training 1 and nothing else. I do 3 or 4 rounds (20x each) every day, but maybe there something else I can do to maximize what I’m doing now?

Your question may get more response in a leech thread (if you haven’t already) since I don’t think many people follow this thread.

When I wrote Self-Study Quiz, my method was to review all items on a new level until I could answer all of them without hesitation (always consistently reciting reading-then-meaning in my head, regardless of which question was being asked, because your brain benefits from consistent sequences). Then, I also reviewed one previous level per day on a rotating schedule. It’s a lot more work than just focusing on leeches, but it worked for me. I didn’t have any leeches, but I’m also blessed with an excellent memory.

As I said, I would get a few more perspectives from people in a leech thread. Then just try a few things to see what works for you.

Good luck, and happy kanji’ing! :slight_smile:

Report: Besides that blank screen on top, also, after I close Self Study Quiz, I can’t scroll down. Temporary solution is close that tab after I do self study quiz, open a new one for WK.

Thank you, I’ll try a couple of things to see what works for me and eventually I’ll search a proper thread to ask these questions!

May I just say thank you for writing Self-Study Quiz? I’m new, so I’m still getting used to the pace of lessons and reviews, but I figured a little extra review never hurt, so I installed the script. It seems very useful!

4 Likes

May I request an option to learn only lone Kanji?
(I forgot if it’s On or Kun honestly. The ones you get with a pink frame)
I struggle remembering those the most.