import { useState, useMemo } from 'react'; import { Card, CardHeader } from '../../ui/Card'; import { Button } from '../../ui/Button'; import { Input } from '../../ui/Input'; import { CheckCircle, Target, TrendingUp, DollarSign } from 'lucide-react'; interface FilaProduccion { q: number; ct: number; } interface FilaCalculada { q: number; precio: number; it: number; ct: number; bt: number; img: number | null; cmg: number | null; } interface SimuladorProduccionProps { ejercicioId: string; onComplete?: (puntuacion: number) => void; } export function SimuladorProduccion({ ejercicioId: _ejercicioId, onComplete }: SimuladorProduccionProps) { const [precio, setPrecio] = useState(80); const datosBase: FilaProduccion[] = [ { q: 0, ct: 200 }, { q: 1, ct: 250 }, { q: 2, ct: 290 }, { q: 3, ct: 320 }, { q: 4, ct: 360 }, { q: 5, ct: 420 }, { q: 6, ct: 500 }, { q: 7, ct: 600 }, { q: 8, ct: 720 }, ]; const datosCalculados: FilaCalculada[] = useMemo(() => { return datosBase.map((fila, index) => { const it = precio * fila.q; const bt = it - fila.ct; const img = index > 0 ? precio : null; const cmg = index > 0 ? fila.ct - datosBase[index - 1].ct : null; return { q: fila.q, precio, it, ct: fila.ct, bt, img, cmg, }; }); }, [precio]); const qOptima = useMemo(() => { let maxBT = -Infinity; let qOpt = 0; datosCalculados.forEach((fila) => { if (fila.bt > maxBT) { maxBT = fila.bt; qOpt = fila.q; } }); return qOpt; }, [datosCalculados]); const verificacionIMgCMg = useMemo(() => { const filasValidas = datosCalculados.filter(f => f.img !== null && f.cmg !== null); const filaOptima = filasValidas.find(f => f.q === qOptima); if (!filaOptima) return null; return { img: filaOptima.img, cmg: filaOptima.cmg, diferencia: Math.abs((filaOptima.img || 0) - (filaOptima.cmg || 0)), cumple: Math.abs((filaOptima.img || 0) - (filaOptima.cmg || 0)) < 5, }; }, [datosCalculados, qOptima]); const maxValor = Math.max( ...datosCalculados.map(d => Math.max(d.it, d.ct, d.bt > 0 ? d.bt : 0)) ); const escala = maxValor > 0 ? 140 / maxValor : 1; const handleCompletar = () => { if (onComplete) { onComplete(100); } return 100; }; return (
| Q | Precio (P) | IT = P × Q | CT | BT = IT - CT | IMg | CMg |
|---|---|---|---|---|---|---|
| {fila.q} | {fila.precio} | {fila.it} | {fila.ct} | = 0 ? 'text-success' : 'text-error'}`}> {fila.bt} | {fila.img !== null ? fila.img : '-'} | {fila.cmg !== null ? fila.cmg : '-'} |
Cantidad Óptima: Q = {qOptima}
Beneficio Máximo: BT = {datosCalculados.find(d => d.q === qOptima)?.bt} {' '}(${precio} × {qOptima} - {datosCalculados.find(d => d.q === qOptima)?.ct})
IMg = {verificacionIMgCMg.img}, CMg = {verificacionIMgCMg.cmg} {' '}(Diferencia: {verificacionIMgCMg.diferencia.toFixed(1)})
{verificacionIMgCMg.cumple ? '✓ La condición de optimalidad se cumple: IMg ≈ CMg' : 'La diferencia es significativa, pero el beneficio sigue siendo máximo en Q = ' + qOptima}
Ingreso Total (IT)
IT = P × Q
Beneficio Total (BT)
BT = IT - CT
Ingreso Marginal (IMg)
IMg = ΔIT / ΔQ = P (en competencia perfecta)
Condición de Optimalidad
IMg = CMg (producir hasta que el ingreso marginal iguale al costo marginal)