"use client"; import { useState, useCallback } from "react"; import { Card } from "@/components/ui/card"; import { ClientOnly } from "@/components/ui/client-only"; import { StepControls } from "./step-controls"; import { MathDisplay } from "@/components/math/math-display"; type Mode = "identity" | "inverse" | "zero"; type Op = "add" | "multiply"; interface Step { label: string; math: string; danger?: boolean; } function buildIdentitySteps(n: number, op: Op): Step[] { if (op === "add") { return [ { label: "The identity for addition is 0 — it leaves a number unchanged.", math: `${n} + 0` }, { label: "Adding 0 changes nothing.", math: `${n} + 0 = ${n}` }, { label: "So 0 is the identity element for addition.", math: `n + 0 = n` }, ]; } return [ { label: "The identity for multiplication is 1 — it leaves a number unchanged.", math: `${n} \\times 1` }, { label: "Multiplying by 1 changes nothing.", math: `${n} \\times 1 = ${n}` }, { label: "So 1 is the identity element for multiplication.", math: `n \\times 1 = n` }, ]; } function buildInverseSteps(n: number, op: Op): Step[] { if (op === "add") { const inv = -n; const invText = inv < 0 ? `(${inv})` : `${inv}`; return [ { label: "The additive inverse is the number that brings you back to the identity, 0.", math: `${n} + \\square = 0` }, { label: `Flip the sign of ${n} to get its additive inverse.`, math: `\\text{inverse of } ${n} = ${inv}` }, { label: "Check: adding a number and its inverse gives 0.", math: `${n} + ${invText} = 0` }, ]; } // multiplicative inverse (reciprocal) const absN = Math.abs(n); const recip = n < 0 ? `-\\frac{1}{${absN}}` : `\\frac{1}{${absN}}`; const recipParen = n < 0 ? `\\left(-\\frac{1}{${absN}}\\right)` : `\\frac{1}{${absN}}`; return [ { label: "The multiplicative inverse (reciprocal) brings you back to the identity, 1.", math: `${n} \\times \\square = 1` }, { label: `Write ${n} as a fraction and flip it. The sign stays in front.`, math: `\\text{inverse of } ${n} = ${recip}` }, { label: "Check: a number times its reciprocal gives 1.", math: `${n} \\times ${recipParen} = 1` }, ]; } function buildZeroSteps(n: number): Step[] { return [ { label: "Multiplying any number by zero always gives zero.", math: `${n} \\times 0 = 0` }, { label: "Zero shared into any number of groups is still zero.", math: `0 \\div ${n === 0 ? 5 : n} = 0` }, { label: "But you can never divide BY zero — there is no answer. It is undefined.", math: `${n} \\div 0 = \\text{undefined}`, danger: true, }, ]; } // ── Quick practice ─────────────────────────────────────────────────────────── interface PracticeQ { prompt: string; answer: number; } function randInt(min: number, max: number) { return Math.floor(Math.random() * (max - min + 1)) + min; } function makeQuestion(): PracticeQ { const roll = Math.floor(Math.random() * 5); if (roll === 0) { const n = randInt(-12, 12) || 3; return { prompt: `What is the additive inverse of ${n}?`, answer: -n }; } if (roll === 1) { const n = randInt(1, 20); return { prompt: `What is ${n} × 0?`, answer: 0 }; } if (roll === 2) { return { prompt: `What number is the identity for addition?`, answer: 0 }; } if (roll === 3) { return { prompt: `What number is the identity for multiplication?`, answer: 1 }; } const n = randInt(2, 12); return { prompt: `The multiplicative inverse of ${n} is 1 over what number?`, answer: n }; } function QuickPractice() { const [q, setQ] = useState(() => makeQuestion()); const [val, setVal] = useState(""); const [feedback, setFeedback] = useState<"correct" | "incorrect" | null>(null); const [score, setScore] = useState({ correct: 0, total: 0 }); function check() { const parsed = parseInt(val, 10); if (isNaN(parsed)) return; const correct = parsed === q.answer; setFeedback(correct ? "correct" : "incorrect"); setScore((s) => ({ correct: s.correct + (correct ? 1 : 0), total: s.total + 1 })); } function next() { setQ(makeQuestion()); setVal(""); setFeedback(null); } return (

Quick Practice

{score.correct}/{score.total}

{q.prompt}

{ setVal(e.target.value); setFeedback(null); }} onKeyDown={(e) => { if (e.key === "Enter") { if (feedback !== null) next(); else check(); } }} className={`w-24 rounded-lg border-2 px-3 py-2 text-center text-xl font-bold outline-none transition-colors ${ feedback === "correct" ? "border-correct bg-correct-light" : feedback === "incorrect" ? "border-incorrect bg-incorrect-light" : "border-border focus:border-unit-8" }`} placeholder="?" aria-label="Your answer" /> {feedback === null ? ( ) : ( )}
{feedback === "correct" &&

Correct!

} {feedback === "incorrect" && (

Not quite — the answer is {q.answer}.

)}
); } // ── Main explorer ──────────────────────────────────────────────────────────── export function IdentityInverseExplorer() { const [mode, setMode] = useState("identity"); const [op, setOp] = useState("add"); const [input, setInput] = useState("3"); const [error, setError] = useState(""); const [steps, setSteps] = useState(null); const [currentStep, setCurrentStep] = useState(0); const [isPlaying, setIsPlaying] = useState(false); const done = steps ? currentStep >= steps.length - 1 : false; const reset = useCallback(() => { setSteps(null); setCurrentStep(0); setIsPlaying(false); }, []); function switchMode(m: Mode) { setMode(m); setError(""); reset(); } function handleGo() { setError(""); const n = parseInt(input, 10); if (isNaN(n)) return setError("Enter a valid whole number."); if (Math.abs(n) > 100) return setError("Keep the number between -100 and 100."); if (mode === "inverse" && op === "multiply" && n === 0) { return setError("Zero has no multiplicative inverse — try another number."); } if (mode === "identity") setSteps(buildIdentitySteps(n, op)); else if (mode === "inverse") setSteps(buildInverseSteps(n, op)); else setSteps(buildZeroSteps(n)); setCurrentStep(0); setIsPlaying(false); } const stepForward = useCallback(() => { if (!steps || currentStep >= steps.length - 1) return; setCurrentStep((s) => s + 1); if (currentStep + 1 >= steps.length - 1) setIsPlaying(false); }, [steps, currentStep]); const stepBack = useCallback(() => { if (currentStep <= 0) return; setCurrentStep((s) => s - 1); }, [currentStep]); const togglePlay = useCallback(() => setIsPlaying((p) => !p), []); const step = steps ? steps[currentStep] : null; const showOp = mode !== "zero"; return (
{/* Mode toggle */}
{(["identity", "inverse", "zero"] as Mode[]).map((m) => ( ))}
{/* Operation tabs */} {showOp && (
{(["add", "multiply"] as Op[]).map((o) => ( ))}
)} {/* Input card */}

{mode === "identity" ? "See how the identity leaves a number unchanged" : mode === "inverse" ? "Find the inverse of a number" : "Explore what happens with zero"}

setInput(e.target.value)} className="w-24 rounded-lg border-2 border-border bg-surface px-3 py-2 text-center text-lg font-bold outline-none focus:border-unit-8" aria-label="Number" />
{error &&

{error}

}
{/* Display card */} {!step ? (

Enter a number above and click Go

) : ( <>

{step.label}

)}
{/* Controls */} 0} /> {/* Quick practice */} }>
); }