import React, { useState, useEffect } from 'react';
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, LineChart, Line, PieChart, Pie, Cell } from 'recharts';
import { Calendar, TrendingUp, Target, Database, Calculator, Award, Plus, Download, Upload, RefreshCw, Save } from 'lucide-react';
const JamaicaLottoAnalyzer = () => {
const [gameType, setGameType] = useState('lotto'); // 'lotto' or 'superlotto'
const [historicalData, setHistoricalData] = useState({ lotto: [], superlotto: [] });
const [predictions, setPredictions] = useState([]);
const [hotNumbers, setHotNumbers] = useState([]);
const [coldNumbers, setColdNumbers] = useState([]);
const [selectedNumbers, setSelectedNumbers] = useState([]);
const [bonusNumber, setBonusNumber] = useState(null);
const [analysis, setAnalysis] = useState(null);
const [activeTab, setActiveTab] = useState('predictions');
const [isScrapingData, setIsScrapingData] = useState(false);
const [scrapingStatus, setScrapingStatus] = useState('');
// Manual input states
const [manualInputDate, setManualInputDate] = useState('');
const [manualInputNumbers, setManualInputNumbers] = useState([]);
const [manualInputBonus, setManualInputBonus] = useState('');
const [manualInputJackpot, setManualInputJackpot] = useState('');
const [showManualInput, setShowManualInput] = useState(false);
// Game configurations
const gameConfig = {
lotto: {
name: 'Lotto',
maxNumber: 38,
numbersCount: 6,
hasBonus: true,
drawDays: 'Wed & Sat',
ticketPrice: 'J$100',
startingJackpot: 'J$25M'
},
superlotto: {
name: 'Super Lotto',
maxNumber: 35,
numbersCount: 6,
hasBonus: false,
drawDays: 'Wed & Sat',
ticketPrice: 'J$200',
startingJackpot: 'J$70M'
}
};
const getCurrentConfig = () => gameConfig[gameType];
// Enhanced mock data generation for both games
const generateMockData = (type) => {
const config = gameConfig[type];
const data = [];
for (let i = 0; i < 150; i++) {
const date = new Date();
date.setDate(date.getDate() - (i * 3.5));
const numbers = [];
while (numbers.length < config.numbersCount) {
const num = Math.floor(Math.random() * config.maxNumber) + 1;
if (!numbers.includes(num)) {
numbers.push(num);
}
}
const bonus = config.hasBonus ? Math.floor(Math.random() * config.maxNumber) + 1 : null;
data.push({
date: date.toLocaleDateString(),
numbers: numbers.sort((a, b) => a - b),
bonus: bonus,
jackpot: Math.floor(Math.random() * 200000000) + (type === 'superlotto' ? 70000000 : 25000000)
});
}
return data.reverse();
};
const calculateFrequencies = (data) => {
const config = getCurrentConfig();
const frequencies = {};
for (let i = 1; i <= config.maxNumber; i++) {
frequencies[i] = 0;
}
data.forEach(draw => {
draw.numbers.forEach(num => {
frequencies[num]++;
});
if (draw.bonus && config.hasBonus) {
frequencies[draw.bonus] = (frequencies[draw.bonus] || 0) + 0.5; // Bonus counts as half
}
});
return frequencies;
};
const getHotColdNumbers = (frequencies) => {
const sorted = Object.entries(frequencies)
.map(([num, freq]) => ({ number: parseInt(num), frequency: freq }))
.sort((a, b) => b.frequency - a.frequency);
return {
hot: sorted.slice(0, 12),
cold: sorted.slice(-12).reverse()
};
};
const generatePredictions = (data) => {
const config = getCurrentConfig();
const frequencies = calculateFrequencies(data);
const { hot, cold } = getHotColdNumbers(frequencies);
// Strategy 1: Balanced approach
const balanced = [
...hot.slice(0, Math.floor(config.numbersCount / 2)).map(n => n.number),
...cold.slice(0, Math.floor(config.numbersCount / 2)).map(n => n.number)
];
while (balanced.length < config.numbersCount) {
const num = Math.floor(Math.random() * config.maxNumber) + 1;
if (!balanced.includes(num)) balanced.push(num);
}
// Strategy 2: Hot numbers focus
const hotFocus = hot.slice(0, config.numbersCount).map(n => n.number).sort((a, b) => a - b);
// Strategy 3: Pattern analysis (odd/even distribution)
const patternStrategy = [];
const targetOdds = Math.floor(config.numbersCount / 2);
let odds = 0, evens = 0;
while (patternStrategy.length < config.numbersCount) {
const num = Math.floor(Math.random() * config.maxNumber) + 1;
if (!patternStrategy.includes(num)) {
if (num % 2 === 1 && odds < targetOdds) {
patternStrategy.push(num);
odds++;
} else if (num % 2 === 0 && evens < (config.numbersCount - targetOdds)) {
patternStrategy.push(num);
evens++;
}
}
}
// Strategy 4: Range distribution
const ranges = [];
const rangeSize = Math.ceil(config.maxNumber / config.numbersCount);
for (let i = 0; i < config.numbersCount; i++) {
const start = i * rangeSize + 1;
const end = Math.min((i + 1) * rangeSize, config.maxNumber);
ranges.push([start, end]);
}
const rangeStrategy = ranges.map(range => {
return Math.floor(Math.random() * (range[1] - range[0] + 1)) + range[0];
});
return [
{ name: 'Balanced Hot/Cold', numbers: balanced.sort((a, b) => a - b), confidence: 76 },
{ name: 'Hot Numbers Focus', numbers: hotFocus, confidence: 72 },
{ name: 'Pattern Analysis', numbers: patternStrategy.sort((a, b) => a - b), confidence: 74 },
{ name: 'Range Distribution', numbers: rangeStrategy.sort((a, b) => a - b), confidence: 70 }
];
};
// Manual input functions
const toggleManualNumber = (number) => {
const config = getCurrentConfig();
if (manualInputNumbers.includes(number)) {
setManualInputNumbers(manualInputNumbers.filter(n => n !== number));
} else if (manualInputNumbers.length < config.numbersCount) {
setManualInputNumbers([...manualInputNumbers, number]);
}
};
const addManualEntry = () => {
const config = getCurrentConfig();
if (manualInputNumbers.length !== config.numbersCount || !manualInputDate) {
alert(`Please select exactly ${config.numbersCount} numbers and enter a date`);
return;
}
const newEntry = {
date: manualInputDate,
numbers: manualInputNumbers.sort((a, b) => a - b),
bonus: config.hasBonus ? parseInt(manualInputBonus) || null : null,
jackpot: parseInt(manualInputJackpot.replace(/[^0-9]/g, '')) || 0
};
const updatedData = { ...historicalData };
updatedData[gameType] = [newEntry, ...updatedData[gameType]];
setHistoricalData(updatedData);
// Reset manual input
setManualInputDate('');
setManualInputNumbers([]);
setManualInputBonus('');
setManualInputJackpot('');
setShowManualInput(false);
alert('Entry added successfully!');
};
// Database scraping simulation
const scrapeDatabase = async () => {
setIsScrapingData(true);
setScrapingStatus('Initializing scraper...');
// Simulate scraping process
const steps = [
'Connecting to Supreme Ventures...',
'Fetching Lotto historical data...',
'Parsing Lotto results...',
'Fetching Super Lotto data...',
'Parsing Super Lotto results...',
'Validating data integrity...',
'Generating CSV files...',
'Complete!'
];
for (let i = 0; i < steps.length; i++) {
setScrapingStatus(steps[i]);
await new Promise(resolve => setTimeout(resolve, 1000));
}
// Generate fresh data for both games
const newData = {
lotto: generateMockData('lotto'),
superlotto: generateMockData('superlotto')
};
setHistoricalData(newData);
setIsScrapingData(false);
setScrapingStatus('');
alert('Database updated successfully! In live version, CSV files would be generated.');
};
// Export to CSV
const exportToCSV = () => {
const data = historicalData[gameType];
if (!data.length) {
alert('No data to export');
return;
}
const config = getCurrentConfig();
const headers = ['Date', 'Numbers', config.hasBonus ? 'Bonus' : null, 'Jackpot'].filter(Boolean);
const csvContent = [
headers.join(','),
...data.map(row => [
row.date,
`"${row.numbers.join(' ')}"`,
config.hasBonus ? row.bonus || '' : null,
row.jackpot
].filter(cell => cell !== null).join(','))
].join('\n');
const blob = new Blob([csvContent], { type: 'text/csv' });
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `${config.name.toLowerCase()}_results.csv`;
a.click();
window.URL.revokeObjectURL(url);
};
useEffect(() => {
// Initialize with mock data
const initialData = {
lotto: generateMockData('lotto'),
superlotto: generateMockData('superlotto')
};
setHistoricalData(initialData);
}, []);
useEffect(() => {
// Update analysis when game type changes
const currentData = historicalData[gameType] || [];
if (currentData.length > 0) {
const frequencies = calculateFrequencies(currentData);
const { hot, cold } = getHotColdNumbers(frequencies);
setHotNumbers(hot);
setColdNumbers(cold);
setPredictions(generatePredictions(currentData));
}
// Clear selections when changing game type
setSelectedNumbers([]);
setBonusNumber(null);
}, [gameType, historicalData]);
const analyzeSelectedNumbers = () => {
const config = getCurrentConfig();
if (selectedNumbers.length !== config.numbersCount) return;
const frequencies = calculateFrequencies(historicalData[gameType]);
const analysis = selectedNumbers.map(num => ({
number: num,
frequency: frequencies[num],
lastSeen: findLastOccurrence(num)
}));
setAnalysis(analysis);
};
const findLastOccurrence = (number) => {
const data = historicalData[gameType];
for (let i = data.length - 1; i >= 0; i--) {
if (data[i].numbers.includes(number) || data[i].bonus === number) {
return data.length - i;
}
}
return 'Never';
};
const toggleNumber = (number) => {
const config = getCurrentConfig();
if (selectedNumbers.includes(number)) {
setSelectedNumbers(selectedNumbers.filter(n => n !== number));
} else if (selectedNumbers.length < config.numbersCount) {
setSelectedNumbers([...selectedNumbers, number]);
}
};
const renderNumberGrid = (isManualInput = false) => {
const config = getCurrentConfig();
const grid = [];
const currentNumbers = isManualInput ? manualInputNumbers : selectedNumbers;
const toggleFunction = isManualInput ? toggleManualNumber : toggleNumber;
for (let i = 1; i <= config.maxNumber; i++) {
const isSelected = currentNumbers.includes(i);
const isHot = hotNumbers.some(h => h.number === i);
const isCold = coldNumbers.some(c => c.number === i);
grid.push(
<button
key={i}
onClick={() => toggleFunction(i)}
className={`
w-10 h-10 m-1 rounded-lg font-bold text-sm transition-all
${isSelected ? 'bg-blue-600 text-white' : 'bg-gray-100 text-gray-700'}
${isHot ? 'ring-2 ring-red-400' : ''}
${isCold ? 'ring-2 ring-blue-400' : ''}
hover:scale-105 hover:shadow-md
`}
>
{i}
</button>
);
}
return grid;
};
const renderTab = (tabName, icon, label) => (
<button
onClick={() => setActiveTab(tabName)}
className={`
flex items-center px-4 py-2 rounded-lg font-medium transition-all
${activeTab === tabName
? 'bg-blue-600 text-white'
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
}
`}
>
{icon}
<span className="ml-2">{label}</span>
</button>
);
const currentConfig = getCurrentConfig();
const currentData = historicalData[gameType] || [];
return (
<div className="max-w-7xl mx-auto p-6 bg-gradient-to-br from-blue-50 to-purple-50 min-h-screen">
<div className="bg-white rounded-xl shadow-2xl p-8">
<h1 className="text-4xl font-bold text-center mb-2 bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent">
Jamaica Lottery Analyzer Pro
</h1>
<p className="text-center text-gray-600 mb-8">
Advanced prediction system for Supreme Ventures games
</p>
{/* Game Type Selector */}
<div className="flex justify-center mb-6">
<div className="bg-gray-100 rounded-lg p-1 flex">
<button
onClick={() => setGameType('lotto')}
className={`px-6 py-2 rounded-md font-medium transition-all ${
gameType === 'lotto'
? 'bg-blue-600 text-white shadow-md'
: 'text-gray-600 hover:text-gray-800'
}`}
>
Lotto (6/38)
</button>
<button
onClick={() => setGameType('superlotto')}
className={`px-6 py-2 rounded-md font-medium transition-all ${
gameType === 'superlotto'
? 'bg-purple-600 text-white shadow-md'
: 'text-gray-600 hover:text-gray-800'
}`}
>
Super Lotto (6/35)
</button>
</div>
</div>
{/* Game Info Bar */}
<div className="bg-gradient-to-r from-blue-100 to-purple-100 rounded-lg p-4 mb-6">
<div className="flex flex-wrap justify-center gap-6 text-sm">
<span><strong>Game:</strong> {currentConfig.name}</span>
<span><strong>Draw Days:</strong> {currentConfig.drawDays}</span>
<span><strong>Ticket:</strong> {currentConfig.ticketPrice}</span>
<span><strong>Starting Jackpot:</strong> {currentConfig.startingJackpot}</span>
<span><strong>Total Draws:</strong> {currentData.length}</span>
</div>
</div>
{/* Navigation Tabs */}
<div className="flex flex-wrap gap-3 mb-8 justify-center">
{renderTab('predictions', <Target className="w-4 h-4" />, 'Predictions')}
{renderTab('analysis', <TrendingUp className="w-4 h-4" />, 'Analysis')}
{renderTab('selector', <Calculator className="w-4 h-4" />, 'Number Selector')}
{renderTab('history', <Database className="w-4 h-4" />, 'Historical Data')}
{renderTab('manual', <Plus className="w-4 h-4" />, 'Manual Input')}
{renderTab('database', <Download className="w-4 h-4" />, 'Database')}
</div>
{/* Predictions Tab */}
{activeTab === 'predictions' && (
<div className="space-y-6">
<h2 className="text-2xl font-bold flex items-center">
<Award className="mr-2 text-yellow-500" />
{currentConfig.name} Predictions
</h2>
<div className="grid md:grid-cols-2 gap-6">
{predictions.map((pred, index) => (
<div key={index} className={`rounded-xl p-6 text-white ${
gameType === 'lotto'
? 'bg-gradient-to-r from-blue-500 to-blue-700'
: 'bg-gradient-to-r from-purple-500 to-purple-700'
}`}>
<h3 className="text-lg font-bold mb-3">{pred.name}</h3>
<div className="flex flex-wrap gap-2 mb-3">
{pred.numbers.map(num => (
<span key={num} className="bg-white text-gray-800 px-3 py-1 rounded-full font-bold">
{num}
</span>
))}
</div>
<div className="flex justify-between items-center">
<span className="text-sm opacity-90">Confidence Level</span>
<span className="font-bold">{pred.confidence}%</span>
</div>
</div>
))}
</div>
</div>
)}
{/* Analysis Tab */}
{activeTab === 'analysis' && (
<div className="space-y-6">
<div className="grid md:grid-cols-2 gap-8">
<div>
<h3 className="text-xl font-bold mb-4 text-red-600">🔥 Hot Numbers (Most Frequent)</h3>
<div className="space-y-2 max-h-64 overflow-y-auto">
{hotNumbers.map(item => (
<div key={item.number} className="flex justify-between items-center p-3 bg-red-50 rounded-lg">
<span className="font-bold text-lg">{item.number}</span>
<span className="text-sm text-gray-600">{item.frequency.toFixed(1)} times</span>
</div>
))}
</div>
</div>
<div>
<h3 className="text-xl font-bold mb-4 text-blue-600">❄️ Cold Numbers (Least Frequent)</h3>
<div className="space-y-2 max-h-64 overflow-y-auto">
{coldNumbers.map(item => (
<div key={item.number} className="flex justify-between items-center p-3 bg-blue-50 rounded-lg">
<span className="font-bold text-lg">{item.number}</span>
<span className="text-sm text-gray-600">{item.frequency.toFixed(1)} times</span>
</div>
))}
</div>
</div>
</div>
{hotNumbers.length > 0 && (
<div>
<h3 className="text-xl font-bold mb-4">Number Frequency Distribution</h3>
<ResponsiveContainer width="100%" height={400}>
<BarChart data={hotNumbers}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="number" />
<YAxis />
<Tooltip />
<Bar dataKey="frequency" fill={gameType === 'lotto' ? '#3b82f6' : '#8b5cf6'} />
</BarChart>
</ResponsiveContainer>
</div>
)}
</div>
)}
{/* Number Selector Tab */}
{activeTab === 'selector' && (
<div className="space-y-6">
<h2 className="text-2xl font-bold">Select Your {currentConfig.name} Numbers</h2>
<p className="text-gray-600">
Choose {currentConfig.numbersCount} numbers (1-{currentConfig.maxNumber}).
{currentConfig.hasBonus && ' Plus select a bonus number.'}
<br />
<span className="text-red-500">Red rings</span> = Hot numbers,
<span className="text-blue-500 ml-2">Blue rings</span> = Cold numbers
</p>
<div className="bg-gray-50 p-6 rounded-xl">
<div className="flex flex-wrap justify-center">
{renderNumberGrid()}
</div>
</div>
{currentConfig.hasBonus && (
<div className="text-center">
<h3 className="text-lg font-bold mb-3">Bonus Number (Optional)</h3>
<div className="flex flex-wrap justify-center gap-2 max-w-md mx-auto">
{Array.from({length: currentConfig.maxNumber}, (_, i) => i + 1).map(num => (
<button
key={num}
onClick={() => setBonusNumber(bonusNumber === num ? null : num)}
className={`
w-8 h-8 rounded-full text-sm font-bold transition-all
${bonusNumber === num
? 'bg-yellow-500 text-white'
: 'bg-gray-200 text-gray-700 hover:bg-gray-300'
}
`}
>
{num}
</button>
))}
</div>
</div>
)}
<div className="text-center">
<p className="text-lg mb-4">
Selected: <span className="font-bold text-blue-600">{selectedNumbers.join(', ')}</span>
({selectedNumbers.length}/{currentConfig.numbersCount})
{bonusNumber && <span className="text-yellow-600 ml-2">Bonus: {bonusNumber}</span>}
</p>
<button
onClick={analyzeSelectedNumbers}
disabled={selectedNumbers.length !== currentConfig.numbersCount}
className="bg-blue-600 text-white px-6 py-3 rounded-lg font-bold disabled:bg-gray-300 hover:bg-blue-700 transition-colors"
>
Analyze Selection
</button>
</div>
{analysis && (
<div className="bg-white border rounded-xl p-6">
<h3 className="text-xl font-bold mb-4">Selection Analysis</h3>
<div className="grid md:grid-cols-3 gap-4">
{analysis.map(item => (
<div key={item.number} className="p-4 bg-gray-50 rounded-lg text-center">
<div className="text-2xl font-bold text-blue-600">{item.number}</div>
<div className="text-sm text-gray-600">Appeared {item.frequency.toFixed(1)} times</div>
<div className="text-sm text-gray-600">Last seen: {item.lastSeen} draws ago</div>
</div>
))}
</div>
</div>
)}
</div>
)}
{/* History Tab */}
{activeTab === 'history' && (
<div className="space-y-6">
<div className="flex justify-between items-center">
<h2 className="text-2xl font-bold">{currentConfig.name} Draw History</h2>
<button
onClick={exportToCSV}
className="flex items-center bg-green-600 text-white px-4 py-2 rounded-lg hover:bg-green-700 transition-colors"
>
<Download className="w-4 h-4 mr-2" />
Export CSV
</button>
</div>
<div className="overflow-x-auto">
<table className="w-full border-collapse">
<thead>
<tr className="bg-gray-100">
<th className="border p-3 text-left">Date</th>
<th className="border p-3 text-left">Winning Numbers</th>
{currentConfig.hasBonus && <th className="border p-3 text-left">Bonus</th>}
<th className="border p-3 text-left">Jackpot</th>
</tr>
</thead>
<tbody>
{currentData.slice(-25).reverse().map((draw, index) => (
<tr key={index} className="hover:bg-gray-50">
<td className="border p-3">{draw.date}</td>
<td className="border p-3">
<div className="flex gap-1 flex-wrap">
{draw.numbers.map(num => (
<span key={num} className="bg-blue-100 px-2 py-1 rounded text-sm font-bold">
{num}
</span>
))}
</div>
</td>
{currentConfig.hasBonus && (
<td className="border p-3">
{draw.bonus && (
<span className="bg-yellow-100 px-2 py-1 rounded text-sm font-bold">
{draw.bonus}
</span>
)}
</td>
)}
<td className="border p-3 font-bold">J${draw.jackpot.toLocaleString()}</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
)}
{/* Manual Input Tab */}
{activeTab === 'manual' && (
<div className="space-y-6">
<h2 className="text-2xl font-bold flex items-center">
<Plus className="mr-2 text-green-500" />
Manual {currentConfig.name} Entry
</h2>
<div className="bg-gray-50 rounded-xl p-6">
<div className="grid md:grid-cols-2 gap-6 mb-6">
<div>
<label className="block text-sm font-bold text-gray-700 mb-2">Draw Date</label>
<input
type="date"
value={manualInputDate}
onChange={(e) => setManualInputDate(e.target.value)}
className="w-full p-3 border rounded-lg focus:ring-2 focus:ring-blue-500"
/>
</div>
<div>
<label className="block text-sm font-bold text-gray-700 mb-2">Jackpot Amount</label>
<input
type="text"
placeholder="e.g., 50000000"
value={manualInputJackpot}
onChange={(e) => setManualInputJackpot(e.target.value)}
className="w-full p-3 border rounded-lg focus:ring-2 focus:ring-blue-500"
/>
</div>
</div>
<div className="mb-6">
<label className="block text-sm font-bold text-gray-700 mb-2">
Winning Numbers (Select {currentConfig.numbersCount})
</label>
<div className="flex flex-wrap justify-center bg-white p-4 rounded-lg">
{renderNumberGrid(true)}
</div>
<p className="text-center mt-2 text-sm text-gray-600">
Selected: {manualInputNumbers.join(', ')} ({manualInputNumbers.length}/{currentConfig.numbersCount})
</p>
</div>
{currentConfig.hasBonus && (
<div className="mb-6">
<label className="block text-sm font-bold text-gray-700 mb-2">Bonus Number</label>
<input
type="number"
min="1"
max={currentConfig.maxNumber}
placeholder={`1-${currentConfig.maxNumber}`}
value={manualInputBonus}
onChange={(e) => setManualInputBonus(e.target.value)}
className="w-full max-w-xs p-3 border rounded-lg focus:ring-2 focus:ring-blue-500"
/>
</div>
)}
<button
onClick={addManualEntry}
disabled={manualInputNumbers.length !== currentConfig.numbersCount || !manualInputDate}
className="w-full bg-green-600 text-white py-3 px-6 rounded-lg font-bold hover:bg-green-700 disabled:bg-gray-300 transition-colors"
>
<Save className="w-4 h-4 inline mr-2" />
Add Entry to Database
</button>
</div>
</div>
)}
{/* Database Tab */}
{activeTab === 'database' && (
<div className="space-y-6">
<h2 className="text-2xl font-bold flex items-center">
<Database className="mr-2 text-purple-500" />
Database Management
</h2>
<div className="grid md:grid-cols-2 gap-6">
{/* Scraping Section */}
<div className="bg-gradient-to-br from-purple-50 to-blue-50 rounded-xl p-6">
<h3 className="text-xl font-bold mb-4 text-purple-700">Auto Data Scraping</h3>
<p className="text-gray-600 mb-4">
Automatically collect historical data from multiple sources including Supreme Ventures
and Jamaica Index. This will update both Lotto and Super Lotto databases.
</p>
{isScrapingData ? (
<div className="text-center">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-purple-600 mx-auto mb-4"></div>
<p className="text-purple-700 font-medium">{scrapingStatus}</p>
</div>
) : (
<button
onClick={scrapeDatabase}
className="w-full bg-purple-600 text-white py-3 px-6 rounded-lg font-bold hover:bg-purple-700 transition-colors flex items-center justify-center"
>
<RefreshCw className="w-4 h-4 mr-2" />
Scrape & Update Database
</button>
)}
<div className="mt-4 text-sm text-gray-500">
<h4 className="font-bold mb-2">Data Sources:</h4>
<ul className="space-y-1">
<li>• Supreme Ventures Official Site</li>
<li>• Jamaica Index Lottery Results</li>
<li>• Historical Archives</li>
<li>• Third-party Lottery APIs</li>
</ul>
</div>
</div>
{/* Export Section */}
<div className="bg-gradient-to-br from-green-50 to-blue-50 rounded-xl p-6">
<h3 className="text-xl font-bold mb-4 text-green-700">Data Export</h3>
<p className="text-gray-600 mb-4">
Export historical data to CSV format for external analysis,
backup purposes, or integration with other tools.
</p>
<div className="space-y-3">
<button
onClick={() => exportSpecificData('lotto')}
className="w-full bg-blue-600 text-white py-2 px-4 rounded-lg font-medium hover:bg-blue-700 transition-colors"
>
<Download className="w-4 h-4 inline mr-2" />
Export Lotto Data ({historicalData.lotto?.length || 0} records)
</button>
<button
onClick={() => exportSpecificData('superlotto')}
className="w-full bg-purple-600 text-white py-2 px-4 rounded-lg font-medium hover:bg-purple-700 transition-colors"
>
<Download className="w-4 h-4 inline mr-2" />
Export Super Lotto Data ({historicalData.superlotto?.length || 0} records)
</button>
<button
onClick={() => exportAllData()}
className="w-full bg-green-600 text-white py-2 px-4 rounded-lg font-medium hover:bg-green-700 transition-colors"
>
<Download className="w-4 h-4 inline mr-2" />
Export All Data (Combined CSV)
</button>
</div>
<div className="mt-4 text-sm text-gray-500">
<h4 className="font-bold mb-2">CSV Format Includes:</h4>
<ul className="space-y-1">
<li>• Date of draw</li>
<li>• Winning numbers</li>
<li>• Bonus numbers (where applicable)</li>
<li>• Jackpot amounts</li>
<li>• Game type identifier</li>
</ul>
</div>
</div>
</div>
{/* Database Statistics */}
<div className="bg-white border rounded-xl p-6">
<h3 className="text-xl font-bold mb-4">Database Statistics</h3>
<div className="grid md:grid-cols-4 gap-4">
<div className="text-center p-4 bg-blue-50 rounded-lg">
<div className="text-2xl font-bold text-blue-600">{historicalData.lotto?.length || 0}</div>
<div className="text-sm text-gray-600">Lotto Records</div>
</div>
<div className="text-center p-4 bg-purple-50 rounded-lg">
<div className="text-2xl font-bold text-purple-600">{historicalData.superlotto?.length || 0}</div>
<div className="text-sm text-gray-600">Super Lotto Records</div>
</div>
<div className="text-center p-4 bg-green-50 rounded-lg">
<div className="text-2xl font-bold text-green-600">
{((historicalData.lotto?.length || 0) + (historicalData.superlotto?.length || 0))}
</div>
<div className="text-sm text-gray-600">Total Records</div>
</div>
<div className="text-center p-4 bg-yellow-50 rounded-lg">
<div className="text-2xl font-bold text-yellow-600">
{historicalData.lotto?.length > 0 || historicalData.superlotto?.length > 0
? new Date().toLocaleDateString()
: 'N/A'}
</div>
<div className="text-sm text-gray-600">Last Updated</div>
</div>
</div>
</div>
{/* Import Section */}
<div className="bg-gray-50 rounded-xl p-6">
<h3 className="text-xl font-bold mb-4">Import Data</h3>
<p className="text-gray-600 mb-4">
Import historical data from CSV files or other sources.
</p>
<div className="flex gap-3">
<input
type="file"
accept=".csv"
className="flex-1 p-3 border rounded-lg"
onChange={handleFileImport}
/>
<button className="bg-gray-600 text-white px-6 py-3 rounded-lg font-medium hover:bg-gray-700 transition-colors">
<Upload className="w-4 h-4 inline mr-2" />
Import
</button>
</div>
</div>
{/* API Configuration (Future) */}
<div className="bg-gray-100 rounded-xl p-6 opacity-75">
<h3 className="text-xl font-bold mb-4 text-gray-600">🚧 Future Features</h3>
<div className="space-y-2 text-sm text-gray-500">
<p>• Real-time API integration with Supreme Ventures</p>
<p>• Automated daily data updates</p>
<p>• Advanced machine learning predictions</p>
<p>• Mobile app synchronization</p>
<p>• Social sharing of predictions</p>
</div>
</div>
</div>
)}
{/* Footer */}
<div className="mt-12 text-center text-gray-500 text-sm border-t pt-6">
<p>⚠️ This is for entertainment purposes only. Lottery games are random and no system can guarantee wins.</p>
<div className="mt-2 flex justify-center gap-8 text-xs">
<span>Lotto: Wed & Sat 8:25 PM | Tickets: J$100</span>
<span>Super Lotto: Wed & Sat 8:25 PM | Tickets: J$200</span>
</div>
<p className="mt-2">Always play responsibly within your means.</p>
</div>
</div>
</div>
);
// Additional helper functions
function exportSpecificData(gameType) {
const data = historicalData[gameType] || [];
const config = gameConfig[gameType];
if (!data.length) {
alert(`No ${config.name} data to export`);
return;
}
const headers = ['Date', 'Numbers', config.hasBonus ? 'Bonus' : null, 'Jackpot', 'Game'].filter(Boolean);
const csvContent = [
headers.join(','),
...data.map(row => [
row.date,
`"${row.numbers.join(' ')}"`,
config.hasBonus ? (row.bonus || '') : null,
row.jackpot,
config.name
].filter(cell => cell !== null).join(','))
].join('\n');
downloadCSV(csvContent, `${config.name.toLowerCase().replace(' ', '_')}_results.csv`);
}
function exportAllData() {
const allData = [
...(historicalData.lotto || []).map(row => ({ ...row, game: 'Lotto' })),
...(historicalData.superlotto || []).map(row => ({ ...row, game: 'Super Lotto' }))
].sort((a, b) => new Date(b.date) - new Date(a.date));
if (!allData.length) {
alert('No data to export');
return;
}
const headers = ['Date', 'Numbers', 'Bonus', 'Jackpot', 'Game'];
const csvContent = [
headers.join(','),
...allData.map(row => [
row.date,
`"${row.numbers.join(' ')}"`,
row.bonus || '',
row.jackpot,
row.game
].join(','))
].join('\n');
downloadCSV(csvContent, 'jamaica_lottery_complete_results.csv');
}
function downloadCSV(content, filename) {
const blob = new Blob([content], { type: 'text/csv;charset=utf-8;' });
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = filename;
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
}
function handleFileImport(event) {
const file = event.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = (e) => {
try {
const csv = e.target.result;
const lines = csv.split('\n');
const headers = lines[0].split(',');
// Basic CSV parsing (in production, use a proper CSV parser)
const importedData = lines.slice(1)
.filter(line => line.trim())
.map(line => {
const values = line.split(',');
return {
date: values[0],
numbers: values[1].replace(/"/g, '').split(' ').map(n => parseInt(n)).filter(n => !isNaN(n)),
bonus: values[2] ? parseInt(values[2]) : null,
jackpot: parseInt(values[3]) || 0
};
})
.filter(row => row.numbers.length > 0);
if (importedData.length > 0) {
// Merge with existing data
const updatedData = { ...historicalData };
// Simple merge - in production, implement proper deduplication
updatedData[gameType] = [...importedData, ...updatedData[gameType]];
setHistoricalData(updatedData);
alert(`Successfully imported ${importedData.length} records`);
}
} catch (error) {
alert('Error importing file. Please check the format.');
}
};
reader.readAsText(file);
}
};
export default JamaicaLottoAnalyzer;