[Userscript] Self-Study Quiz

Hmm… smells like a meta userscript opportunity. :grin:

Yeah… Back when I originally designed the framework, I designed it with a means for someone to write a ‘Sync Settings’ script, which would do exactly what I did above, but with some sort of server to optionally store people’s settings if they wanted.

I knew I wouldn’t have time to implement it myself, though.

1 Like

Thank you very much @rfindley !
That will be very helpful!

1 Like

Challenge accepted. <laugh>

I’m still deep in the weeds with a crazy amount of recent learnings as I work on the Ganbarometer でぶ edition.

I’ve figured out how to write svelte components for WK userscripts, using jest to test and rollup to package as an iife for tampermonkey, as well as msw to mock the API/wkof interactions and @mswjs/data with faker to flesh out the mocks for testing. Oh, and all while developing in typescript with live updates to my browser. All of that is as insane and unnecessary to write a simple little userscript as it sounds.

I never intended to learn so much about front-end development, but, sheesh, everything about it is a hellaciously tempting loose thread in the biggest sweater imaginable.

Anyway, something simple like a sync-setting script will eventually be a nice change of pace.


Nice! I’m glad to see someone playing with Svelte. I’m hoping to spend more time with it on my next web-oriented project. (Whenever that may be…)

If you do build a Sync Settings script, I would love to see your workflow, and especially the hot reloading. Time travel is also fantastic in certain use-cases, though I don’t see that being useful for something as simple as Sync Settings.


By the way you didn’t accidentally dump this into a Github repo somewhere? This all sounds very nice, especially the testing part, but I‘d be way too lazy busy to put this all together myself :sweat_smile:


“Hot” is a bit of an overstatement, but at least I don’t need to copy/paste code around any more. It turned out to be astonishingly easy. I just had to add this userscript to tampermonkey:

// ==UserScript==
// @name        ganbarometer-svelte -> dev
// @description Svelte version of the GanbarOmeter for Wanikani
// @namespace   https://github.com/wrex/
// @version     0.0.1
// @homepage    https://github.com/wrex/ganbarometer-svelte#readme
// @author      Rex Walters -- rw [at] pobox.com
// @license     MIT-0
// @resource    css file:///Users/rex/Public/repos/ganbarometer-svelte/dist/bundle.css
// @include     /^https://(www|preview).wanikani.com/(dashboard)?$/
// @connect     github.com
// @run-at      document-idle
// @require     file:///Users/rex/Public/repos/ganbarometer-svelte/dist/bundle.js
// @grant       GM_addStyle
// @grant       GM_getResourceText
// @grant       GM_xmlhttpRequest
// ==/UserScript==

That’s all, just the header (the actual iife is in the bundle.js file).

Rollup watches my source tree for changes, so whenever I save a file it rebuilds bundle.js. I still need to refresh the browser window manually, but it had never occurred to me to use file: urls for dev work on scripts.

And svelte is REALLY nice. It feels right to compile. I’m still uncomfortable with all the magic happening in vscode and various npm packages, but it’s very cool to develop with TDD an see the individual tests go red and green right in my editor on the appropriate lines.


Still very much in active development, but you can see the current mess at GitHub - wrex/ganbarometer-svelte

As someone once said, it’s not how WELL the dog sings…


Thanks, will look into it :slight_smile:

Oh, by the way, I can HIGHLY recommend this course: https://www.udemy.com/course/svelte-with-test-driven-development/

The other big missing piece was this: GitHub - lpshanley/tampermonkey-svelte: Tampermonkey template build with the use of svelte in mind!


Ah, thanks, I‘m a happy React dev though :sweat_smile:
Also, I took a quick look at svelte.dev but the little that I saw seemed to hint that they are quite fond of mutable state which is the exact opposite of my preferred coding style :woman_shrugging:
But not going to start a war here, no worries. It’s great that we have so many alternatives available nowadays!

1 Like

Nothing wrong with React, of course. Jest, Rollup, and MSW and all the other pieces should work just fine in that environment. The resources I linked to are pretty svelte-specific but I’m pretty sure all the techniques should still apply.

I’m still weirded out that immutability (and types!) aren’t enforced by the language at compile time. It’s ALL new to me…

[Also, I think mutability is a by-practice thing with svelte, too: see the immutable option at Special elements / <svelte:options> • Svelte Tutorial .]

1 Like

Oh interesting! I only saw the mention of being able to use x=x+1 in the code without the need for useState or the like, and of their auto-binding (which I thought everybody learned with the original Angular that it’s a bad idea, but maybe it’s something different here, or history has come to repeat itself?). Hmmm, anyways :upside_down_face:

1 Like

