import React, { useState, useMemo } from 'react'; import { Target, TrendingUp, Filter, Eye } from 'lucide-react'; import { LotomaniaGame, LotomaniaResult } from '../types'; import { LotomaniaAlgorithm } from '../utils/lotomaniaAlgorithm'; interface GameByGameResultsProps { allGames: LotomaniaGame[]; algorithm: LotomaniaAlgorithm; currentResult: LotomaniaResult; } interface GameResultDetailed { game: LotomaniaGame; numbers: number[]; matchedNumbers: number[]; nonMatchedNumbers: number[]; points: number; prizeValue: number; prizeDescription: string; netProfit: number; isWinning: boolean; } export const GameByGameResults: React.FC = ({ allGames, algorithm, currentResult }) => { const [filterType, setFilterType] = useState<'all' | 'vertical' | 'horizontal'>('all'); const [filterPoints, setFilterPoints] = useState<'all' | 'winning' | '15+' | '16' | '17+' | '18' | '19+' | '20' | '0'>('all'); const [showGrid, setShowGrid] = useState(true); const [currentPage, setCurrentPage] = useState(1); const GAMES_PER_PAGE = 10; // Analisar todos os jogos const gameResults = useMemo(() => { return allGames.map(game => { const gameNumbers = algorithm.getNumbersFromGame(game); const matchedNumbers = gameNumbers.filter(num => currentResult.numeros.includes(num)); const nonMatchedNumbers = gameNumbers.filter(num => !currentResult.numeros.includes(num)); let points = matchedNumbers.length; let prizeValue = 0; let prizeDescription = 'Sem prêmio'; // Verificar premiação oficial const premio = currentResult.premiacoes?.find(p => p.acertos === points); if (premio && points >= 15) { prizeValue = premio.valorPremio; prizeDescription = premio.descricao; } else if (points === 0) { const premioZero = currentResult.premiacoes?.find(p => p.acertos === 0); if (premioZero) { prizeValue = premioZero.valorPremio; prizeDescription = premioZero.descricao; } } const netProfit = prizeValue - 3.00; return { game, numbers: gameNumbers, matchedNumbers, nonMatchedNumbers, points, prizeValue, prizeDescription, netProfit, isWinning: prizeValue > 0 }; }); }, [allGames, algorithm, currentResult]); // Filtrar resultados const filteredResults = useMemo(() => { let filtered = gameResults; if (filterType !== 'all') { filtered = filtered.filter(r => r.game.type === filterType); } if (filterPoints === 'winning') { filtered = filtered.filter(r => r.isWinning); } else if (filterPoints === '20') { filtered = filtered.filter(r => r.points === 20); } else if (filterPoints === '18') { filtered = filtered.filter(r => r.points === 18); } else if (filterPoints === '16') { filtered = filtered.filter(r => r.points === 16); } else if (filterPoints === '0') { filtered = filtered.filter(r => r.points === 0); } else if (filterPoints !== 'all') { const minPoints = parseInt(filterPoints.replace('+', '')); filtered = filtered.filter(r => r.points >= minPoints); } return filtered; }, [gameResults, filterType, filterPoints]); // Paginação const totalPages = Math.ceil(filteredResults.length / GAMES_PER_PAGE); const paginatedResults = filteredResults.slice( (currentPage - 1) * GAMES_PER_PAGE, currentPage * GAMES_PER_PAGE ); // Estatísticas resumidas const stats = useMemo(() => { const totalGames = filteredResults.length; const winningGames = filteredResults.filter(r => r.isWinning).length; const totalCost = totalGames * 3.00; const totalPrizes = filteredResults.reduce((sum, r) => sum + r.prizeValue, 0); // Distribuição por pontos const pointsDistribution = filteredResults.reduce((acc, r) => { acc[r.points] = (acc[r.points] || 0) + 1; return acc; }, {} as Record); return { totalGames, winningGames, totalCost, totalPrizes, netResult: totalPrizes - totalCost, winRate: (winningGames / totalGames) * 100, pointsDistribution }; }, [filteredResults]); // Renderizar grid de um jogo const renderGameGrid = (result: GameResultDetailed) => { if (!showGrid) return null; return (
🎯 Grid Visual - Jogo #{result.game.id}
{/* Grid compacto 10x10 */}
{Array.from({ length: 100 }, (_, i) => { const number = i; const isMarked = result.numbers.includes(number); const isHit = result.matchedNumbers.includes(number); const wasDrawn = currentResult.numeros.includes(number); let cellClass = 'w-5 h-5 text-[8px] font-bold flex items-center justify-center border'; if (isMarked && isHit) { cellClass += ' bg-green-600 text-white'; // Marcado e acertou } else if (isMarked && !isHit) { cellClass += ' bg-blue-600 text-white'; // Marcado mas não acertou } else if (!isMarked && wasDrawn) { cellClass += ' bg-yellow-400 text-black'; // Não marcado mas saiu } else { cellClass += ' bg-white text-gray-600'; // Normal } return (
{number === 0 ? '00' : number.toString().padStart(2, '0')}
); })}
{/* Legenda compacta */}
Acertou ({result.matchedNumbers.length})
Marcado ({result.numbers.length - result.matchedNumbers.length})
Perdeu ({currentResult.numeros.filter(n => !result.numbers.includes(n)).length})
); }; return (
{/* Header */}

Resultado Jogo por Jogo

Análise individual de cada um dos {allGames.length} jogos contra o concurso {currentResult.concurso}

{/* Estatísticas Resumidas */}
Jogos Analisados

{stats.totalGames}

Jogos Premiados

{stats.winningGames}

{stats.winRate.toFixed(1)}%

Total Prêmios

R$ {stats.totalPrizes.toLocaleString('pt-BR', { maximumFractionDigits: 0 })}

Custo Total

R$ {stats.totalCost.toLocaleString('pt-BR', { maximumFractionDigits: 0 })}

= 0 ? 'border-green-500 bg-green-50' : 'border-red-500 bg-red-50' }`}> = 0 ? 'text-green-600' : 'text-red-600'}`}> Resultado

