Files
edbridge-scholars/src/components/lessons/FactoringWidget.tsx
2026-03-01 20:24:14 +06:00

116 lines
5.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useState } from 'react';
const FactoringWidget: React.FC = () => {
// ax^2 + bx + c
const [a, setA] = useState(1);
const [b, setB] = useState(5);
const [c, setC] = useState(6);
const product = a * c;
const sum = b;
// We won't solve it for them immediately, let them guess or think
// But we will show if it's factorable over integers
// Simple check for nice numbers
const getFactors = () => {
// Find two numbers p, q such that p*q = product and p+q = sum
// Brute force range reasonable for typical SAT (up to +/- 100)
for (let i = -100; i <= 100; i++) {
if (i === 0) continue;
const q = product / i;
if (Math.abs(q - Math.round(q)) < 0.001) { // is integer
if (i + q === sum) return [i, q].sort((x,y) => x-y);
}
}
return null;
};
const solution = getFactors();
return (
<div className="bg-white p-6 rounded-xl shadow-lg border border-slate-200">
<div className="flex flex-col md:flex-row gap-8 items-center">
{/* Input Side */}
<div className="w-full md:w-1/2 space-y-4">
<h4 className="font-bold text-violet-900 mb-2">Polynomial: <span className="font-mono text-lg">{a === 1 ? '' : a}x² {b >= 0 ? '+' : ''}{b}x {c >= 0 ? '+' : ''}{c}</span></h4>
<div className="grid grid-cols-3 gap-2">
<div>
<label className="text-xs font-bold text-slate-400">a</label>
<input type="number" value={a} onChange={e => setA(parseInt(e.target.value) || 0)} className="w-full p-2 border rounded font-mono font-bold text-center" />
</div>
<div>
<label className="text-xs font-bold text-slate-400">b (Sum)</label>
<input type="number" value={b} onChange={e => setB(parseInt(e.target.value) || 0)} className="w-full p-2 border rounded font-mono font-bold text-center" />
</div>
<div>
<label className="text-xs font-bold text-slate-400">c</label>
<input type="number" value={c} onChange={e => setC(parseInt(e.target.value) || 0)} className="w-full p-2 border rounded font-mono font-bold text-center" />
</div>
</div>
<div className="p-4 bg-slate-50 rounded-lg text-sm text-slate-600">
<p><strong>AC Method (Diamond):</strong></p>
<p>Find two numbers that multiply to <strong>a·c</strong> and add to <strong>b</strong>.</p>
<p className="mt-2 font-mono text-center">
Product (ac) = {a} × {c} = <strong>{product}</strong> <br/>
Sum (b) = <strong>{sum}</strong>
</p>
</div>
</div>
{/* Visual Side */}
<div className="flex-1 flex flex-col items-center justify-center">
<div className="relative w-48 h-48">
{/* X Shape */}
<div className="absolute top-0 left-0 w-full h-full">
<svg width="100%" height="100%" viewBox="0 0 200 200">
<line x1="20" y1="20" x2="180" y2="180" stroke="#cbd5e1" strokeWidth="4" />
<line x1="180" y1="20" x2="20" y2="180" stroke="#cbd5e1" strokeWidth="4" />
</svg>
</div>
{/* Top (Product) */}
<div className="absolute top-0 left-1/2 -translate-x-1/2 -translate-y-4 bg-violet-100 px-3 py-1 rounded border border-violet-300 text-violet-800 font-bold shadow-sm">
{product}
</div>
{/* Bottom (Sum) */}
<div className="absolute bottom-0 left-1/2 -translate-x-1/2 translate-y-4 bg-indigo-100 px-3 py-1 rounded border border-indigo-300 text-indigo-800 font-bold shadow-sm">
{sum}
</div>
{/* Left (Factor 1) */}
<div className="absolute left-0 top-1/2 -translate-x-6 -translate-y-1/2 bg-white px-3 py-2 rounded border-2 border-emerald-400 text-emerald-700 font-bold shadow-md min-w-[3rem] text-center">
{solution ? solution[0] : "?"}
</div>
{/* Right (Factor 2) */}
<div className="absolute right-0 top-1/2 translate-x-6 -translate-y-1/2 bg-white px-3 py-2 rounded border-2 border-emerald-400 text-emerald-700 font-bold shadow-md min-w-[3rem] text-center">
{solution ? solution[1] : "?"}
</div>
</div>
<div className="mt-8 text-center">
{solution ? (
<div className="text-emerald-700 font-bold bg-emerald-50 px-4 py-2 rounded-lg border border-emerald-200">
Factors Found: {solution[0]} and {solution[1]}
{a === 1 && (
<div className="text-sm mt-1 font-mono text-slate-600">
(x {solution[0] >= 0 ? '+' : ''}{solution[0]})(x {solution[1] >= 0 ? '+' : ''}{solution[1]})
</div>
)}
</div>
) : (
<div className="text-rose-600 font-bold text-sm bg-rose-50 px-4 py-2 rounded-lg border border-rose-200">
No integer factors found. (Prime)
</div>
)}
</div>
</div>
</div>
</div>
);
};
export default FactoringWidget;