Maths practice site
From prototype to maths.malcolm.nz · written 2026-10-05 · status Step 0 Complete Step 1 Not Started · text version: mvp_plan.md
Goal: a 14-year-old in the Cook Islands passes GCSE Foundation (grade 4). Short daily practice on the topics with the most marks, with stars, worlds, reviews that keep topics fresh, and real rewards the parent sets.
Where we are: two prototypes prove the loop and the questions. Nothing is playable by him yet: no answer box, no checking, nothing saved, nothing deployed.
Plan: grow the prototype into a static site, World 1 first, live at maths.malcolm.nz. Progress stays in the browser until parent rewards need accounts (Step 4).
topics.yaml: 31 core ★, 20 extend ◆, 6 later ○1 · The core loop
Decided in zdocs/summary.txt and topics.md, and built (with simulated days) in prototype/core-loop.html.
2 · One learning path, and when each part goes live
needs entry. Full tables: zdocs/topics.md.3 · Static site first, server later
Static site, browser storage proposed
- nginx Dockerfile like
../duane, deployed with malcolm-apps - Prototype JS reused as is; live in days, not weeks
- Rules and checkers are DOM-free modules, tested with
node --test, portable to a server - Cost: progress is on one device until Step 4, then imported once
Server app from Step 1 not now
- Stack (SvelteKit or Flask) still undecided
- Logins, database and backups before he answers one real question
- Only needed for parent rewards across devices
AI-generated questions no
- Cost per question
- Wrong answers would teach wrong maths
- Code generators already cover every world
One path, not a graph
Linear path proposed
- Subtopics in world order; the next opens at 1★
- World order already respects every
needs(checked 2026-10-05, all 34) needskept in the yaml, used only by a test that guards the order- Worlds stay as sections with checkpoints and badges
- Cost: no choice of branch; a hard topic blocks the rest. Low risk: 1★ is the easy level, and reviews mix older topics in
Prerequisite graph no
needsdrives unlocks; branches open side by side- Graph logic, a harder map and more tests
- Choice he doesn't need to make
What the app looks like
zdocs/topics.yaml ──embed_topics.py──▶ app/topics-data.js
app/
generators.js gen(rng, level, ctx) → { q, a, svg? } (from prototype)
checkers.js check(answerType, given, expected) → { ok, feedback }
progress.js pure rules: path position, stars, boxes, due dates, queue, meters
store.js load/save progress (localStorage now, HTTP API in Step 4)
index.html path → run (10 questions) → result
tests/ node --test: generators, checkers, progress
Dockerfile nginx:alpine, copies app/
Checkers: the real new work
Built in the order the worlds need them. Every generator gets a test: 100 seeded questions per level, and its own answer must pass its checker.
| Answer type | First needed | How it checks |
|---|---|---|
| number | World 1 (Step 1) | Accept − or -, commas, spaces; exact compare; rounding answers must match the dp/sf asked |
| fraction | World 2 | Parse a/b, a b/c; equal value; feedback if not simplest |
| choice | World 2 | Buttons, no typing |
| expression | World 4 | Evaluate both at random values (as topics.md suggests), so term order doesn't matter; plus a form rule per subtopic: expand → no brackets, factorise → brackets, simplify → no like terms left |
| ratio, number_pair, coordinate | Worlds 5–6 | Parse a : b, (x, y); compare parts |
| table | World 6 | One box per cell, each a number check |
| standard_form | World 10 | Parse a × 10^n or aEn; require 1 ≤ a < 10 |
4 · Decisions
Already made
- UK GCSE Foundation, grade 4 target, Cook Islands context ($, metric, local places)
- Stars from passing harder levels, pass = 8/10 as prototyped (
topics.mdstill marks it "Decision needed"; confirm before Step 1) - Stars never taken away; stale topics stop counting as fresh. Review queue capped at 5
- One linear path in
topics.yamlworld order; next subtopic opens at 1★ proposed - Worlds open by checkpoint: 10 mixed questions, 8/10
Still needed
| Question | Recommendation | By |
|---|---|---|
| Stars from levels or from score? | Levels, as prototyped: 3★ means exam-ready | Step 1 |
| Laptop, tablet or phone? | Ask him. Touch needs an on-screen keypad for −, ÷, fractions, x² | Step 1 |
| Fractions in simplest form / mixed? | Accept any equivalent; show simplest as feedback | Step 2 |
| Calculator flag per level? | Yes: "no calculator" on L1–L2 number skills | Step 2 |
| Server: TypeScript or Python? | Decide at Step 4; the JS modules work with either | Step 4 |
| SQLite on a storage mount or Dokku Postgres? | SQLite: two users, one app | Step 4 |
| Parent view: rewards only, or weak spots too? | Both; weak spots come from the attempts table | Step 4 |
5 · Development steps
Each step deploys on its own and he uses it before the next one starts. Offline tests: node --test tests/. Live check: he plays on his own device and the parent looks at the result.
Step 0 · Prototypes (no deploy) Complete
- Goal
- Check the core loop and question generation feel right before building.
- Done looks like
- A clickable loop with simulated days, and generators for every world.
- Result
prototype/core-loop.html: map, worlds, levels → stars, Leitner boxes, freshness halo, review queue, checkpoints, exam-ready meter. Built ontopics.yamlviaembed_topics.py→topics-data.jsprototype/question-generator.html+generators.js: 40 generators, 3 levels each, local context, SVG for grids and distance-time graphs- Latest generator work (
generators.js,topics-data.js) is uncommitted
Step 1 · World 1 playable at maths.malcolm.nz Not Started
- Goal
- He earns a real star on his own device.
- Changes
app/from the prototype:generators.js,topics-data.js,progress.js(rules lifted fromcore-loop.html),store.js(localStorage, versioned JSON)checkers.js: number onlyindex.html: the path's first 3 nodes, World 1 (negative_numbers, order_of_operations, rounding_decimal_places) → 10 questions one at a time, answer box, right/wrong with the correct answer → result with stars- On-screen keypad only if he plays on a phone or tablet
Dockerfile(nginx:alpine, like../duane); deploy with malcolm-apps
- Done looks like
https://maths.malcolm.nzloads; he passes L1 of a World 1 topic and sees 1★; a reload keeps it.- How we verify
- Offline: number checker accepts
-4,−4,1,200,3.5; rejects3.50when 1 dp is asked - Offline: each World 1 generator × level × 100 seeds gives an answer its checker accepts
- Offline: 8/10 passes a level, 7/10 doesn't; passing L(n) sets stars to n and never lowers them
- Live: he plays one session; the parent sees the stars on his device
- Offline: number checker accepts
Step 2 · All ten worlds playable Not Started
- Goal
- The whole learning path is open to him, world by world.
- Changes
- Path through all 10 worlds; next node opens at 1★; checkpoints (10 mixed questions, 8/10 opens the next world, badge)
- Checkers: fraction, choice, expression, ratio, number_pair, coordinate, table, standard_form. SVG diagrams shown with the question
- "No calculator" label per level, if decided
- Done looks like
- Every subtopic in Worlds 1–10 can be played and passed; passing World 1's checkpoint opens World 2.
- How we verify
- Offline: every world generator × level × 100 seeds checks as correct against its own answer
- Offline: equivalent answers accepted (
2/4for1/2,x + 3for3 + x); unexpanded2(x + 3)rejected where the level asks to expand - Offline: a node without 1★ before it can't be started; a checkpoint draws only from its world; path order respects every
needsintopics.yaml - Live: he finishes World 1's checkpoint; keep a list of "my answer was right but it said wrong" for the first week, aim for none
Step 3 · Freshness on real dates Not Started
- Goal
- Topics he has passed come back for review at the right time.
- Changes
- Leitner boxes on calendar dates (local time); due/stale halo on the path
- "Today" panel with up to 5 due reviews, most overdue first; a review is one run at his current star level
- Fresh stars and the exam-ready meter (share of core subtopics at fresh 2★+: 26 in Worlds 1–10, all 31 after Step 5) on the home screen
- Done looks like
- A topic passed today shows as due on the right date; after a holiday the queue still shows at most 5.
- How we verify
- Offline: pass → box up, due = today + interval; fail → box down (min 1); stars never drop
- Offline: queue cap 5; meter counts only fresh 2★+ core subtopics
- Live: over a week, reviews appear on the expected days
Step 4 · Accounts and parent rewards Not Started
- Goal
- The parent sets real rewards on their device; he sees them on his.
- Changes
- Stack decided. Small server app + SQLite on a Dokku storage mount; two accounts created upfront, no signup page
- Tables:
users,topic_state(user, topic, stars, box, due_at),attempts(user, topic, level, question, given, correct, ms),rewards store.jstalks to the API; one-time import of the localStorage progress- Parent page: create a reward (fresh stars ≥ N, branch at 2★, topic at 3★, streak of N days, checkpoint passed, exam-ready ≥ N%); mark earned rewards as given; weak spots from
attempts - He sees each reward with a progress bar ("14 / 20 fresh stars"); earned is never taken back
- Done looks like
- A reward set on the parent's phone shows on his device with the right progress; earning it shows on both.
- How we verify
- Offline: each condition type against fixtures; earned → given only by the parent; importing a Step 3 save loses nothing
- Live: one real reward set and earned
Step 5 · Shape & data Not Started
- Goal
- The ~30% of Foundation marks in Shape & data.
- Changes
- Generators and worlds 11+, appended to the path, for the 11 non-canvas Shape & data subtopics (angles, area_perimeter, pythagoras, trigonometry, …), with SVG diagrams
- The 3 missing algebra/graph subtopics: inequalities, simultaneous_equations, perpendicular_lines
transformations,constructions,plotting_drawstay parked until a drawing canvas is worth building
- Done looks like
- The new worlds are playable with their checkpoints.
- How we verify
- Same generator/checker tests as Step 2
6 · Not in scope
- Drawing-canvas answers (transformations, constructions, plotting_draw)
- Higher-tier topics
- Signup, more than two accounts, a theme beyond the prototype's look
- Exam papers in £ (a few at the end, per
topics.md)