Study plans¶
A plan is an ordered set of blocks. Each block holds a fixed list of questions and, optionally, reading to go with them.
StudyPlan.kind is set or mixed.
Membership is snapshotted¶
A block's question_ids are written once, when the plan is built. A block is
not a live filter. A plan built in March is the same plan in June, whatever
has been added to the bank since — which is the point of assigning one.
Starting a block¶
builds — or reuses, per learner — a saved test from the block's question ids, restricted to what that learner is allowed to see.
Progress is one row per block per learner, carrying the quiz it was sat as and when it was completed. It is marked complete automatically when the backing attempt is submitted, handed in, or auto-closed by the clock. Nothing asks the learner to tick it off.
Reading progress is tracked separately, per block-article link, and is reversible:
Plans built from a blueprint¶
POST /study-plans/from-blueprint (moderator-only) builds a plan from an
exam's published blueprint weights, in one of two shapes:
| Shape | What each block is | For |
|---|---|---|
papers |
A miniature of the real exam, drawn to the board's weights. No question repeats across blocks. | Rehearsal |
domains |
One block per content domain, sized in proportion to its weight. Every domain gets at least one block. | Working through a subject |
See Exams and blueprints.
Plans are not deleted¶
A database event listener refuses deletion through every path except the one
explicit admin route. Retire a plan by setting is_published = 0 instead —
somebody may be halfway through it.