pdf-quiz-generator/backend/scripts
Daniel 5c4823d9a4 feat: exams are a group you can build, with the board's own blueprint
Four gaps, one change.

Articles could not belong to an exam at all — an article reached one only
by inference through its category, which cannot say that the same article
belongs to a basic-science step and a clinical one showing different
views in each. article_exam_links says whether it is in the group;
Exam.article_views already decided what is shown once you are there.

POST /exams/ wrote name, slug, sort order and active, and silently
dropped family, description and article views, so a new objective landed
in "Other" showing everything whatever was asked for. It writes what it
is given now, and PATCH can change it afterwards.

Membership was one link row at a time, which nobody would do for three
thousand questions. POST /exams/{id}/assign takes whole topics with
everything beneath them — questions and articles both — and is
idempotent, so widening a selection and running it again adds only what
is new.

And the point of all of it: a real paper is not a uniform draw. The ABP
publishes that 12% of a general paediatrics exam is preventive care and
2% is rheumatology; forty questions drawn evenly is forty coin flips.
exam_blueprints holds a board's published outline — its own numbering,
its headings, its weights — and blueprint_category_links maps it onto
our taxonomy rather than bending the tree to fit, because their outline
is arranged for examining and ours for studying.

The sampler uses largest-remainder, so twenty-four percentages still come
to forty questions, and a domain that cannot supply its share gives the
shortfall back to be spread over those that can — the paper keeps its
length and loses only accuracy, and the working is returned so the
shortfall is visible rather than silent.

Seeded from the ABP General Pediatrics Content Outline (Oct 2024):
structure and published weights only, no exam material. 120 lines, 22 of
24 domains mapped; Psychosocial Issues and Child Abuse and Neglect have
no category of ours and are reported rather than hidden.

Creating an objective is now an administrator's rather than a
moderator's: it appears in everyone's picker and scopes the whole bank,
which is site configuration, and it sits with the other site switches a
moderator cannot reach.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TqXevQJhxFrM7jJg82cgZN
2026-09-11 20:27:48 +02:00
..
abp-2024-outline.json feat: exams are a group you can build, with the board's own blueprint 2026-09-11 20:27:48 +02:00
article_pipeline.py feat: a study objective that changes what you see; purge unused figures 2026-09-11 02:47:01 +02:00
backfill_question_figures.py feat: figures as records, question-centred dashboard, fewer hints mid-quiz 2026-09-11 03:18:49 +02:00
backfill_section_index.py feat: real organ systems, symptoms grouped by system, and admin taxonomy CRUD 2026-09-10 10:44:39 +02:00
bind_exam_tags.py feat: exam-scoped disciplines and exam-scoped facet counts 2026-09-10 02:48:34 +02:00
classify_unfiled_questions.py feat: MinIO-backed media libraries, and file the last 316 questions 2026-09-10 06:45:22 +02:00
convert_tags_to_categories.py refactor: name the study plans ourselves, and stop reserving 64k tokens a call 2026-09-11 01:41:18 +02:00
fix_lab_formatting.py refactor: name the study plans ourselves, and stop reserving 64k tokens a call 2026-09-11 01:41:18 +02:00
generate_articles.py feat: article CMS, three reading views, and articles written from the library 2026-09-10 17:13:07 +02:00
index_question_images.py feat: every figure in the image bank, bigger editing boxes, footer links 2026-09-11 02:32:06 +02:00
link_articles.py feat: settings as places with addresses; repair nested cross-references 2026-09-11 12:46:13 +02:00
mdm_pass.py fix: 'No therapy is required' is an answer, not a placeholder 2026-09-11 13:58:02 +02:00
merge_duplicate_conditions.py feat: nest the system tree and give each condition one home 2026-09-10 04:26:48 +02:00
migrate_uploads_to_s3.py feat: serve uploads through storage, and move all 3,852 files to MinIO 2026-09-10 10:23:34 +02:00
nest_symptoms_by_system.py feat: real organ systems, symptoms grouped by system, and admin taxonomy CRUD 2026-09-10 10:44:39 +02:00
nest_systems.py feat: nest the system tree and give each condition one home 2026-09-10 04:26:48 +02:00
number_board_reviews.py feat: session analysis after a quiz, and a merged TODO for the rest 2026-09-11 03:07:05 +02:00
promote_primary_categories.py feat: promote primary categories from system down to condition 2026-09-10 04:32:55 +02:00
prose_pass.py fix: the imperative detector only ever saw sentence starts 2026-09-11 13:16:05 +02:00
purge_unused_figures.py feat: a study objective that changes what you see; purge unused figures 2026-09-11 02:47:01 +02:00
rename_study_plans.py refactor: name the study plans ourselves, and stop reserving 64k tokens a call 2026-09-11 01:41:18 +02:00
retitle_figures.py feat: cross-link the articles, and strip what the analysis page replaced 2026-09-11 03:44:44 +02:00
rollback_tag_category_conversion.py
sanitize_categories.py fix: category tree cleanup, mixed-content redirect, and category page clarity 2026-09-10 04:09:18 +02:00
sanitize_tags.py feat: facet filters on the question bank, category page, sanitised tags 2026-09-10 00:13:31 +02:00
seed_abp_blueprint.py feat: exams are a group you can build, with the board's own blueprint 2026-09-11 20:27:48 +02:00
seed_illustrations.py feat: one Markdown renderer for the whole site, with LaTeX and highlights intact 2026-09-10 18:12:37 +02:00
seed_lab_references.py
seed_sample_content.py
seed_showcase_articles.py
seed_study_plans.py feat: study-plan blocks as modules, sessions that know their block 2026-09-11 04:31:21 +02:00
tag_source_quizzes.py refactor: name the study plans ourselves, and stop reserving 64k tokens a call 2026-09-11 01:41:18 +02:00
triage_question_images.py refactor: name the study plans ourselves, and stop reserving 64k tokens a call 2026-09-11 01:41:18 +02:00