73 lines
2.6 KiB
TypeScript
73 lines
2.6 KiB
TypeScript
import { describe, it, expect } from "vitest";
|
|
import type { Difficulty, MathProblem } from "../types";
|
|
import { generateFractionBodmas, generateSignedFraction } from "./fraction-problems";
|
|
import { generateDefineRatio, generateFractionsAndRatios } from "./ratio-problems";
|
|
import { generateIntegerOrderCompare, generateIntegerAddSubtractMixed } from "./integer-problems";
|
|
import { generateQuaternaryToDenary } from "./number-system-problems";
|
|
|
|
function assertWellFormed(p: MathProblem) {
|
|
expect(typeof p.prompt).toBe("string");
|
|
expect(p.prompt.length).toBeGreaterThan(0);
|
|
expect(Array.isArray(p.hints)).toBe(true);
|
|
expect(Array.isArray(p.steps)).toBe(true);
|
|
|
|
const a = p.answer;
|
|
if (a.kind === "integer") {
|
|
expect(Number.isFinite(a.value)).toBe(true);
|
|
} else if (a.kind === "fraction") {
|
|
expect(Number.isInteger(a.numerator)).toBe(true);
|
|
expect(Number.isInteger(a.denominator)).toBe(true);
|
|
expect(a.denominator).not.toBe(0);
|
|
} else if (a.kind === "ratio") {
|
|
expect(a.parts.length).toBeGreaterThan(0);
|
|
a.parts.forEach((v) => expect(Number.isFinite(v)).toBe(true));
|
|
}
|
|
}
|
|
|
|
const NEW_GENERATORS: Record<string, (d: Difficulty) => MathProblem> = {
|
|
"fraction BODMAS": generateFractionBodmas,
|
|
"signed fraction": generateSignedFraction,
|
|
"define ratio": generateDefineRatio,
|
|
"fractions and ratios": generateFractionsAndRatios,
|
|
"integer order/compare": generateIntegerOrderCompare,
|
|
"integer add/subtract (mixed)": generateIntegerAddSubtractMixed,
|
|
"quaternary to denary": generateQuaternaryToDenary,
|
|
};
|
|
|
|
describe("new practice generators produce well-formed problems", () => {
|
|
for (const [name, gen] of Object.entries(NEW_GENERATORS)) {
|
|
it(name, () => {
|
|
for (const d of [1, 2, 3] as Difficulty[]) {
|
|
for (let i = 0; i < 40; i++) assertWellFormed(gen(d));
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
describe("quaternary answer matches its base-4 prompt", () => {
|
|
it("converts base 4 correctly", () => {
|
|
for (const d of [1, 2, 3] as Difficulty[]) {
|
|
for (let i = 0; i < 40; i++) {
|
|
const p = generateQuaternaryToDenary(d);
|
|
const digits = p.prompt.match(/^(\d+)_\{4\}/)?.[1];
|
|
expect(digits).toBeTruthy();
|
|
if (p.answer.kind === "integer") {
|
|
expect(p.answer.value).toBe(parseInt(digits!, 4));
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
describe("order/compare answer is one of the numbers asked about", () => {
|
|
it("picks a value from the prompt", () => {
|
|
for (let i = 0; i < 60; i++) {
|
|
const p = generateIntegerOrderCompare(1);
|
|
const nums = (p.prompt.match(/-?\d+/g) ?? []).map(Number);
|
|
if (p.answer.kind === "integer") {
|
|
expect(nums).toContain(p.answer.value);
|
|
}
|
|
}
|
|
});
|
|
});
|