Wanikani Item Lattice Script
This script brings back the previously removed item lattices, which display your SRS progress for radicals and kanji as a lattice:
The lattices are displayed at the bottom of your profile page:
This script can be installed via greasyfork.
Wanikani Open Framework is required.
I made this script a while ago and it has been sitting around for the past 2 weeks in purgatory because I can’t for the life of me get the image radicals to display. In the end I figured I’m better off publishing it with 30 or so missing file pictures than ripping my hair out trying to fix it for several weeks:
Also, your lattice will display on any user profile, which is obviously not meant to happen but I haven’t got around to fixing it since it’s a minor issue.
Finally, I never actually knew about this feature until after it was removed so I had to recreate the lattices using what few screenshots I could find. It seems like a pretty straightforward thing, but if I’ve missed any key features, please let me know.
Some things I noticed in the code:
What is this line supposed to do:
filtered_items.sort((a,b) => a.data.slug - b.data.slug);
In the line
let item_level = item_obj.assignments.srs_stage;
you try to access the
srs_stage property of
assignments without first checking if
assignments even exists (which it doesn’t if you have not unlocked the item yet). You could use optional chaining:
let item_level = item_obj.assignments?.srs_stage ?? 0;
As for the problem with the image-based radicals: I have no idea if this can be fixed. I just noticed that the method I’m using in ConfusionGuesser has also stopped working. I think it is some CORS problem, but I’m not certain.
EDIT: The reason why I’m thinking it is probably a CORS problem is that
await (await fetch(items.find(i => i.id === 1).data.character_images.url)).text()
works without a problem, but when I try to fetch it for item 8761 (which is the image-based “Stick” radical), I get a CORS error:
await (await fetch(items.find(i => i.id === 8761).data.character_images.url)).text()
So originally I was going to convert the strings to unicode, however after checking the documentation for
sort(), it turns out you can just compare the strings as is, as it converts strings automatically. I’m using the sort method here to arrange the items within each level in unicode order as @rfindley recommended a while back (however thinking about it, sorting by the character rather than the English may be closer to what WK did).
OH THAT’S WHAT THAT’S CALLED!
I spent ages trying to find what that was called since I didn’t know what it did but google kept thinking I meant ternary operators. I’ll be sure to add that later.
Oh well that’s slightly relieving knowing it may not entirely be my inability to implement svgs. I’ll look into it later maybe. I noticed the images still worked on the stats site though so I’m not entirely sure what I’ll be able to do.
And the “proper” way to sort them:
filtered_items.sort((a,b) => a.data.slug.localeCompare(b.data.slug));
Just out of curiosity, is there any difference between this method and just using the greater than operator? I know localecompare is supposedly the correct way, but I never looked into the difference
Different languages sort things differently.
In German, “a” and “ä” get sorted together.
In Spanish, “n” and “ñ” get sorted together.
['Hängt', 'Haut', 'Hüllen', 'Hubert'].sort();
// ['Haut', 'Hubert', 'Hängt', 'Hüllen']
['Hängt', 'Haut', 'Hüllen', 'Hubert'].sort((a, b) => a.localeCompare(b));
// ['Hängt', 'Haut', 'Hubert', 'Hüllen']
Oh that’s useful to know! Although is there a way to sort by the alphabetical order of a given locale in that case? Since (and Kumirei can confirm) I believe Swedish puts those accented vowels at the end of the alphabet (X, Y, Z, Å, Ä, Ö).
This may have to be something I look into later since now I’m also curious about Japanese kana order…
localeCompare() pulls your language settings from the Browser, which defaults to the OS settings.
If you need to specify the locale, you can use
Intl.Collator, which is probably used internally by
['z', 'ä', 'Z', 'a'].sort(new Intl.Collator('en-US').compare);
['z', 'ä', 'Z', 'a'].sort(new Intl.Collator('en-GB').compare);
['z', 'ä', 'Z', 'a'].sort(new Intl.Collator('de').compare);
['z', 'ä', 'Z', 'a'].sort(new Intl.Collator('sv').compare);
[Edit: Some interesting
Intl.Collator options [here] ].
Just one lil nugget left 0: