What Is It?
Queue Manipulator is a user-created library script that can be used by other userscripts. It simplifies and coordinates the manipulation of the review/lesson queue.
How Can I Use It?
Queue Manipulator can be required in your userscript:
// @require https://greasyfork.org/scripts/462049-wanikani-queue-manipulator/code/WaniKani%20Queue%20Manipulator.user.js?version=1448112
Alternatively, the end user can be instructed to install Queue Manipulator manually – similar to Open Framework. The @require
method is more comfortable for the end user, but comes with a few disadvantages:
- The
@require
meta data has to be kept up-to-date manually (I don’t plan to do many updates for Queue Manipulator, but they might be necessary every time WK changes the way it handles the queue. - The entire code of Queue Manipulator is inserted into every script that
@require
s it, which can increase the parsing time by a few milliseconds.
If Queue Manipulator is available (by @require
or by manually installing it), you can use it via the wkQueue
object in the global scope. For example:
window.wkQueue.addReorder(q => q.reverse());
The lesson manipulation functionality requires Open Framework. If only reviews are manipulated, Open Framework is not needed.
Documentation
Selectors
This library script can be used similarly to Item Info Injector, but is much simpler since there is only one selector: on()
. This selector can be used to specify on which pages your registered manipulation should be applied:
wkQueue.on("lesson, review, extraStudy").addFilter(q => q.slice(0, 5));
The available keywords are lesson, lessonQuiz, review, and extraStudy. Omitting the selector is the same as using all four keywords.
Actions
The selector chain determines when something should happen – the “action” that is appended to the end of the chain determines what should happen. The available actions are:
Action | Description |
---|---|
addTotalChange() | Intended for manipulations that add/remove/reorder subjects in the queue. |
addFilter() | Intended for manipulations that remove/reorder subjects in the queue. |
addReorder() | Intended for manipulations that reorder subjects in the queue. |
addPostprocessing() | Can be used to change the subject data that will be written into the id="quiz-queue" DOM element. |
All these functions take two arguments: a \textcolor{green}{\text{callback}} function that applies the manipulation, and an optional \textcolor{orange}{\text{settings}} object. The \textcolor{green}{\text{callback}} function will be called when needed and receives two arguments:
- an array (which is the queue)
- an object with information about the current state
The current state object only has one property: on
, which can be either "lesson"
, "lessonQuiz"
, "review"
, or "extraStudy"
. Each element of the array is an object with the following properties:
Property | Description |
---|---|
id | The WaniKani subject id of the item. |
srs | The SRS level of the item. Only available on the review page, and if the item was not added by a manipulation. |
subject | The subject as it is structured in the id="quiz-queue" DOM element. Only guaranteed to be available if the \textcolor{orange}{\text{settings}} object passed to the action contained {subject: true} . |
item | The Open Framework item as it was returned by Open Framework. Only guaranteed to be available if the \textcolor{orange}{\text{settings}} object passed to the action contained {openFramework: true} . Use openFrameworkGetItemsConfig to specify any further endpoints you need, e.g. |
Return Value
Registering an action returns an object containing a remove()
function. Calling this function unregisters the manipulation and causes the queue to be recomputed.
Other Functionality
Settings
Aside from registering manipulations, wkQueue
also offers a way to change two review settings provided by WaniKani: completeSubjectsInOrder
and questionOrder
. Setting completeSubjectsInOrder
to true
results in the same behavior as in extra study sessions: for every subject, both reading and meaning question has to be answered correctly before proceeding to the next subject. questionOrder
can be set to either meaningFirst
or readingFirst
.
For lessons, lessonBatchSize
can be used to change the batch size. To go back to the default batch size, set it to null
.
wkQueue.completeSubjectsInOrder = true;
wkQueue.questionOrder = "meaningFirst";
wkQueue.lessonBatchSize = 15;
applyManipulation()
This can be used to apply a manipulation to the current queue without causing it to be recomputed and without registering the manipulation. This means that it will only be applied once. I initially created this function with the intention to use it in my Later Crabigator userscript to push the current element to the end of the queue – it would only be a change to the current queue, and if the queue gets reordered, it does not matter that the change is lost. However, since every queue manipulation has the side effect of WaniKani forgetting all half-answered subjects, I did not end up using this function at all.
refresh()
Use this to cause the queue to be recomputed.
wkQueue.refresh();
currentLessonQueue(), currentReviewQueue()
Use these functions to retrieve the current queues. Takes the same \textcolor{orange}{\text{settings}} object as described above as an optional argument. Returns the same queue array as passed to the \textcolor{green}{\text{callback}} described before.
Example Code
Only keep kanji:
let kanjiFilter = wkQueue.addFilter(q => q.filter(i => i.subject.subject_category === `Kanji`), {subject: true});
// to remove the filter: kanjiFilter.remove();
Order by level:
let levelSort = wkQueue.on(`review,extraStudy`).addReorder(q => q.sort((i0, i1) => i0.item.data.level - i1.item.data.level), {openFramework: true});
Order by SRS level:
wkQueue.addReorder(orderBySrs, {openFramework: true, openFrameworkGetItemsConfig: "assignments"});
function orderBySrs(currentQueue) {
return currentQueue.sort((i0, i1) => i0.item.assignments.srs_stage - i1.item.assignments.srs_stage);
}
Completely replace the queue with a new queue containing the items with id 1, 2, and 3:
wkQueue.addTotalChange(() => [1, 2, 3]);
Add “こういち” as accepted reading to all vocabulary items:
wkQueue.addPostprocessing(q => q.forEach(i => {
if (i.subject.subject_category === "Vocabulary") {
i.subject.readings.push({reading: "こういち", pronunciation: {sources: []}});
}
}));
Warnings
Every time the queue is manipulated, WaniKani forgets about half-finished items. It is recommended to only register manipulations at script start and not cause any queue recomputations halfway through a review session.
Furthermore, do not store any wkQueue
properties for later access: The global wkQueue
object might get replaced by a newer version at any time – for example, if script A @require
s version 1.0, but later, Tampermonkey injects script B which @require
s version 1.2, the version 1.0 wkQueue
will get replaced (and any already registered manipulations get transferred to the version 1.2 wkQueue
). Storing a reference like const queue = window.wkQueue
should be possible since all properties of wkQueue
will redirect to the new version, but please do not try this:
let myRefreshReference = window.wkQueue.refresh;
// and somewhere else
myRefreshReference();
And one more problem I noticed with users of Item Info Injector and Queue Manipulator: if you choose to @require
the library script in your script, you should include the version number at the end of the URL, and keep it up-to-date. The default setting for Tampermonkey is to never look for updates of @require
d scripts, so it will only download the current version at the time the end user installs your script, but won’t be kept up-to-date.
Feedback and Requests
If you need additional features, ask here in this thread and I will think about adding them. Also let me know if any part of the documentation is unclear, or if the script shows some unexpected behavior. Lastly, I’m not a native English speaker, so my wording might be awkward or grammatically incorrect – feel free to also correct me on that.