import React, { useMemo } from 'react'; import { Target, Calculator, TrendingUp, Zap, Percent, BarChart3, DollarSign, PieChart } from 'lucide-react'; import { LotomaniaGame, LotomaniaResult } from '../types'; import { Bar } from 'react-chartjs-2'; import '../utils/chartSetup'; // Importar configuração do Chart.js interface ProbabilityCalculatorProps { verticalGames: LotomaniaGame[]; horizontalGames: LotomaniaGame[]; latestResult?: LotomaniaResult | null; } const ProbabilityCalculator: React.FC = ({ verticalGames, horizontalGames, latestResult }) => { // Removendo variáveis não utilizadas por enquanto // const [selectedScenario, setSelectedScenario] = useState<'single' | 'multiple' | 'strategy'>('strategy'); // const [customNumbers, setCustomNumbers] = useState([]); // Cálculos de probabilidade teórica const theoreticalProbabilities = useMemo(() => { // Probabilidades baseadas na combinatória da Lotomania // Total de números: 100, Números sorteados: 20, Números jogados: 50 const totalNumbers = 100; const drawnNumbers = 20; const playedNumbers = 50; // Função para calcular combinações C(n, k) const combination = (n: number, k: number): number => { if (k > n || k < 0) return 0; if (k === 0 || k === n) return 1; let result = 1; for (let i = 0; i < Math.min(k, n - k); i++) { result = result * (n - i) / (i + 1); } return result; }; // Função para calcular probabilidade de acertar exatamente k números const calculateProbability = (k: number): number => { const numerator = combination(playedNumbers, k) * combination(totalNumbers - playedNumbers, drawnNumbers - k); const denominator = combination(totalNumbers, drawnNumbers); return numerator / denominator; }; return { exact0: calculateProbability(0), exact15: calculateProbability(15), exact16: calculateProbability(16), exact17: calculateProbability(17), exact18: calculateProbability(18), exact19: calculateProbability(19), exact20: calculateProbability(20), winning15Plus: calculateProbability(15) + calculateProbability(16) + calculateProbability(17) + calculateProbability(18) + calculateProbability(19) + calculateProbability(20) + calculateProbability(0), winning17Plus: calculateProbability(17) + calculateProbability(18) + calculateProbability(19) + calculateProbability(20) + calculateProbability(0), winning18Plus: calculateProbability(18) + calculateProbability(19) + calculateProbability(20) + calculateProbability(0), winning19Plus: calculateProbability(19) + calculateProbability(20) + calculateProbability(0), winning20: calculateProbability(20) + calculateProbability(0), }; }, []); // Cálculos para estratégia completa const strategyCalculations = useMemo(() => { const totalVerticalGames = verticalGames.length; const totalHorizontalGames = horizontalGames.length; const totalGames = totalVerticalGames + totalHorizontalGames; // Probabilidade de pelo menos um prêmio na estratégia completa const probNoWin17Plus = Math.pow(1 - theoreticalProbabilities.winning17Plus, totalGames); const probAtLeastOneWin17Plus = 1 - probNoWin17Plus; const probNoWin20 = Math.pow(1 - theoreticalProbabilities.winning20, totalGames); const probAtLeastOneWin20 = 1 - probNoWin20; return { totalGames, totalVerticalGames, totalHorizontalGames, probAtLeastOneWin17Plus: probAtLeastOneWin17Plus * 100, probAtLeastOneWin20: probAtLeastOneWin20 * 100, expectedWins17Plus: totalGames * theoreticalProbabilities.winning17Plus, expectedWins20: totalGames * theoreticalProbabilities.winning20, expectedValue: totalGames * ( theoreticalProbabilities.exact17 * 5 + // Prêmio estimado 17 pontos theoreticalProbabilities.exact18 * 50 + // Prêmio estimado 18 pontos theoreticalProbabilities.exact19 * 1000 + // Prêmio estimado 19 pontos theoreticalProbabilities.winning20 * 100000 // Prêmio estimado 20/0 pontos ) }; }, [verticalGames, horizontalGames, theoreticalProbabilities]); // Cálculos de ganhos reais baseados no último concurso const realPrizesAnalysis = useMemo(() => { if (!latestResult || !latestResult.premiacoes) { return null; } const totalGames = 504; const gameCost = 3.00; const totalInvestment = totalGames * gameCost; // R$ 1.512,00 // Organizar prêmios por faixa de pontos const prizesByPoints: Record = {}; latestResult.premiacoes.forEach(premio => { if (premio.acertos !== undefined && premio.valorPremio !== undefined) { prizesByPoints[premio.acertos] = { value: premio.valorPremio, description: premio.descricao || `${premio.acertos} acertos` }; } }); // Calcular ganhos potenciais para nossa estratégia const potentialGains = { 15: prizesByPoints[15]?.value || 0, 16: prizesByPoints[16]?.value || 0, 17: prizesByPoints[17]?.value || 0, 18: prizesByPoints[18]?.value || 0, 19: prizesByPoints[19]?.value || 0, 20: prizesByPoints[20]?.value || 0, 0: prizesByPoints[0]?.value || 0, // Prêmio de consolação }; // Estimativa de ganhos baseada em probabilidades const estimatedWinnings = Object.entries(potentialGains).reduce((total, [points, value]) => { const pointsNum = parseInt(points); let probability = 0; switch (pointsNum) { case 0: probability = theoreticalProbabilities.exact0; break; case 15: probability = theoreticalProbabilities.exact15; break; case 16: probability = theoreticalProbabilities.exact16; break; case 17: probability = theoreticalProbabilities.exact17; break; case 18: probability = theoreticalProbabilities.exact18; break; case 19: probability = theoreticalProbabilities.exact19; break; case 20: probability = theoreticalProbabilities.exact20; break; } const expectedGames = totalGames * probability; return total + (expectedGames * value); }, 0); const netResult = estimatedWinnings - totalInvestment; const roi = totalInvestment > 0 ? (netResult / totalInvestment) * 100 : 0; return { concurso: latestResult.concurso, data: latestResult.data, totalInvestment, estimatedWinnings, netResult, roi, prizesByPoints, acumulado: latestResult.acumulado, valorAcumulado: latestResult.valorAcumuladoProximoConcurso || 0 }; }, [latestResult, theoreticalProbabilities]); // Dados para gráficos const probabilityChartData = { labels: ['0 pontos', '17 pontos', '18 pontos', '19 pontos', '20 pontos'], datasets: [{ label: 'Probabilidade Individual (%)', data: [ theoreticalProbabilities.exact0 * 100, theoreticalProbabilities.exact17 * 100, theoreticalProbabilities.exact18 * 100, theoreticalProbabilities.exact19 * 100, theoreticalProbabilities.exact20 * 100 ], backgroundColor: [ 'rgba(34, 197, 94, 0.8)', 'rgba(59, 130, 246, 0.8)', 'rgba(245, 158, 11, 0.8)', 'rgba(239, 68, 68, 0.8)', 'rgba(168, 85, 247, 0.8)' ], borderColor: [ 'rgb(34, 197, 94)', 'rgb(59, 130, 246)', 'rgb(245, 158, 11)', 'rgb(239, 68, 68)', 'rgb(168, 85, 247)' ], borderWidth: 2 }] }; const strategyComparisonData = { labels: ['Vertical', 'Horizontal', 'Total'], datasets: [{ label: 'Prêmios Esperados (17+)', data: [ strategyCalculations.totalVerticalGames * theoreticalProbabilities.winning17Plus, strategyCalculations.totalHorizontalGames * theoreticalProbabilities.winning17Plus, strategyCalculations.expectedWins17Plus ], backgroundColor: 'rgba(59, 130, 246, 0.8)', borderColor: 'rgb(59, 130, 246)', borderWidth: 2 }, { label: 'Prêmios Máximos Esperados (20/0)', data: [ strategyCalculations.totalVerticalGames * theoreticalProbabilities.winning20, strategyCalculations.totalHorizontalGames * theoreticalProbabilities.winning20, strategyCalculations.expectedWins20 ], backgroundColor: 'rgba(239, 68, 68, 0.8)', borderColor: 'rgb(239, 68, 68)', borderWidth: 2 }] }; const StatCard: React.FC<{ title: string; value: string | number; icon: React.ReactNode; color: string; subtitle?: string; percentage?: boolean; }> = ({ title, value, icon, color, subtitle, percentage = false }) => (

