One VTU logoOne VTU
All posts
EngineeringProductData

A topic you have not opened in a month still says 'Yesterday'

Daily Revision schedules reviews on a five-rung ladder and then labels them with times that cannot be right. An item untouched for a month still reads "Yesterday".

17 September 20264 min read

Daily Revision is a spaced-repetition scheduler, just a small hand-written one: five rungs at 1, 3, 7, 14 and 30 days. Finish a topic and it comes back tomorrow. Pass the review and the interval grows; fail and it shrinks. The mechanism works. The labels describing it are wrong by construction, and wrong in the way that hides the one thing a revision screen most needs to say.

The ladder

static const List<int> intervalDays = [1, 3, 7, 14, 30];

An item exists only as a side effect of finishing a topic in Update Learning. Completing a topic seeds one, due tomorrow. A pass moves the stage up one and the difficulty down one; a failure moves the stage down and the difficulty up. Difficulty is clamped to 0–10 and the stage is clamped to the ladder, so the top rung is thirty days and stays there.

The labels describe the past but are indexed by the future

The screen groups items under five headings: Yesterday, 3 days ago, 1 week ago, 2 weeks ago, 1 month ago. Those headings are indexed by stage. But stage is not how long ago you last saw the item. It is the interval of the review you have not done yet, and it only moves when you review something.

Follow that through. Seed an item today and never open the app again. Tomorrow it says Yesterday, correctly. Thirty days later, still untouched, still at stage zero, it still says Yesterday. Review a different item five seconds ago and pass it, and it immediately reads "3 days ago" — a review that has not happened yet, described in the past tense.

The five labels are true in exactly one instant per item: the moment it is precisely on time. A student who is early or late — which is all of them, most of the time — is reading a label that does not mean what it says.

The summary counts the wrong population

The five numbers at the top of the screen tell the same story. They count every item by stage, with no due-date filter at all. So it is a histogram of the ladder wearing a lateness label: the column marked "1 month ago" really means "items currently on the thirty-day rung", which includes items you reviewed last week and items you have never touched.

Next review is calculated from today, not from the due date

nextReviewOn: today.add(Duration(days: intervalDays[newStage])),

That single line is the structural problem. It anchors the next review on the day you actually reviewed, not the day the review was due. So a review done twenty-nine days late shortens nothing — it pushes the next one a full thirty days out from the late date. The ladder can never catch up, and the schedule has no way to represent being behind.

Being behind is not a cosmetic gap in a revision tool. It is the main thing the student needs to know, and this design cannot store it: there is no overdue flag, no lateness field, and no record anywhere of a missed review.

Nothing ever graduates

The top rung clamps rather than completes. There is no archived state, no graduated state, and no way to retire an item from the screen. The steady state is every topic you have ever finished, coming back every thirty days, forever. There is no cap on the day's list either, so the day after a productive weekend can show twenty due topics with no way to say "not this one".

Two quieter ones

Un-ticking a topic deletes its review history with no confirmation. The stage and the difficulty are removed, and ticking the topic again reseeds it from zero. There is no dialog, and this is the only deletion path that exists — the store's own remove and clear methods are never called by anything.

And a topic you keep failing pins itself to the top permanently. The due list sorts by difficulty first, and difficulty saturates at 10, so one chronically hard topic leads the list every single day ahead of items that are far more overdue.

Why not use a real algorithm?

Because a five-rung ladder is explainable, and a student can see why something came back today. A tuned ease factor models forgetting better and is close to impossible to explain in a settings screen. The ladder is not the problem.

Anchoring on the review date instead of the due date is, and it is a smaller change than it sounds, because it needs an overdue concept to exist first — which is precisely the thing that is missing. The labels cannot be fixed by re-indexing either, for the same reason: there is nothing recorded to index by. That is the honest state of it. The feature keeps a schedule and cannot report on it, and the reporting is the part students act on.

Keep reading

Related reading

EngineeringAndroidProduct

The card you mark as known never comes back

Flashcards has three states and no spaced-repetition scheduler. Marking a card known removes it from revision permanently, and four different screens disagree about which cards are due.

16 September 20264 min read
EngineeringAIProduct

Every rule that makes a timetable a timetable is English text in a prompt

We went looking for the scheduler in our AI study timetable and there is not one. No overlap detection, no chronological sort, no feasibility check — the plan is whatever the model returns, and the rules exist only as sentences asking it to behave.

12 September 20266 min read