"use client"; import { useState, useCallback } from "react"; import { Card } from "@/components/ui/card"; import { StepControls } from "./step-controls"; import { gcd, lcm, simplify, toKatex } from "@/lib/math/fractions"; import { MathDisplay } from "@/components/math/math-display"; type Operation = "add" | "subtract" | "multiply" | "divide"; interface Step { label: string; math: string; barA: { filled: number; total: number }; barB: { filled: number; total: number }; barResult?: { filled: number; total: number }; } function buildSteps( n1: number, d1: number, n2: number, d2: number, op: Operation, ): Step[] { const steps: Step[] = []; // Step 0: Show the original fractions const opSymbol = { add: "+", subtract: "-", multiply: "\\times", divide: "\\div" }[op]; steps.push({ label: "Start with the two fractions", math: `${toKatex(n1, d1)} ${opSymbol} ${toKatex(n2, d2)}`, barA: { filled: n1, total: d1 }, barB: { filled: n2, total: d2 }, }); if (op === "add" || op === "subtract") { // Step 1: Find LCD const lcd = lcm(d1, d2); const mult1 = lcd / d1; const mult2 = lcd / d2; const cn1 = n1 * mult1; const cn2 = n2 * mult2; if (d1 !== d2) { steps.push({ label: `Find the LCD of ${d1} and ${d2}`, math: `\\text{LCD}(${d1}, ${d2}) = ${lcd}`, barA: { filled: n1, total: d1 }, barB: { filled: n2, total: d2 }, }); // Step 2: Convert both fractions steps.push({ label: "Convert to equivalent fractions with the LCD", math: `${toKatex(n1, d1)} = ${toKatex(cn1, lcd)} \\quad ${toKatex(n2, d2)} = ${toKatex(cn2, lcd)}`, barA: { filled: cn1, total: lcd }, barB: { filled: cn2, total: lcd }, }); } // Step 3: Perform the operation const resultNum = op === "add" ? cn1 + cn2 : cn1 - cn2; steps.push({ label: op === "add" ? "Add the numerators" : "Subtract the numerators", math: `${toKatex(cn1, lcd)} ${opSymbol} ${toKatex(cn2, lcd)} = ${toKatex(resultNum, lcd)}`, barA: { filled: cn1, total: lcd }, barB: { filled: cn2, total: lcd }, barResult: { filled: Math.abs(resultNum), total: lcd }, }); // Step 4: Simplify if needed const [sn, sd] = simplify(resultNum, lcd); if (Math.abs(sn) !== Math.abs(resultNum) || sd !== lcd) { const g = gcd(Math.abs(resultNum), lcd); steps.push({ label: `Simplify by dividing by GCD = ${g}`, math: `${toKatex(resultNum, lcd)} = ${toKatex(sn, sd)}`, barA: { filled: cn1, total: lcd }, barB: { filled: cn2, total: lcd }, barResult: { filled: Math.abs(sn), total: sd }, }); } } else if (op === "multiply") { // Step 1: Multiply numerators and denominators const rn = n1 * n2; const rd = d1 * d2; steps.push({ label: "Multiply numerators and denominators", math: `\\frac{${n1} \\times ${n2}}{${d1} \\times ${d2}} = ${toKatex(rn, rd)}`, barA: { filled: n1, total: d1 }, barB: { filled: n2, total: d2 }, barResult: { filled: rn, total: rd }, }); // Step 2: Simplify const [sn, sd] = simplify(rn, rd); if (sn !== rn || sd !== rd) { const g = gcd(Math.abs(rn), rd); steps.push({ label: `Simplify by dividing by GCD = ${g}`, math: `${toKatex(rn, rd)} = ${toKatex(sn, sd)}`, barA: { filled: n1, total: d1 }, barB: { filled: n2, total: d2 }, barResult: { filled: Math.abs(sn), total: sd }, }); } } else { // divide: invert and multiply steps.push({ label: "Invert the second fraction (reciprocal)", math: `${toKatex(n1, d1)} \\times ${toKatex(d2, n2)}`, barA: { filled: n1, total: d1 }, barB: { filled: d2, total: n2 }, }); const rn = n1 * d2; const rd = d1 * n2; steps.push({ label: "Multiply numerators and denominators", math: `\\frac{${n1} \\times ${d2}}{${d1} \\times ${n2}} = ${toKatex(rn, rd)}`, barA: { filled: n1, total: d1 }, barB: { filled: d2, total: n2 }, barResult: { filled: rn, total: rd }, }); const [sn, sd] = simplify(rn, rd); if (sn !== rn || sd !== rd) { const g = gcd(Math.abs(rn), rd); steps.push({ label: `Simplify by dividing by GCD = ${g}`, math: `${toKatex(rn, rd)} = ${toKatex(sn, sd)}`, barA: { filled: n1, total: d1 }, barB: { filled: d2, total: n2 }, barResult: { filled: Math.abs(sn), total: sd }, }); } } return steps; } function FractionBar({ filled, total, color, label, }: { filled: number; total: number; color: string; label?: string; }) { const maxSegments = Math.min(total, 24); const fillCount = Math.min(filled, maxSegments); return (
Enter two fractions
{error}
}Enter fractions above and click Go
) : ( <>{step.label}
Result will appear here when steps are complete
) : ( <>Answer