essai × talentcoop · math QB · 23 Apr 2026
Math P1–S3 Question Bank — Build Checklist
Exhaustive task breakdown · MC + fill-in + short-answer · Variety and difficulty handles · All 110 curriculum units
110
P1–S3 curriculum units
~550
Templates to build (avg 5 per unit)
~1,100
Target questions (2 per template)
33
Diagram units (SVG only)
15–20
Est. dev days to full P1–S3
Milestone Plan
Task Definition (per unit)
Every unit gets 8 build tasks. A unit is "production-grade" when all 8 are green. Same standard as the live DSE14/DSE17/P6 bank.
- Map — Competency map JSON: skills DAG, exam-point examples, past paper count, generator constraints
- Gen-MC — Generator templates for MC (4 options, error-modeled distractors) — 5–7 templates per unit
- Traps — 100% trap builders: every template has error-modeled distractors in
traps.js
- Fill-in — Same generator, short-answer output mode (no options, just answer) — 1-day cross-cutting build switch
- Solutions — Step-by-step solution builder in
solutions.js
- ZH — Chinese stems + solutions + trap analysis in
chinese.js
- Verify — Independent numeric verifier in
verify_answers.js
- Diagram — SVG generator (only for units with
needsDiagram: true)
Variety Handle
Three levers for question variety
UPEP corpus as variety ground truth: the 14,597 UPEP records cover S1–S3 topics with high density. Before writing templates, scan the corpus for each unit to see what question patterns actually appear most. This prevents building templates for patterns students never see.
Difficulty Handle
3-tier difficulty system
Rules live in generators/difficulty.js. Overrides per template. Constraint: no tier > 85% of a topic's total questions. The UPEP distribution confirms this target: avg ~43% LV1 / 43% LV2 / 6% LV3 / 8% MC per book.
Empirical UPEP distribution (6 books): 2_LV1 ≈ 43%, 2_LV2 ≈ 43%, 2_LV3 ≈ 6%, 2_MC ≈ 8%. Our generator targets should mirror this — don't over-index on MC (which UPEP uses sparingly) or over-produce advanced questions.
M1 S1–S3 Generators — 31 units
Data available: TSA 2025 S3 exam-points JSON (80+ questions mapped) · UPEP 14,597 records with curriculum codes · EdCity STAR 11,826 records with topic labels · curriculum.json 31 units with objectives
Generator file plan: generators/s1s3_number_algebra.js · generators/s1s3_geometry.js · generators/s1s3_mensuration.js · generators/s1s3_data.js · generators/s1s3_coord_trig.js
Number and Algebra (units 1–14)
| Unit | Topic | Strand | Types | Map | Gen-MC | Traps | Fill-in | Solve | ZH | Verify | Diag |
| 1 | Basic computation (integers, HCF/LCM) | N&A | MC+fill-in | todo | todo | todo | todo | todo | todo | todo | n/a |
| 2 | Directed numbers | N&A | MC+fill-in+word | todo | todo | todo | todo | todo | todo | todo | n/a |
| 3 | Approx values + numerical estimation | N&A | MC+fill-in | todo | todo | todo | todo | todo | todo | todo | n/a |
| 4 | Rational and irrational numbers | N&A | MC+fill-in | todo | todo | todo | todo | todo | todo | todo | n/a |
| 5 | Using percentages | N&A | MC+fill-in+word | todo | todo | todo | todo | todo | todo | todo | n/a |
| 6 | Rates, ratios and proportions | N&A | MC+fill-in+word | todo | todo | todo | todo | todo | todo | todo | n/a |
| 7 | Algebraic expressions | N&A | MC+fill-in | todo | todo | todo | todo | todo | todo | todo | n/a |
| 8 | Linear equations in one unknown | N&A | MC+fill-in+word | todo | todo | todo | todo | todo | todo | todo | n/a |
| 9 | Linear equations in two unknowns (simultaneous) | N&A | MC+fill-in+word | todo | todo | todo | todo | todo | todo | todo | n/a |
| 10 | Laws of integral indices | N&A | MC+fill-in | todo | todo | todo | todo | todo | todo | todo | n/a |
| 11 | Polynomials | N&A | MC+fill-in | todo | todo | todo | todo | todo | todo | todo | n/a |
| 12 | Identities | N&A | MC+fill-in | todo | todo | todo | todo | todo | todo | todo | n/a |
| 13 | Formulae (substitution + manipulation) | N&A | MC+fill-in+word | todo | todo | todo | todo | todo | todo | todo | n/a |
| 14 | Linear inequalities in one unknown | N&A | MC+fill-in+word | todo | todo | todo | todo | todo | todo | todo | n/a |
Measures, Shape and Space (units 15–27)
| Unit | Topic | Strand | Types | Map | Gen-MC | Traps | Fill-in | Solve | ZH | Verify | Diag |
| 15 | Errors in measurement | MSS | MC+fill-in+word | todo | todo | todo | todo | todo | todo | todo | n/a |
| 16 | Arc lengths + areas of sectors | MSS | MC+fill-in+word | todo | todo | todo | todo | todo | todo | todo | n/a |
| 17 | 3-D figures (identification + nets) | MSS | MC 🖼 | todo | todo | todo | n/a | todo | todo | todo | static SVG bank |
| 18 | Mensuration (surface area, volume) | MSS | MC+fill-in+word | todo | todo | todo | todo | todo | todo | todo | n/a |
| 19 | Angles and parallel lines | MSS | MC+fill-in 🖼 | todo | todo | todo | todo | todo | todo | todo | SVG angles |
| 20 | Polygons (interior angles, sum) | MSS | MC+fill-in | todo | todo | todo | todo | todo | todo | todo | n/a |
| 21 | Congruent triangles | MSS | MC+fill-in 🖼 | todo | todo | todo | todo | todo | todo | todo | SVG triangle pairs |
| 22 | Similar triangles | MSS | MC+fill-in 🖼 | todo | todo | todo | todo | todo | todo | todo | SVG triangle pairs |
| 23 | Quadrilaterals (properties) | MSS | MC+fill-in 🖼 | todo | todo | todo | todo | todo | todo | todo | SVG quad |
| 24 | Centres of triangles (centroid, incircle etc) | MSS | MC+fill-in 🖼 | todo | todo | todo | todo | todo | todo | todo | SVG triangle+centre |
| 25 | Pythagoras' theorem | MSS | MC+fill-in+word | todo | todo | todo | todo | todo | todo | todo | extends 2d.js |
| 26 | Rectangular coordinate system (distance, mid-pt, slope) | MSS | MC+fill-in+word | todo | todo | todo | todo | todo | todo | todo | extends DSE10 |
| 27 | Trigonometry (sin/cos/tan, right triangle) | MSS | MC+fill-in+word | todo | todo | todo | todo | todo | todo | todo | extends 2d.js |
Data Handling (units 28–31)
| Unit | Topic | Strand | Types | Map | Gen-MC | Traps | Fill-in | Solve | ZH | Verify | Diag |
| 28 | Organisation of data (tally, freq tables) | Data | MC+fill-in | todo | todo | todo | todo | todo | todo | todo | n/a |
| 29 | Presentation of data (bar, pie, broken-line) | Data | MC+fill-in 🖼 | todo | todo | todo | todo | todo | todo | todo | extends p6_data.js |
| 30 | Measures of central tendency (mean/median/mode) | Data | MC+fill-in+word | todo | todo | todo | todo | todo | todo | todo | n/a |
| 31 | Probability (basic, equally likely) | Data | MC+fill-in+word | todo | todo | todo | todo | todo | todo | todo | n/a |
M2 P6 Gap-Close — 5 diagram items
P6 generators are live (54 templates, 100 Qs). Gap to Grade A: add diagrams for 5 topic types. These are quick-win SVG additions.
| Topic | Gap | Diagram type | Effort |
| p6-angles | No protractor/angle diagram | SVG angle arc on labelled lines | S |
| p6-circles | Circle geometry (arc, chord) | Extend p6_circles.js | S |
| p6-volume-composite | No 3D composite solid | SVG 2D cross-section of composite solid | M |
| p6-symmetry | No symmetry line on shape | SVG shape with dashed axis | S |
| p6-stats-misuse | No misleading chart | SVG bar chart with broken axis | S |
SA Short-Answer / Fill-in Mode (cross-cutting, 1 day)
What this is: Every existing MC generator can emit a fill-in version — same stem, same answer, no options. One
--mode fill-in flag in
generate_questions.js + a display-mode flag in the DB schema (
question_mode: 'mc' | 'fill-in'). No new templates needed.
- Change
generate_questions.js COVERAGE_TARGETS to accept mode: 'mc' | 'fill-in' | 'both'
- Skip
mc_options.js call when mode === 'fill-in'
- Add
question_mode column to dbo.math_questions (migration + seed update)
- Frontend filter: show options when
question_mode === 'mc', show blank answer input when fill-in
- Applies to all existing 300 Qs + all future Qs immediately
M3 P4–P5 Generators — 26 units
Depends on M1 for pattern validation. P6 generators already cover the upper end (percentages, equations, averages, circles). P4–P5 fills the bridge.
| Unit | Grade | Topic | Types | Diag |
| 4N1–4N2 | P4 | Multiplication II + Division II (long mult/div) | MC+fill-in+word | n/a |
| 4N3–4N4 | P4 | Multiples + factors / HCF + LCM | MC+fill-in | n/a |
| 4N5 | P4 | Four arithmetic operations II (brackets, order) | MC+fill-in+word | n/a |
| 4N6 | P4 | Fractions II (add/sub, mixed) | MC+fill-in+word | n/a |
| 4N7–4N8 | P4 | Decimals I + II (place value, ops) | MC+fill-in+word | n/a |
| 4M1–4M2 | P4 | Perimeter I + Area I | MC+fill-in+word | n/a |
| 4S1–4S2 | P4 | Quadrilaterals III + Dissecting shapes | MC 🖼 | SVG shapes |
| 4S3 | P4 | Directions + positions III (4+8 compass, coordinates) | MC | n/a |
| 4D1 | P4 | Bar charts II (grouped) | MC+fill-in 🖼 | extends p6_data.js |
| 5N1 | P5 | Multi-digit numbers (millions) | MC+fill-in | n/a |
| 5N2–5N5 | P5 | Fractions III–V (mult, div, mixed ops) | MC+fill-in+word | n/a |
| 5N4 | P5 | Decimals III (mult/div by powers of 10) | MC+fill-in+word | n/a |
| 5A1–5A2 | P5 | Elementary algebra + Simple equations I | MC+fill-in+word | n/a |
| 5M1–5M2 | P5 | Area II (circles) + Volume I (cubes/cuboids) | MC+fill-in+word | n/a (circle = p6_circles) |
| 5S1–5S2 | P5 | Circles + 3-D shapes III | MC 🖼 | extends p6_circles.js + static bank |
| 5D1 | P5 | Bar charts III (percentage bar) | MC+fill-in 🖼 | extends p6_data.js |
M4 P1–P3 Generators — 38 units
Simplest math = fastest to build. All P1–P3 arithmetic is fully deterministic. Static SVG bank (15–20 labelled 3D-shape images) handles shape-recognition units. No TikZ needed anywhere.
| Unit | Grade | Topic | Types | Diag |
| 1N1–1N3 | P1 | Numbers to 20/100, place value | MC+fill-in | n/a |
| 1N4 | P1 | Addition + subtraction I (≤100, no carry) | MC+fill-in+word | n/a |
| 1M1–1M4 | P1 | Length (cm), Money (HK coins), Time (hr/half-hr) | MC+fill-in | n/a |
| 1S1–1S2 | P1 | 3-D shapes I + 2-D shapes (recognition) | MC 🖼 | static SVG bank |
| 1S3 | P1 | Directions + positions I (over/under/left/right) | MC | n/a |
| 2N1–2N6 | P2 | 3/4-digit numbers, add/sub II+III, mult, div | MC+fill-in+word | n/a |
| 2M1–2M3 | P2 | Length (m), Time (min/am/pm), Money (notes) | MC+fill-in | n/a |
| 2S1–2S4 | P2 | 3-D shapes II, Angles, Directions, Quadrilaterals I | MC 🖼 | static SVG bank + SVG angle |
| 2D1 | P2 | Pictograms | MC+fill-in 🖼 | SVG pictogram |
| 3N1–3N5 | P3 | 5-digit numbers, mult I, div I, 4-ops I, fractions I | MC+fill-in+word | n/a (fractions: SVG bar) |
| 3M1–3M5 | P3 | Length (km/mm), Time (s/24h), Capacity (L/mL), Weight (kg/g) | MC+fill-in | n/a |
| 3S1–3S2 | P3 | Quadrilaterals II + Triangles | MC 🖼 | SVG shapes |
| 3D1 | P3 | Bar charts I | MC+fill-in 🖼 | extends p6_data.js |
M5 Long-Q / DSE Section B — Flag for Leslie
Feasibility: ~65% of DSE Section B patterns are algorithmically generatable. The remaining ~35% (multi-theorem geometric proof, open algebraic reasoning) hit the limits of pure templates.
Schema change needed: add
parts: [{stem, answer, marks}] array to question record +
marks_total field.