{title}

{percentage && typeof value === 'number' ? `${value.toFixed(4)}%` : value}

{subtitle && (

{subtitle}

)}
{icon}
); return (
{/* Header */}

Calculadora de Probabilidades

Análise matemática das chances de premiação na sua estratégia

{/* Probabilidades Teóricas Individuais */}

Probabilidades Teóricas por Jogo Individual

} color="text-red-600" subtitle="20 acertos ou 0 acertos" percentage={true} /> } color="text-orange-600" subtitle="19 acertos exatos" percentage={true} /> } color="text-yellow-600" subtitle="18 acertos exatos" percentage={true} /> } color="text-green-600" subtitle="Qualquer premiação" percentage={true} />
{/* Análise da Estratégia Completa */}

Análise da Estratégia Completa

} color="text-blue-600" subtitle={`${strategyCalculations.totalVerticalGames} verticais + ${strategyCalculations.totalHorizontalGames} horizontais`} /> } color="text-red-600" subtitle="Pelo menos um 20/0 pontos" percentage={true} /> } color="text-green-600" subtitle="Pelo menos um prêmio 17+" percentage={true} /> } color="text-purple-600" subtitle="Expectativa matemática" />
{/* Simulador de Cenários */}

Simulador de Cenários

Investimento vs Retorno Esperado

