Skip to content

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

POST /study-plans/blocks/{block_id}/start?mode=learning|timed

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:

POST /study-plans/reading/{link_id}/read?read=true|false

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.