A lightweight, zero-dependency JavaScript library for generating curriculum-aligned math problems for UK primary school students (Reception to Year 6, ages 4-11).
Installation
npm install maths-game-problem-generator
Quick Start
import { generateProblem, checkAnswer } from 'maths-game-problem-generator'; // Generate a Year 3 division problem const problem = generateProblem({ yearLevel: 'year3', type: 'division', multipleChoice: true }); console.log(problem.expression); // e.g., "72 ÷ 8" console.log(problem.answer); // e.g., 9 console.log(problem.formattedAnswer); // e.g., "9" console.log(problem.choices); // e.g., ["8", "9", "11", "12"] // Check a user's answer const isCorrect = checkAnswer(problem, 9); // true const alsoCorrect = checkAnswer(problem, "9"); // true (strings work too) // Generate a fractions problem const fractionProblem = generateProblem({ yearLevel: 'year5', type: 'fraction', multipleChoice: true }); console.log(fractionProblem.expression); // e.g., "3/4 of 40" console.log(fractionProblem.answer); // e.g., 30
API
generateProblem(options)
Generates a math problem.
// Default: Reception level, random type const problem = generateProblem(); // Specific year level (random type for that year) const year2Problem = generateProblem({ yearLevel: 'year2' }); // Specific type (default year: Reception) const addProblem = generateProblem({ type: 'addition' }); // Both year and type const year5Cube = generateProblem({ yearLevel: 'year5', type: 'cube' });
Returns a problem object:
| Property | Type | Description |
|---|---|---|
expression |
string | The problem (e.g., "15 + 7", "√81", "2³") |
expression_short |
string | Shorter version for compact UIs (e.g., "15+7") |
answer |
number | string |
formattedAnswer |
string | Answer as a display string (handles decimals cleanly) |
type |
string | Problem type (e.g., "addition", "squared") |
yearLevel |
string | Year level (e.g., "year3") |
subtype |
string | Optional curriculum-oriented subtype (e.g., "fraction_of_amount_operator") |
expectedAnswer |
object | Optional structured answer metadata for fraction-aware checking |
When called with { multipleChoice: true }, the returned object also includes:
| Property | Type | Description |
|---|---|---|
choices |
string[] | Plausible answer choices including the correct answer |
correctChoice |
string | The correct answer as a display string |
checkAnswer(problem, userAnswer)
Validates a user's answer. Handles strings, numbers, and floating-point tolerance.
checkAnswer(problem, 42); // true if answer is 42 checkAnswer(problem, "42"); // true (string input works) checkAnswer(problem, 0.25); // handles decimals with tolerance checkAnswer({ answer: "1/2", expectedAnswer: { kind: "fraction", numerator: 1, denominator: 2 } }, "2/4"); // true: equivalent fractions work when expectedAnswer is present
getYearLevels() / getProblemTypes()
Get available options:
getYearLevels(); // ['reception', 'year1', 'year2', 'year3', 'year4', 'year5', 'year6'] getProblemTypes(); // ['addition', 'subtraction', 'multiplication', 'division', 'squared', 'cube', 'fraction']
Constants
Use constants for cleaner code:
import { YEAR_LEVELS, PROBLEM_TYPES } from 'maths-game-problem-generator'; generateProblem({ yearLevel: YEAR_LEVELS.YEAR6, type: PROBLEM_TYPES.SQUARED });
Default Export
import MathProblemGenerator from 'maths-game-problem-generator'; MathProblemGenerator.generateProblem({ yearLevel: 'year3' }); MathProblemGenerator.checkAnswer(problem, answer); MathProblemGenerator.getYearLevels(); MathProblemGenerator.getProblemTypes(); MathProblemGenerator.yearLevels; // Same as YEAR_LEVELS MathProblemGenerator.problemTypes; // Same as PROBLEM_TYPES
Year Levels
| Level | Ages | Focus |
|---|---|---|
reception |
4-5 | Numbers to 10, simple +/- |
year1 |
5-6 | Numbers to 20, +/- within 20 |
year2 |
6-7 | Numbers to 100, ×/÷ by 2, 5, 10 |
year3 |
7-8 | Numbers to 1000, ×/÷ by 3, 4, 8 |
year4 |
8-9 | Larger numbers, all tables up to 12×12, non-unit fractions |
year5 |
9-10 | Decimals, fractions as operators, squares, cubes, powers of 10 |
year6 |
10-11 | Advanced mental strategies, upper-primary fractions, square/cube recall |
Problem Types
| Type | Description |
|---|---|
addition |
Addition problems |
subtraction |
Subtraction problems |
multiplication |
Multiplication problems |
division |
Division problems (remainders in Year 4+) |
squared |
Square numbers and square roots |
cube |
Cube numbers (Year 5-6 only) |
fraction |
Fraction questions, including fraction-of-quantity, equivalence, comparison, and selected operations |
Examples
import { generateProblem, YEAR_LEVELS, PROBLEM_TYPES } from 'maths-game-problem-generator'; // Generate 5 random Year 1 problems const problems = Array(5).fill().map(() => generateProblem({ yearLevel: YEAR_LEVELS.YEAR1 }) ); problems.forEach((p, i) => console.log(`${i+1}. ${p.expression} = ${p.formattedAnswer}`) ); // Year 6 squared problem (includes square roots) const squared = generateProblem({ yearLevel: YEAR_LEVELS.YEAR6, type: PROBLEM_TYPES.SQUARED }); // e.g., { expression: '√144', answer: 12, ... } // Year 5 cube problem const cubed = generateProblem({ yearLevel: 'year5', type: 'cube' }); // e.g., { expression: '2³', answer: 8, ... } // Year 5 fraction problem const fraction = generateProblem({ yearLevel: 'year5', type: PROBLEM_TYPES.FRACTION, multipleChoice: true }); // e.g., { expression: 'three quarters of 40', answer: 30, choices: ['10', '30', '40', '34'], ... }