import { useState, useMemo } from 'react'; import { Card, CardHeader } from '../../ui/Card'; import { Button } from '../../ui/Button'; import { CheckCircle, RotateCcw, Calculator } from 'lucide-react'; interface FilaCostos { q: number; cv: number; } interface FilaCalculada extends FilaCostos { cf: number; ct: number; cfme: number; cvme: number; cme: number; cmg: number | null; } interface CalculadoraCostosProps { ejercicioId: string; onComplete?: (puntuacion: number) => void; } export function CalculadoraCostos({ ejercicioId: _ejercicioId, onComplete }: CalculadoraCostosProps) { const CF_BASE = 200; const [filas, setFilas] = useState([ { q: 0, cv: 0 }, { q: 1, cv: 50 }, { q: 2, cv: 90 }, { q: 3, cv: 120 }, { q: 4, cv: 160 }, { q: 5, cv: 220 }, { q: 6, cv: 300 }, { q: 7, cv: 400 }, { q: 8, cv: 520 }, ]); const [validado, setValidado] = useState(false); const [errores, setErrores] = useState([]); const datosCalculados: FilaCalculada[] = useMemo(() => { return filas.map((fila, index) => { const ct = CF_BASE + fila.cv; const cfme = fila.q > 0 ? CF_BASE / fila.q : 0; const cvme = fila.q > 0 ? fila.cv / fila.q : 0; const cme = fila.q > 0 ? ct / fila.q : 0; const cmg = index > 0 ? ct - (CF_BASE + filas[index - 1].cv) : null; return { ...fila, cf: CF_BASE, ct, cfme, cvme, cme, cmg, }; }); }, [filas]); const handleCvChange = (index: number, valor: string) => { const numValor = parseFloat(valor) || 0; const nuevasFilas = [...filas]; nuevasFilas[index] = { ...nuevasFilas[index], cv: numValor }; setFilas(nuevasFilas); setValidado(false); }; const validarCalculos = () => { const nuevosErrores: string[] = []; datosCalculados.forEach((fila, index) => { if (fila.ct !== fila.cf + fila.cv) { nuevosErrores.push(`Fila ${index + 1}: CT no coincide con CF + CV`); } if (fila.q > 0 && Math.abs(fila.cme - fila.ct / fila.q) > 0.01) { nuevosErrores.push(`Fila ${index + 1}: CMe calculado incorrectamente`); } }); setErrores(nuevosErrores); setValidado(true); if (nuevosErrores.length === 0) { if (onComplete) { onComplete(100); } } }; const reiniciar = () => { setFilas([ { q: 0, cv: 0 }, { q: 1, cv: 50 }, { q: 2, cv: 90 }, { q: 3, cv: 120 }, { q: 4, cv: 160 }, { q: 5, cv: 220 }, { q: 6, cv: 300 }, { q: 7, cv: 400 }, { q: 8, cv: 520 }, ]); setValidado(false); setErrores([]); }; const maxCT = Math.max(...datosCalculados.map(d => d.ct)); const maxCMe = Math.max(...datosCalculados.filter(d => d.q > 0).map(d => d.cme)); const maxCMg = Math.max(...datosCalculados.filter(d => d.cmg !== null).map(d => d.cmg || 0)); const escalaCT = maxCT > 0 ? 150 / maxCT : 1; const escalaCMe = maxCMe > 0 ? 150 / maxCMe : 1; const escalaCMg = maxCMg > 0 ? 150 / maxCMg : 1; return (
{datosCalculados.map((fila, index) => ( ))}
Q CF CV CT CFMe CVMe CMe CMg
{fila.q} {fila.cf} handleCvChange(index, e.target.value)} className="w-20 px-2 py-1 border rounded text-sm focus:ring-2 focus:ring-primary focus:border-transparent" min="0" disabled={fila.q === 0} /> {fila.ct} {fila.q > 0 ? fila.cfme.toFixed(2) : '-'} {fila.q > 0 ? fila.cvme.toFixed(2) : '-'} {fila.q > 0 ? fila.cme.toFixed(2) : '-'} {fila.cmg !== null ? fila.cmg : '-'}
{validado && errores.length === 0 && (
¡Todos los cálculos son correctos!
)} {validado && errores.length > 0 && (

Se encontraron errores:

    {errores.map((error, i) => (
  • {error}
  • ))}
)}

Costo Total (CT)

Cantidad (Q) CT {datosCalculados.map((d, i) => ( {d.q} ))} `${30 + i * 40},${140 - d.ct * escalaCT}`).join(' ')} /> {datosCalculados.map((d, i) => ( ))}

Costo Medio (CMe) vs Costo Marginal (CMg)

Cantidad (Q) Costo {datosCalculados.filter(d => d.q > 0).map((d, i) => ( {d.q} ))} d.q > 0) .map((d, i) => `${70 + i * 40},${140 - d.cme * escalaCMe}`) .join(' ')} /> d.cmg !== null) .map((d, i) => `${70 + i * 40},${140 - (d.cmg || 0) * escalaCMg}`) .join(' ')} /> {datosCalculados.filter(d => d.q > 0).map((d, i) => ( ))} {datosCalculados.filter(d => d.cmg !== null).map((d, i) => ( ))} CMe CMg

Fórmulas utilizadas:

  • CT = CF + CV (Costo Total)
  • CFMe = CF / Q (Costo Fijo Medio)
  • CVMe = CV / Q (Costo Variable Medio)
  • CMe = CT / Q (Costo Medio)
  • CMg = ΔCT / ΔQ (Costo Marginal)
); } export default CalculadoraCostos;