Loto / src /components /CompleteSystemAnalysis.tsx
Raí Santos
oi
4c1e4ec
import React, { useState, useEffect, useMemo, useCallback } from 'react';
import { Play, CheckCircle, AlertTriangle, Calculator, DollarSign, TrendingUp, Database, Target, Award } from 'lucide-react';
import { LotomaniaAlgorithm } from '../utils/lotomaniaAlgorithm';
import { useLotomaniaAPI } from '../hooks/useLotomaniaAPI';
import { LotomaniaGame, LotomaniaResult } from '../types';
interface GameAnalysisResult {
game: LotomaniaGame;
numbers: number[];
matches: number;
points: number;
isWinning: boolean;
prizeValue: number;
prizeDescription: string;
}
interface FinancialSummary {
totalCost: number;
totalPrizes: number;
netResult: number;
profitMargin: number;
winningGames: number;
pointsDistribution: Record<number, number>;
prizeDistribution: Record<number, { count: number; totalValue: number }>;
}
export const CompleteSystemAnalysis: React.FC = () => {
const [algorithm] = useState(() => new LotomaniaAlgorithm());
const [allGames, setAllGames] = useState<LotomaniaGame[]>([]);
const [isAnalyzing, setIsAnalyzing] = useState(false);
const [analysisResults, setAnalysisResults] = useState<GameAnalysisResult[]>([]);
const [financialSummary, setFinancialSummary] = useState<FinancialSummary | null>(null);
const [selectedConcurso, setSelectedConcurso] = useState<number | ''>('');
const { latestResult, fetchLatestResult, analyzeGameResult } = useLotomaniaAPI();
// Verificar e gerar todos os jogos
useEffect(() => {
console.log('🚀 Iniciando geração completa de jogos...');
const startTime = performance.now();
const games = algorithm.generateAllGames();
const endTime = performance.now();
console.log(`✅ Jogos gerados em ${(endTime - startTime).toFixed(2)}ms`);
console.log(`📊 Total de jogos: ${games.length}`);
const verticalGames = algorithm.getVerticalGames();
const horizontalGames = algorithm.getHorizontalGames();
console.log(`🔹 Jogos Verticais: ${verticalGames.length}`);
console.log(`🔸 Jogos Horizontais: ${horizontalGames.length}`);
setAllGames(games);
}, [algorithm]);
// Estatísticas dos jogos
const gameStats = useMemo(() => {
if (allGames.length === 0) return null;
const verticalGames = allGames.filter(g => g.type === 'vertical');
const horizontalGames = allGames.filter(g => g.type === 'horizontal');
const stats = algorithm.getGameStatistics();
return {
...stats,
verticalCount: verticalGames.length,
horizontalCount: horizontalGames.length,
isCorrect: verticalGames.length === 252 && horizontalGames.length === 252,
expectedTotal: 504,
actualTotal: allGames.length
};
}, [allGames, algorithm]);
// Análise completa contra resultado da Lotomania
const performCompleteAnalysis = useCallback(async () => {
if (!latestResult || allGames.length === 0) {
console.error('❌ Dados insuficientes para análise');
return;
}
setIsAnalyzing(true);
console.log('🔄 Iniciando análise completa de todos os jogos...');
console.log(`📊 Analisando ${allGames.length} jogos contra concurso ${latestResult.concurso}`);
const startTime = performance.now();
const results: GameAnalysisResult[] = [];
for (let i = 0; i < allGames.length; i++) {
const game = allGames[i];
const gameNumbers = algorithm.getNumbersFromGame(game);
const analysis = analyzeGameResult(gameNumbers, latestResult);
// Calcular valor do prêmio baseado nos dados oficiais
let prizeValue = 0;
let prizeDescription = 'Sem prêmio';
if (analysis.points >= 15 || analysis.points === 0) {
const premio = latestResult.premiacoes?.find(p => p.acertos === analysis.points);
if (premio) {
prizeValue = premio.valorPremio;
prizeDescription = premio.descricao;
}
}
results.push({
game,
numbers: gameNumbers,
matches: analysis.matches,
points: analysis.points,
isWinning: analysis.isWinning,
prizeValue,
prizeDescription
});
// Log progresso a cada 100 jogos
if ((i + 1) % 100 === 0) {
console.log(`📈 Analisados ${i + 1}/${allGames.length} jogos...`);
}
}
const endTime = performance.now();
console.log(`✅ Análise completa em ${(endTime - startTime).toFixed(2)}ms`);
setAnalysisResults(results);
// Calcular resumo financeiro
const GAME_COST = 3.00; // R$ 3,00 por jogo
const totalCost = allGames.length * GAME_COST;
const totalPrizes = results.reduce((sum, r) => sum + r.prizeValue, 0);
const netResult = totalPrizes - totalCost;
const profitMargin = totalCost > 0 ? (netResult / totalCost) * 100 : 0;
const winningGames = results.filter(r => r.isWinning).length;
// Distribuição de pontos
const pointsDistribution: Record<number, number> = {};
const prizeDistribution: Record<number, { count: number; totalValue: number }> = {};
results.forEach(r => {
pointsDistribution[r.points] = (pointsDistribution[r.points] || 0) + 1;
if (r.isWinning) {
if (!prizeDistribution[r.points]) {
prizeDistribution[r.points] = { count: 0, totalValue: 0 };
}
prizeDistribution[r.points].count++;
prizeDistribution[r.points].totalValue += r.prizeValue;
}
});
const financial: FinancialSummary = {
totalCost,
totalPrizes,
netResult,
profitMargin,
winningGames,
pointsDistribution,
prizeDistribution
};
setFinancialSummary(financial);
// Log resumo final
console.log('💰 ===== ANÁLISE FINANCEIRA COMPLETA =====');
console.log(`💸 Custo Total: R$ ${totalCost.toLocaleString('pt-BR', { minimumFractionDigits: 2 })}`);
console.log(`🏆 Prêmios Totais: R$ ${totalPrizes.toLocaleString('pt-BR', { minimumFractionDigits: 2 })}`);
console.log(`📊 Resultado Líquido: R$ ${netResult.toLocaleString('pt-BR', { minimumFractionDigits: 2 })}`);
console.log(`📈 Margem: ${profitMargin.toFixed(2)}%`);
console.log(`🎯 Jogos Premiados: ${winningGames}/${allGames.length} (${((winningGames/allGames.length)*100).toFixed(2)}%)`);
setIsAnalyzing(false);
}, [latestResult, allGames, algorithm, analyzeGameResult]);
// Auto-executar análise quando resultado estiver disponível
useEffect(() => {
if (latestResult && allGames.length > 0 && analysisResults.length === 0) {
performCompleteAnalysis();
}
}, [latestResult, allGames, analysisResults.length, performCompleteAnalysis]);
// Buscar resultado mais recente ao carregar
useEffect(() => {
fetchLatestResult();
}, [fetchLatestResult]);
return (
<div className="space-y-6">
{/* Header */}
<div className="bg-gradient-to-r from-blue-600 to-purple-600 text-white p-6 rounded-lg">
<h2 className="text-2xl font-bold flex items-center gap-2">
<Database className="w-6 h-6" />
Análise Completa do Sistema Lotomania
</h2>
<p className="text-blue-100 mt-2">
Verificação completa da lógica, geração de jogos e análise financeira detalhada
</p>
</div>
{/* Verificação do Algoritmo */}
<div className="bg-white rounded-lg shadow-lg p-6">
<h3 className="text-xl font-semibold mb-4 flex items-center gap-2">
<Target className="w-5 h-5 text-blue-600" />
Verificação do Algoritmo
</h3>
{gameStats ? (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<div className={`p-4 rounded-lg border-l-4 ${
gameStats.isCorrect ? 'border-green-500 bg-green-50' : 'border-red-500 bg-red-50'
}`}>
<div className="flex items-center gap-2">
{gameStats.isCorrect ? (
<CheckCircle className="w-5 h-5 text-green-600" />
) : (
<AlertTriangle className="w-5 h-5 text-red-600" />
)}
<span className="font-semibold">Status</span>
</div>
<p className={`text-sm ${gameStats.isCorrect ? 'text-green-700' : 'text-red-700'}`}>
{gameStats.isCorrect ? 'Algoritmo Correto ✅' : 'Algoritmo com Problemas ❌'}
</p>
</div>
<div className="p-4 rounded-lg border-l-4 border-blue-500 bg-blue-50">
<div className="flex items-center gap-2">
<Calculator className="w-5 h-5 text-blue-600" />
<span className="font-semibold">Total de Jogos</span>
</div>
<p className="text-2xl font-bold text-blue-800">
{gameStats.actualTotal}
</p>
<p className="text-sm text-blue-600">
Esperado: {gameStats.expectedTotal}
</p>
</div>
<div className="p-4 rounded-lg border-l-4 border-purple-500 bg-purple-50">
<div className="flex items-center gap-2">
<span className="w-5 h-5 bg-purple-600 rounded"></span>
<span className="font-semibold">Jogos Verticais</span>
</div>
<p className="text-2xl font-bold text-purple-800">
{gameStats.verticalCount}
</p>
<p className="text-sm text-purple-600">
Esperado: 252
</p>
</div>
<div className="p-4 rounded-lg border-l-4 border-orange-500 bg-orange-50">
<div className="flex items-center gap-2">
<span className="w-5 h-5 bg-orange-600 rounded"></span>
<span className="font-semibold">Jogos Horizontais</span>
</div>
<p className="text-2xl font-bold text-orange-800">
{gameStats.horizontalCount}
</p>
<p className="text-sm text-orange-600">
Esperado: 252
</p>
</div>
</div>
) : (
<div className="animate-pulse space-y-4">
<div className="h-4 bg-gray-200 rounded w-1/4"></div>
<div className="h-20 bg-gray-200 rounded"></div>
</div>
)}
</div>
{/* Informações do Resultado da Lotomania */}
{latestResult && (
<div className="bg-white rounded-lg shadow-lg p-6">
<h3 className="text-xl font-semibold mb-4 flex items-center gap-2">
<Award className="w-5 h-5 text-green-600" />
Resultado Oficial da Lotomania
</h3>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
<div className="p-4 bg-green-50 rounded-lg">
<span className="text-sm text-green-600">Concurso</span>
<p className="text-2xl font-bold text-green-800">{latestResult.concurso}</p>
</div>
<div className="p-4 bg-blue-50 rounded-lg">
<span className="text-sm text-blue-600">Data</span>
<p className="text-lg font-semibold text-blue-800">{latestResult.data}</p>
</div>
<div className="p-4 bg-yellow-50 rounded-lg">
<span className="text-sm text-yellow-600">Valor Arrecadado</span>
<p className="text-lg font-semibold text-yellow-800">
R$ {(latestResult.valorArrecadado || 0).toLocaleString('pt-BR')}
</p>
</div>
<div className={`p-4 rounded-lg ${latestResult.acumulado ? 'bg-red-50' : 'bg-green-50'}`}>
<span className={`text-sm ${latestResult.acumulado ? 'text-red-600' : 'text-green-600'}`}>
Status
</span>
<p className={`text-lg font-semibold ${latestResult.acumulado ? 'text-red-800' : 'text-green-800'}`}>
{latestResult.acumulado ? 'Acumulou' : 'Teve Ganhador'}
</p>
</div>
</div>
{/* Números Sorteados */}
<div className="mb-4">
<h4 className="font-semibold mb-2">Números Sorteados:</h4>
<div className="grid grid-cols-10 gap-2">
{latestResult.numeros.map((numero, index) => (
<div
key={index}
className="bg-blue-600 text-white rounded-lg p-2 text-center font-bold"
>
{numero === 0 ? '00' : numero.toString().padStart(2, '0')}
</div>
))}
</div>
</div>
</div>
)}
{/* Controles de Análise */}
<div className="bg-white rounded-lg shadow-lg p-6">
<h3 className="text-xl font-semibold mb-4 flex items-center gap-2">
<Play className="w-5 h-5 text-blue-600" />
Análise Completa
</h3>
<div className="flex flex-col md:flex-row gap-4 items-center">
<button
onClick={performCompleteAnalysis}
disabled={isAnalyzing || !latestResult || allGames.length === 0}
className={`flex items-center gap-2 px-6 py-3 rounded-lg font-semibold transition-all ${
isAnalyzing || !latestResult || allGames.length === 0
? 'bg-gray-400 cursor-not-allowed'
: 'bg-blue-600 hover:bg-blue-700 text-white shadow-lg hover:shadow-xl'
}`}
>
{isAnalyzing ? (
<>
<div className="animate-spin rounded-full h-5 w-5 border-b-2 border-white"></div>
Analisando todos os {allGames.length} jogos...
</>
) : (
<>
<Play className="w-5 h-5" />
Analisar Todos os {allGames.length} Jogos
</>
)}
</button>
{analysisResults.length > 0 && (
<div className="text-sm text-gray-600">
✅ Análise completa realizada com {analysisResults.length} jogos
</div>
)}
</div>
</div>
{/* Resumo Financeiro */}
{financialSummary && (
<div className="bg-white rounded-lg shadow-lg p-6">
<h3 className="text-xl font-semibold mb-4 flex items-center gap-2">
<DollarSign className="w-5 h-5 text-green-600" />
Análise Financeira Completa
</h3>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
<div className="p-4 bg-red-50 rounded-lg border-l-4 border-red-500">
<span className="text-sm text-red-600">Custo Total</span>
<p className="text-2xl font-bold text-red-800">
R$ {financialSummary.totalCost.toLocaleString('pt-BR', { minimumFractionDigits: 2 })}
</p>
<p className="text-sm text-red-600">
{allGames.length} jogos × R$ 3,00
</p>
</div>
<div className="p-4 bg-green-50 rounded-lg border-l-4 border-green-500">
<span className="text-sm text-green-600">Prêmios Totais</span>
<p className="text-2xl font-bold text-green-800">
R$ {financialSummary.totalPrizes.toLocaleString('pt-BR', { minimumFractionDigits: 2 })}
</p>
<p className="text-sm text-green-600">
{financialSummary.winningGames} jogos premiados
</p>
</div>
<div className={`p-4 rounded-lg border-l-4 ${
financialSummary.netResult >= 0 ? 'border-blue-500 bg-blue-50' : 'border-orange-500 bg-orange-50'
}`}>
<span className={`text-sm ${
financialSummary.netResult >= 0 ? 'text-blue-600' : 'text-orange-600'
}`}>
Resultado Líquido
</span>
<p className={`text-2xl font-bold ${
financialSummary.netResult >= 0 ? 'text-blue-800' : 'text-orange-800'
}`}>
{financialSummary.netResult >= 0 ? '+' : ''}R$ {financialSummary.netResult.toLocaleString('pt-BR', { minimumFractionDigits: 2 })}
</p>
<p className={`text-sm ${
financialSummary.netResult >= 0 ? 'text-blue-600' : 'text-orange-600'
}`}>
{financialSummary.profitMargin >= 0 ? 'Lucro' : 'Prejuízo'}: {Math.abs(financialSummary.profitMargin).toFixed(2)}%
</p>
</div>
<div className="p-4 bg-purple-50 rounded-lg border-l-4 border-purple-500">
<span className="text-sm text-purple-600">Taxa de Acerto</span>
<p className="text-2xl font-bold text-purple-800">
{((financialSummary.winningGames / allGames.length) * 100).toFixed(2)}%
</p>
<p className="text-sm text-purple-600">
{financialSummary.winningGames} de {allGames.length} jogos
</p>
</div>
</div>
{/* Distribuição de Pontos */}
<div className="mt-6">
<h4 className="font-semibold mb-3">Distribuição de Pontos:</h4>
<div className="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-8 gap-3">
{Object.entries(financialSummary.pointsDistribution)
.sort(([a], [b]) => parseInt(b) - parseInt(a))
.map(([points, count]) => {
const prize = financialSummary.prizeDistribution[parseInt(points)];
const isWinning = prize && prize.count > 0;
return (
<div
key={points}
className={`p-3 rounded-lg text-center ${
isWinning ? 'bg-green-100 border border-green-300' : 'bg-gray-100'
}`}
>
<div className={`font-bold text-lg ${
isWinning ? 'text-green-800' : 'text-gray-700'
}`}>
{points} pts
</div>
<div className={`text-sm ${
isWinning ? 'text-green-600' : 'text-gray-600'
}`}>
{count} jogos
</div>
{isWinning && (
<div className="text-xs text-green-600 font-semibold">
R$ {prize.totalValue.toLocaleString('pt-BR', { maximumFractionDigits: 0 })}
</div>
)}
</div>
);
})}
</div>
</div>
</div>
)}
{/* Confirmação do Sistema */}
<div className="bg-gradient-to-r from-green-500 to-blue-500 text-white p-6 rounded-lg">
<h3 className="text-xl font-semibold mb-3 flex items-center gap-2">
<CheckCircle className="w-6 h-6" />
Confirmação do Sistema
</h3>
<div className="space-y-2">
<p className="flex items-center gap-2">
<span className="w-2 h-2 bg-white rounded-full"></span>
<strong>Algoritmo Verified:</strong> Gera exatamente {gameStats?.actualTotal} jogos conforme especificado
</p>
<p className="flex items-center gap-2">
<span className="w-2 h-2 bg-white rounded-full"></span>
<strong>Jogos Verticais:</strong> {gameStats?.verticalCount} jogos (colunas marcadas)
</p>
<p className="flex items-center gap-2">
<span className="w-2 h-2 bg-white rounded-full"></span>
<strong>Jogos Horizontais:</strong> {gameStats?.horizontalCount} jogos (linhas marcadas)
</p>
<p className="flex items-center gap-2">
<span className="w-2 h-2 bg-white rounded-full"></span>
<strong>Comparação Real:</strong> Cada jogo é comparado com resultado oficial da Caixa
</p>
<p className="flex items-center gap-2">
<span className="w-2 h-2 bg-white rounded-full"></span>
<strong>Análise Financeira:</strong> Custo total vs. prêmios reais obtidos
</p>
<p className="flex items-center gap-2">
<span className="w-2 h-2 bg-white rounded-full"></span>
<strong>Dados Oficiais:</strong> API da Caixa Econômica Federal integrada
</p>
</div>
</div>
</div>
);
};
export default CompleteSystemAnalysis;