File size: 6,795 Bytes
733c20d
ede745b
 
 
 
 
 
733c20d
ede745b
 
 
 
 
 
 
733c20d
ede745b
 
 
 
 
 
 
 
 
 
733c20d
ede745b
 
733c20d
 
 
 
 
 
 
 
 
ede745b
733c20d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ede745b
 
 
733c20d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ede745b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
733c20d
ede745b
 
 
733c20d
ede745b
 
 
 
 
 
 
 
 
 
 
 
733c20d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206

// Global state
let bankroll = 10000.00;
let currentPredictions = [];
let topNumbers = [];
let spinResult = null;
let selectedNumber = null;
let lastFetchedResults = [];

// DOM Elements
const predictionsContainer = document.getElementById('predictions-container');
const topNumbersList = document.getElementById('top-numbers-list');
const bankrollValue = document.getElementById('bankroll-value');
const betAmountEl = document.getElementById('bet-amount');
const betTargetEl = document.getElementById('bet-target');
const fetchButton = document.getElementById('fetch-button');

// Initialize the app
document.addEventListener('DOMContentLoaded', () => {
    generateMockData();
    renderPredictions();
    renderTopNumbers();
    renderOracleStatus();
    updateBankrollDisplay();
    
    // Event listeners
    fetchButton.addEventListener('click', fetchLatestResults);
});

// Fetch latest results from the roulette game
async function fetchLatestResults() {
    fetchButton.disabled = true;
    fetchButton.textContent = 'Fetching...';
    
    try {
        // Simulate fetching results (in a real implementation, this would call the Python backend)
        const response = await fetch('/api/fetch-results');
        const data = await response.json();
        
        if (data.success && data.results && data.results.length > 0) {
            // Process the latest result (first in array since they're ordered newest first)
            const latestResult = data.results[0];
            recordSpinResult(latestResult);
            
            // Store results for reference
            lastFetchedResults = data.results;
            
            // Show notification
            showNotification(`Fetched result: ${latestResult}`, 'success');
        } else {
            showNotification('No new results found', 'info');
        }
    } catch (error) {
        console.error('Error fetching results:', error);
        showNotification('Failed to fetch results', 'error');
    } finally {
        fetchButton.disabled = false;
        fetchButton.textContent = 'Fetch Latest Results';
    }
}

// Show notification message
function showNotification(message, type = 'info') {
    // Remove any existing notifications
    const existingNotification = document.querySelector('.notification');
    if (existingNotification) {
        existingNotification.remove();
    }
    
    const notification = document.createElement('div');
    notification.className = `notification fixed top-4 right-4 px-6 py-4 rounded-lg shadow-lg z-50 transform transition-transform duration-300 ${
        type === 'success' ? 'bg-green-600' : 
        type === 'error' ? 'bg-red-600' : 'bg-blue-600'
    }`;
    notification.textContent = message;
    
    document.body.appendChild(notification);
    
    // Auto remove after 3 seconds
    setTimeout(() => {
        notification.style.transform = 'translateX(150%)';
        setTimeout(() => {
            notification.remove();
        }, 300);
    }, 3000);
}
// Generate mock data for demonstration
function generateMockData() {
    // Generate mock predictions
    currentPredictions = [];
    const predictionCount = 20;
    
    for (let i = 0; i < predictionCount; i++) {
        const number = Math.floor(Math.random() * 37);
        const predictors = Math.floor(Math.random() * 15) + 1;
        currentPredictions.push({ number, predictors });
    }
    
    // Sort by predictor count descending
    currentPredictions.sort((a, b) => b.predictors - a.predictors);
    
    // Generate top 12 numbers
    topNumbers = currentPredictions.slice(0, 12);
    
    // Calculate recommended bet
    calculateRecommendedBet();
}

// Render predictions
function renderPredictions() {
    predictionsContainer.innerHTML = '';
    
    currentPredictions.forEach((pred, index) => {
        const card = document.createElement('custom-prediction-card');
        card.prediction = pred;
        card.rank = index + 1;
        predictionsContainer.appendChild(card);
    });
}

// Render top numbers
function renderTopNumbers() {
    topNumbersList.innerHTML = '';
    
    topNumbers.forEach((pred, index) => {
        const topNumber = document.createElement('custom-top-number');
        topNumber.prediction = pred;
        topNumber.rank = index + 1;
        topNumbersList.appendChild(topNumber);
    });
}

// Render oracle status indicators
function renderOracleStatus() {
    const container = document.querySelector('.grid.grid-cols-2.md\\:grid-cols-4.lg\\:grid-cols-7');
    container.innerHTML = '';
    
    // Create 70 oracle indicators
    for (let i = 1; i <= 70; i++) {
        const indicator = document.createElement('custom-oracle-indicator');
        indicator.oracle = {
            id: i,
            active: Math.random() > 0.3,
            accuracy: Math.floor(Math.random() * 100)
        };
        container.appendChild(indicator);
    }
}

// Calculate recommended bet using Kelly criterion
function calculateRecommendedBet() {
    if (topNumbers.length === 0) return;
    
    // Get the top prediction
    const topPrediction = topNumbers[0];
    
    // Kelly fractions based on rank (simplified for demo)
    const kellyFractions = [
        0.0619, 0.0237, 0.000902, 0.00035, 0.000133,
        0.0005, 0.0002, 0.000074, 0.000029, 0.000011,
        0.0000041, 0.0000026
    ];
    
    // Get fraction for top prediction (default to smallest if beyond top 12)
    const fraction = topNumbers.indexOf(topPrediction) < 12 ? 
        kellyFractions[topNumbers.indexOf(topPrediction)] : 0.0000026;
    
    const betAmount = bankroll * fraction;
    betAmountEl.textContent = betAmount.toFixed(2);
    betTargetEl.textContent = `#${topPrediction.number}`;
}

// Update bankroll display
function updateBankrollDisplay() {
    bankrollValue.textContent = bankroll.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
// Record spin result and update bankroll
function recordSpinResult(number) {
    spinResult = number;
    
    // Check if we had a bet on this number
    const topPrediction = topNumbers[0];
    const betAmount = parseFloat(betAmountEl.textContent);
    
    if (topPrediction && topPrediction.number === number && betAmount > 0) {
        // Win! 35:1 payout
        bankroll += betAmount * 35;
        showNotification(`WIN! +${(betAmount * 35).toFixed(2)} on number ${number}`, 'success');
    } else if (betAmount > 0) {
        // Loss
        bankroll -= betAmount;
        showNotification(`Loss of ${betAmount.toFixed(2)}`, 'error');
    }
    
    // Update display
    updateBankrollDisplay();
    
    // Regenerate predictions for next spin
    setTimeout(() => {
        generateMockData();
        renderPredictions();
        renderTopNumbers();
        calculateRecommendedBet();
    }, 500);
}