I’m also not interested in a war, of course… I don’t care one way or the other. But I admit to being ignorant of the need for and/or advantage of hard immutability. It probably stems from me being a long-time C/C++ programmer living in the embedded systems world. We don’t have many guiderails, so programming styles (as opposed to language features) and programming habits tend to be a large part of our coding safety.

But also, as a low-level programmer (i.e. close to the hardware), the idea of copying immutable objects all the time seems like wasted CPU cycles… but then, I’m used to working in resource-limited environments, so I always have to be aware of what the compiler is likely doing behind the scenes. (I know languages with immutability sometimes use tricks to prevent duplication in memory, but that seems like a lot of checking/tracking that is offloaded from the designer to the runtime.)

Anyway… I guess I’m just feeling old :slight_smile:


Oh, I can totally see that you have very different needs when you’re working with embedded devices and stuff - you probably want to control each bit and want to know exactly when it gets updated :slight_smile:

The beauty of immutability (for me at least) is that I don’t need to keep track of things that change. I can simply see when changes happen, because modified data gets returned from a function. I don’t have to guess what the current state of this or that mutable variable is. Especially when it comes to (pseudo-)parallel code execution, e.g. in the modern multikernel processor architectures, that’s a big win. Given the same arguments, the return value is always the same. Of course, it’s also possible to write good code that uses mutability, but that’s a tad harder… To put it in your words, immutability patterns lead to coding safety.
(I vividly remember how early on in my career I wanted to analyze a given piece of software, a Java class of about 800 loc, that would make heavy use of an array of data. The code would fill the array, read some parts of it back out again, use the data to update other parts, and that several times. Highly convoluted mathematical aberrations. Of course there was a subclass involved which did not make things any clearer… I don’t remember exactly, but I don’t think I could figure out all the edge cases in the code. :roll_eyes:)

And yes, in order to leverage this effectively, you need compilers that understand immutability and that can work with it. The big advantage is that whenever data is immutable, it’s automatically shareable (because it will remain the same until the process dies or until it gets garbage collected). That’s how compilers of functional languages can make effective use of data structures. E.g. if you think of lists, if you have a list [A, B, C] then this can be represented as a linked list A → B → C. If you now want to drop the first element of the list, you can just return a pointer to the second element, done. No need to copy anything. If you want to append an element to the front of the list, you can just create a new element that points to the list we already have. Now lists happen to be one of the main data types in functional languages, so it’s understandable that they are not as redundant as it might feel, I hope.
On the other hand, I once tried to implement such a functional pattern in Java, and while it was ok for small amounts of data, of course it did not work any more as soon as the data got too much, because Java of course would copy all the lists and stuff because it doesn’t know about immutability. (Or at least it didn’t, back in the day.)

So yeah, I’m fully with you, one needs to adapt the way of coding to the task at hand, and one needs to pick the right tool (i.e. programming language) on top of that.

1 Like

Feature request:

During reviews with the standard WK user interface, the “f” key displays the correct answer after a miss.

Would it be possible for the self-study quiz to accept the “f” key as well as F1 to display the correct answer? I realize this only makes sense after the user has provided an answer, because the “f” must be interpreted as part of the answer otherwise.


During my daily reviews, whenever I provide an incorrect answer I hit the “f” key to display the correct answer to improve my memory.

Several months ago I started using the Wanikani Item Inspector every day before my reviews to launch a self-study quiz for just the kanji items currently in Apprentice-1 or Apprentice-2 stages. I repeat the quiz multiple times until I score 100% before starting my real reviews. I don’t feel this is “cheating” since I only perform reviews once per-day (and thus miss the 8 hour intervals anyway).

This works extremely well for me in practice — I get lots of “extra” reviews for what I usually find most difficult to memorize: recently introduced kanji.

Currently F1 displays the correct answer for an item during a self-study quiz. The F1 key works before or after providing an answer (correct or incorrect).

Remembering to type F1 during my self-study quizzes when I miss an item, and “f” during an actual review is creating some mental friction. It would be nice if I could use the same key for both.

@rfindley Amazing script!!

Just one fairly frequent potential bug that I’m coming across: when you get an answer nearly right and it tells you that it was slightly off, it then doesn’t let you try again, just showing the text box as locked.

Surely, as with the main WaniKani reviews, it should let you modify your answer and try submitting again? (like the scripts already does with for example the “looking for reading, not the meaning”)
Or am I misunderstanding its purpose?

If this is a bug/unintended, it would be great if you could fix it if you can find the time!
Thanks :slight_smile:

Just press Backspace and SSQ will erase your old answer and let you type your answer again.

This works with all answers, not just the ones that are slightly off.


This script is awesome I can test myself on items of a particular level. It seems I already forgot some of the items on wanikani especially vocabulary.