= 0 ? 'text-green-800' : 'text-red-800'}`}> {stats.netResult >= 0 ? '+' : ''}R$ {stats.netResult.toLocaleString('pt-BR', { maximumFractionDigits: 0 })}

{/* Filtros */}
{filteredResults.length} resultado(s)
{/* Lista de Resultados */}
{paginatedResults.map((result) => (
{/* Info do Jogo */}
#{result.game.id}
{result.game.type === 'vertical' ? '🔹 Vertical' : '🔸 Horizontal'}
Fase {result.game.phase}, Ciclo {result.game.cycle}
Pontuação: {result.points} pontos
Prêmio: R$ {result.prizeValue.toLocaleString('pt-BR', { minimumFractionDigits: 2 })}
Resultado: = 0 ? 'text-green-600' : 'text-red-600'}`}> {result.netProfit >= 0 ? '+' : ''}R$ {result.netProfit.toLocaleString('pt-BR', { minimumFractionDigits: 2 })}
{result.isWinning && (
🏆 {result.prizeDescription}
)}
{/* Grid Visual */}
{renderGameGrid(result)}
{/* Números Detalhados */}
✅ Acertos ({result.matchedNumbers.length})
{result.matchedNumbers.map(num => ( {num === 0 ? '00' : num.toString().padStart(2, '0')} ))}
⭐ Perdidos ({currentResult.numeros.filter(n => !result.numbers.includes(n)).length})
{currentResult.numeros .filter(n => !result.numbers.includes(n)) .slice(0, 8) .map(num => ( {num === 0 ? '00' : num.toString().padStart(2, '0')} ))} {currentResult.numeros.filter(n => !result.numbers.includes(n)).length > 8 && ( +{currentResult.numeros.filter(n => !result.numbers.includes(n)).length - 8} )}
))}
{/* Paginação */} {totalPages > 1 && (
Página {currentPage} de {totalPages}
)} {/* Distribuição de Pontos */}

Distribuição de Pontuação

{Object.entries(stats.pointsDistribution) .sort(([a], [b]) => parseInt(b) - parseInt(a)) .map(([points, count]) => { const isWinning = parseInt(points) >= 15 || parseInt(points) === 0; return (
{points}pts
{count} jogos
); })}
); }; export default GameByGameResults;