Custo por jogo (R$ 3,00): R$ 3,00
Investimento total: R$ {(strategyCalculations.totalGames * 3.0).toLocaleString()}
Retorno esperado estimado: R$ {strategyCalculations.expectedValue.toLocaleString()}
ROI Esperado: (strategyCalculations.totalGames * 3.0) ? 'text-green-600' : 'text-red-600'}`}> {(((strategyCalculations.expectedValue / (strategyCalculations.totalGames * 3.0)) - 1) * 100).toFixed(2)}%

Métricas Avançadas

Jogos para 90% chance prêmio: {Math.ceil(Math.log(0.1) / Math.log(1 - theoreticalProbabilities.winning17Plus)).toLocaleString()}
Jogos para 50% chance prêmio máximo: {Math.ceil(Math.log(0.5) / Math.log(1 - theoreticalProbabilities.winning20)).toLocaleString()}
Frequência esperada prêmio: 1 a cada {Math.round(1 / theoreticalProbabilities.winning17Plus)} jogos
Cobertura da estratégia: 50% dos números
{/* Análise de Ganhos Reais */} {realPrizesAnalysis && (

Análise de Ganhos Reais - Concurso {realPrizesAnalysis.concurso}

{/* Prêmios por Faixa */}

💰 Prêmios por Faixa de Pontos

{Object.entries(realPrizesAnalysis.prizesByPoints) .sort(([a], [b]) => parseInt(b) - parseInt(a)) .map(([points, prize]) => (
= 18 ? 'text-red-600' : parseInt(points) >= 17 ? 'text-orange-600' : 'text-green-600' }`}> {points === '0' ? '0 pontos (consolação)' : `${points} pontos`} {prize.value.toLocaleString('pt-BR', { style: 'currency', currency: 'BRL' })}
))}
{realPrizesAnalysis.acumulado && (
Concurso Acumulado: {realPrizesAnalysis.valorAcumulado.toLocaleString('pt-BR', { style: 'currency', currency: 'BRL' })}
)}
{/* Análise Financeira */}

📊 Análise Financeira da Estratégia

💸 Investimento Total: {realPrizesAnalysis.totalInvestment.toLocaleString('pt-BR', { style: 'currency', currency: 'BRL' })}
504 jogos × R$ 3,00
💰 Ganho Estimado: {realPrizesAnalysis.estimatedWinnings.toLocaleString('pt-BR', { style: 'currency', currency: 'BRL' })}
Baseado em probabilidades
= 0 ? 'bg-green-50 border-green-200' : 'bg-red-50 border-red-200' }`}>
= 0 ? 'text-green-700' : 'text-red-700' }`}> {realPrizesAnalysis.netResult >= 0 ? '📈 Lucro Líquido:' : '📉 Prejuízo:'} = 0 ? 'text-green-800' : 'text-red-800' }`}> {realPrizesAnalysis.netResult.toLocaleString('pt-BR', { style: 'currency', currency: 'BRL' })}
= 0 ? 'text-green-600' : 'text-red-600' }`}> ROI: {realPrizesAnalysis.roi.toFixed(2)}%
🎯 Estratégia: {realPrizesAnalysis.roi >= 0 ? 'VIÁVEL' : 'ALTO RISCO'}
{/* Gráfico de Ganhos Potenciais */}

📈 Distribuição de Ganhos por Faixa

parseInt(a) - parseInt(b)) .map(points => points === '0' ? '0 pts' : `${points} pts`), datasets: [{ label: 'Valor do Prêmio (R$)', data: Object.entries(realPrizesAnalysis.prizesByPoints) .sort(([a], [b]) => parseInt(a) - parseInt(b)) .map(([, prize]) => prize.value), backgroundColor: [ 'rgba(34, 197, 94, 0.8)', // 0 pontos 'rgba(59, 130, 246, 0.8)', // 15 pontos 'rgba(245, 158, 11, 0.8)', // 16 pontos 'rgba(239, 68, 68, 0.8)', // 17 pontos 'rgba(168, 85, 247, 0.8)', // 18 pontos 'rgba(236, 72, 153, 0.8)', // 19 pontos 'rgba(14, 165, 233, 0.8)' // 20 pontos ], borderColor: [ 'rgb(34, 197, 94)', 'rgb(59, 130, 246)', 'rgb(245, 158, 11)', 'rgb(239, 68, 68)', 'rgb(168, 85, 247)', 'rgb(236, 72, 153)', 'rgb(14, 165, 233)' ], borderWidth: 2 }] }} options={{ responsive: true, plugins: { legend: { display: false }, title: { display: false } }, scales: { y: { beginAtZero: true, ticks: { callback: function(value) { return new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL', minimumFractionDigits: 0 }).format(value as number); } } } } }} />
{/* Insights e Recomendações */}
{((realPrizesAnalysis.estimatedWinnings / realPrizesAnalysis.totalInvestment) * 100).toFixed(1)}%
Taxa de Retorno
{Object.keys(realPrizesAnalysis.prizesByPoints).length}
Faixas de Prêmio
504
Jogos Analisados
)} {/* Aviso quando não há dados da API */} {!realPrizesAnalysis && (

Dados de Prêmios Indisponíveis

Aguardando dados do último concurso da API da Caixa para análise de ganhos reais.

)} {/* Disclaimer */}

Importante:

Os cálculos apresentados são baseados em probabilidades teóricas e não garantem resultados. A Lotomania é um jogo de azar e deve ser jogada com responsabilidade. Nunca aposte mais do que pode perder.

); }; export default ProbabilityCalculator;