Let me try and help by providing some more context and guidance.
I want to start with the caveat that this by no means constitutes documentation or provides any guarantee about how the code may or may not work in the future.
Firstly as I am sure you are aware we use Turbo and Stimulus (aka Hotwire) to power most of the pages in Wanikani. Not all pages have migrated to this architecture (namely the dashboard) but they will. In particular you probably want to pay attention to the Turbo events (e.g. turbo:load
or turbo:before-render
would probably be useful). These events will let you know when the page has / is going to change in the instance where it is not a full page reload.
As you have discovered there are number of events that I use to control different aspects of the app. Rather than have you guess what they do and when they fire, I will just tell you in the list below:
- audioWillPlay - Sent when the audio for a subject will play. I use this to stop any other playing audio. You should consider this for internal use only.
- willShowNextQuestion - This event fires right before the question changes. It is used by multiple components to change display states, and also by the main quiz input to set the current question and subject.
- didChangeSRS - This is fired after a subject is completed to allow the SRS indicator that pops up in reviews to show up. You should consider this for internal use only.
- didUpdateUserSynonyms - I keep a dictionary of synonyms for each of the subjects that is in the current review queue. Historically the synonyms were mixed in with subjects but this impacts cache-ability so I now keep the dictionary separate. If you open up the item info for a subject and add or remove a synonym the dictionary is updated so that the next time you answer the question your new synoynm is used (or not if you deleted it). You should consider this for internal use only.
- registerWrapUpObserver - This event is fired when you click on the wrap up button. You should consider this for internal use only.
- didAnswerQuestion - This event is fired after the answer checking is done and is used to power things like the autoplaying of audio, or enabling the item info button.
- didCompleteSubject - This is fired when the subject is completed so the statistics at the top of the page can update.
- updateQuizProgress - This event is used to power the progress bar at the top of the page. You should consider this for internal use only.
- connectionTimeout - this is fired when the client can’t send the subject results to the server (after a number of retires) and allows the timeout modal to show up. You should consider this for internal use only.
The 2 events that I think will be most useful to you are willShowNextQuestion and didAnswerQuestion.
Next it seems that the queue ordering (and reordering) is a popular topic. In order (no pun intended) to make this easier to understand it is probably helpful for you know a bit more about how it works (and how I would approach such a task)
The whole queue is managed by the HTML element with the id quiz-queue
. This queue element is picked up by a stimulus controller which interprets the internal data and data attributes as follows:
- The script tag with
data-quiz-queue-target="subjects"
contains a json string for the first (up to) 100 subjects preloaded onto the page. - The script tag with
data-quiz-queue-target="subjectIds"
contains a json string for the entire list of subject ids for the current quiz. This is used for extra study and for lesson quizzes (not for reviews) - The script tag with
data-quiz-queue-target="subjectIdsWithSRS"
contains a json string for the entire list of subject ids and current SRS (Spaced Repetition System) levels represented as an array of tuple[[id, srs], [id, srs], ...]
. This is used for reviews. - The data attribute
data-quiz-queue-items-url-value
is the URL where additional subjects are fetched from when the backlog queue is running low - The data attribute
data-quiz-queue-completion-url-value
is the URL where the subject results are sent - The data attribute
data-quiz-queue-done-url-value
is the URL that will be visited once the review is complete. - The data attribute
data-quiz-queue-complete-subjects-in-order-value
is a boolean set to"true"
when you want to complete each subject in the order of the given queue (both reading and meaning are answered before moving on). This is used in extra study. - The data attribute
data-quiz-queue-question-order-value
can be set to eitherreadingFirst
ormeaningFirst
and will override the random question selection with the given preference. - there is also an HTML template for the done modal that shows up on lesson pages.
Currently there is no way to set the question order (e.g. reading first or meaning first), however I don’t feel that you can properly control the queue without this so I will add this in tomorrow and report back with more info on how you can set the value.
So with all this above information, I would take the following approach to reordering the queue.
- get the queue DOM node -
queueEl = document.getElementById('quiz-queue')
- grab a reference to the queues parent -
parentEl = queueEl.parentElement
- remove the queueEl from the DOM -
queueEl.remove()
- clone the queueEl -
cloneEl = queueEl.cloneNode(true)
- manipulate the queues however you need on the cloned node
- reattach the clone node (after reordering is done) -
parentEl.appendChild(cloneEl)
The rationale for this approach has to do with the order that the stimulus lifecycle callbacks fire. I have to do most of the work in setting up the queue in the initialise callback of the stimulus controller as the queue needs to be setup before the quiz input detects it as an outlet. Because of the way lifecycle callbacks work with stimulus I can’t put the queue setup logic in the connect callback which necessitates the need to clone the DOM node that I mentioned above. When you attach the clone back to the DOM, my code will pick this up and create the new queue based on your reorder logic and fire the willShowNextQuestion event which should update the UI. Note that if you changed the order where the first subject is no longer the first subject, the user will see the subject change on there screen which may be a little jarring, so you might want to consider adding something to indicate loading/reordering that makes it a little more user friendly (or not, it is up to you).
Sorry this is a bit of a long one, but hopefully it is helpful and you find it useful. I will update you tomorrow once I have made the question ordering configurable.
Updated:
I have now implemented the ability to specify the question order and updated the attributes list for the quiz-queue
above. I have also made it so that the question order can be set via a URL parameter question_order=reading_first
or question_order=meaning_first
which is there to help with setting the preferred question type for the first preloaded subject. Note the use of snake-case for the url parameter and the use camelcase for the javascript parameter used in the data attribute.