"use client"; import { useState, useCallback } from "react"; import { Card } from "@/components/ui/card"; import { StepControls } from "./step-controls"; import { MathDisplay } from "@/components/math/math-display"; import { simplify, toKatex, gcd } from "@/lib/math/fractions"; import { parseStrictDecimal, parseStrictInt } from "@/lib/math/validation"; type ConvertMode = "decToFrac" | "fracToDec"; interface Step { label: string; math: string; gridFilled?: number; // out of 100 for decimal grid barFilled?: number; barTotal?: number; } function buildDecToFracSteps(decimal: string): Step[] { const steps: Step[] = []; const val = parseFloat(decimal); steps.push({ label: `Convert ${decimal} to a fraction`, math: `${decimal} = \\;?`, gridFilled: Math.round(val * 100), }); // Count decimal places const parts = decimal.split("."); const decPlaces = parts[1]?.length || 0; const denominator = Math.pow(10, decPlaces); const numerator = Math.round(val * denominator); steps.push({ label: `${decPlaces} decimal place${decPlaces !== 1 ? "s" : ""} → denominator is ${denominator}`, math: `${decimal} = ${toKatex(numerator, denominator)}`, gridFilled: Math.round(val * 100), barFilled: numerator, barTotal: denominator, }); // Simplify const [sn, sd] = simplify(numerator, denominator); if (sn !== numerator || sd !== denominator) { const g = gcd(numerator, denominator); steps.push({ label: `Simplify by dividing by GCD = ${g}`, math: `${toKatex(numerator, denominator)} = ${toKatex(sn, sd)}`, gridFilled: Math.round(val * 100), barFilled: sn, barTotal: sd, }); } steps.push({ label: `Result: ${decimal} = ${sn}/${sd}`, math: `${decimal} = ${toKatex(sn, sd)}`, gridFilled: Math.round(val * 100), barFilled: sn, barTotal: sd, }); return steps; } function buildFracToDecSteps(num: number, den: number): Step[] { const steps: Step[] = []; steps.push({ label: `Convert ${num}/${den} to a decimal`, math: `${toKatex(num, den)} = \\;?`, barFilled: num, barTotal: den, }); // Step: Perform the division const result = num / den; const resultStr = Number.isInteger(result) ? result.toString() : result.toFixed(6).replace(/0+$/, ""); steps.push({ label: `Divide numerator by denominator`, math: `${num} \\div ${den} = ${resultStr}`, barFilled: num, barTotal: den, gridFilled: Math.min(100, Math.round(result * 100)), }); // Check for terminating vs repeating let tempDen = den; const [, simpDen] = simplify(num, den); tempDen = simpDen; // Remove factors of 2 and 5 while (tempDen % 2 === 0) tempDen /= 2; while (tempDen % 5 === 0) tempDen /= 5; const isTerminating = tempDen === 1; steps.push({ label: isTerminating ? `This is a terminating decimal` : `This is a recurring decimal`, math: `${toKatex(num, den)} = ${resultStr}${!isTerminating ? "..." : ""}`, barFilled: num, barTotal: den, gridFilled: Math.min(100, Math.round(result * 100)), }); return steps; } function DecimalGrid({ filled }: { filled: number }) { return (
{mode === "decToFrac" ? "Enter a decimal" : "Enter a fraction"}
{error}
}Enter a value above and click Convert
) : ( <>{step.label}
Result will appear here when steps are complete
) : ( <>Answer