"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 { simplifyRatio } from "@/lib/math/ratios"; import { gcd } from "@/lib/math/fractions"; type RatioMode = "divide" | "simplify" | "equivalent"; interface Step { label: string; math: string; barSegments: { value: number; filled: boolean; label?: string }[]; } const COLORS = ["var(--unit-4)", "var(--unit-1)", "var(--unit-3)", "var(--hint)"]; function buildDivideSteps(total: number, parts: number[]): Step[] { const steps: Step[] = []; const sum = parts.reduce((a, b) => a + b, 0); // Step 0: Show the ratio and total steps.push({ label: `Divide ${total} in the ratio ${parts.join(" : ")}`, math: `${total} \\div (${parts.join(" : ")})`, barSegments: parts.map((p) => ({ value: p, filled: false })), }); // Step 1: Sum the parts steps.push({ label: `Add the ratio parts: ${parts.join(" + ")} = ${sum}`, math: `${parts.join(" + ")} = ${sum} \\text{ total parts}`, barSegments: parts.map((p) => ({ value: p, filled: false })), }); // Step 2: Find one part const onePart = total / sum; steps.push({ label: `Find one part: ${total} ÷ ${sum} = ${onePart}`, math: `\\text{One part} = ${total} \\div ${sum} = ${Number.isInteger(onePart) ? onePart : onePart.toFixed(2)}`, barSegments: parts.map((p) => ({ value: p, filled: false })), }); // Steps 3+: Calculate each share const shares: number[] = []; parts.forEach((p, i) => { const share = p * onePart; shares.push(share); steps.push({ label: `Part ${i + 1}: ${p} × ${Number.isInteger(onePart) ? onePart : onePart.toFixed(2)} = ${Number.isInteger(share) ? share : share.toFixed(2)}`, math: `${p} \\times ${Number.isInteger(onePart) ? onePart : onePart.toFixed(2)} = ${Number.isInteger(share) ? share : share.toFixed(2)}`, barSegments: parts.map((pp, j) => ({ value: pp, filled: j <= i, label: j <= i ? `${Number.isInteger(shares[j]) ? shares[j] : shares[j].toFixed(2)}` : undefined, })), }); }); // Final step: Show all shares const shareStrs = shares.map((s) => (Number.isInteger(s) ? s.toString() : s.toFixed(2))); steps.push({ label: `Result: ${shareStrs.join(", ")}`, math: `${total} = ${shareStrs.join(" + ")}`, barSegments: parts.map((pp, j) => ({ value: pp, filled: true, label: shareStrs[j], })), }); return steps; } function buildSimplifySteps(parts: number[]): Step[] { const steps: Step[] = []; steps.push({ label: `Simplify the ratio ${parts.join(" : ")}`, math: parts.join(" : "), barSegments: parts.map((p) => ({ value: p, filled: true })), }); // Find GCD let g = parts[0]; for (let i = 1; i < parts.length; i++) g = gcd(g, parts[i]); if (g === 1) { steps.push({ label: "The ratio is already in its simplest form (GCD = 1)", math: `\\text{GCD} = 1`, barSegments: parts.map((p) => ({ value: p, filled: true })), }); } else { steps.push({ label: `Find the GCD of all parts: ${g}`, math: `\\text{GCD}(${parts.join(", ")}) = ${g}`, barSegments: parts.map((p) => ({ value: p, filled: true })), }); const simplified = simplifyRatio(parts); steps.push({ label: `Divide each part by ${g}`, math: parts.map((p) => `${p} \\div ${g} = ${p / g}`).join(", \\quad "), barSegments: simplified.map((p) => ({ value: p, filled: true })), }); steps.push({ label: `Simplified ratio: ${simplified.join(" : ")}`, math: `${parts.join(" : ")} = ${simplified.join(" : ")}`, barSegments: simplified.map((p) => ({ value: p, filled: true })), }); } return steps; } function buildEquivalentSteps(parts: number[], multiplier: number): Step[] { const steps: Step[] = []; steps.push({ label: `Find an equivalent ratio: ${parts.join(" : ")} × ${multiplier}`, math: `(${parts.join(" : ")}) \\times ${multiplier}`, barSegments: parts.map((p) => ({ value: p, filled: true })), }); const result = parts.map((p) => p * multiplier); steps.push({ label: `Multiply each part by ${multiplier}`, math: parts.map((p) => `${p} \\times ${multiplier} = ${p * multiplier}`).join(", \\quad "), barSegments: result.map((p) => ({ value: p, filled: true })), }); steps.push({ label: `Equivalent ratio: ${result.join(" : ")}`, math: `${parts.join(" : ")} = ${result.join(" : ")}`, barSegments: result.map((p) => ({ value: p, filled: true })), }); return steps; } function RatioBar({ segments, }: { segments: { value: number; filled: boolean; label?: string }[]; }) { const total = segments.reduce((s, seg) => s + seg.value, 0); if (total === 0) return null; return (
{mode === "divide" ? "Enter ratio parts and total" : mode === "simplify" ? "Enter ratio parts" : "Enter ratio parts and multiplier"}
{error}
}Enter values above and click Go
) : ( <>{step.label}
Result will appear here when steps are complete
) : ( <>Answer
{steps[steps.length - 1].label.replace("Result: ", "").replace("Simplified ratio: ", "").replace("Equivalent ratio: ", "")}
> )}