I've just completed the "session scheduler", which schedules the order of cards in the current review session. For pseudocode, it looks a bit like this:
fun schedule(card, wasCorrect) {
if (!wasCorrect) {
studyQueue.add(1, card) // Wrong answer, re-schedule it after the next card
streaks[card] = 0
} else {
if (card !in streaks) {
return // We got the card correct first try! No more reviews needed
}
if (streaks[card] + 1 >= 3) {
return // We got the answer right three times in a row! No more reviewing it
}
studyQueue.add(2 + streaks[card] * 2, card)
streaks[card] += 1
}
}
As you can see, answering a card wrong will re-schedule it again immediately after the next card. Answering correctly will push your next review out further, with each correct answer pushing your review time further down the list. Three correct reviews in a row will "finish" a card for that review session.
Now that short term (single review session) card scheduling is finished, next up is to figure out, for each card, how far in the future we should schedule it's next scheduled review. I'm thinking about implementing a modified version of the Leitner system for this!