johnfmarti commited on
Commit
38bc18b
·
verified ·
1 Parent(s): 229afb8

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +962 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Roulette 1
3
- emoji: 🐢
4
- colorFrom: purple
5
- colorTo: purple
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: roulette-1
3
+ emoji: 🐳
4
+ colorFrom: red
5
+ colorTo: pink
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,962 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Roulette Strategy Simulator</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
9
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
10
+ <style>
11
+ .strategy-card:hover {
12
+ transform: translateY(-5px);
13
+ box-shadow: 0 10px 20px rgba(0,0,0,0.1);
14
+ }
15
+ .tab-active {
16
+ border-bottom: 3px solid #3b82f6;
17
+ color: #3b82f6;
18
+ font-weight: 600;
19
+ }
20
+ .bankroll-up {
21
+ color: #10b981;
22
+ }
23
+ .bankroll-down {
24
+ color: #ef4444;
25
+ }
26
+ .progress-bar {
27
+ transition: width 0.3s ease;
28
+ }
29
+ .fade-in {
30
+ animation: fadeIn 0.5s;
31
+ }
32
+ @keyframes fadeIn {
33
+ from { opacity: 0; }
34
+ to { opacity: 1; }
35
+ }
36
+ .pulse {
37
+ animation: pulse 2s infinite;
38
+ }
39
+ @keyframes pulse {
40
+ 0% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.4); }
41
+ 70% { box-shadow: 0 0 0 10px rgba(59, 130, 246, 0); }
42
+ 100% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0); }
43
+ }
44
+ </style>
45
+ </head>
46
+ <body class="bg-gray-100 min-h-screen">
47
+ <div class="container mx-auto px-4 py-8">
48
+ <header class="mb-8">
49
+ <h1 class="text-4xl font-bold text-center text-blue-800 mb-2">Roulette Strategy Simulator</h1>
50
+ <p class="text-center text-gray-600 max-w-2xl mx-auto">
51
+ Test, analyze, and compare roulette betting strategies with comprehensive simulations and visualizations
52
+ </p>
53
+ </header>
54
+
55
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
56
+ <!-- Left Panel - Configuration -->
57
+ <div class="bg-white rounded-xl shadow-md p-6 lg:col-span-1">
58
+ <h2 class="text-xl font-semibold mb-4 text-gray-800 border-b pb-2">Simulation Settings</h2>
59
+
60
+ <div class="space-y-4">
61
+ <div>
62
+ <label class="block text-sm font-medium text-gray-700 mb-1">Starting Bankroll</label>
63
+ <div class="relative">
64
+ <span class="absolute inset-y-0 left-0 flex items-center pl-3 text-gray-500">$</span>
65
+ <input type="number" id="bankroll" class="pl-8 w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500" value="1000" min="1">
66
+ </div>
67
+ </div>
68
+
69
+ <div>
70
+ <label class="block text-sm font-medium text-gray-700 mb-1">Minimum Bet</label>
71
+ <input type="number" id="min-bet" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500" value="1" min="1">
72
+ </div>
73
+
74
+ <div>
75
+ <label class="block text-sm font-medium text-gray-700 mb-1">Bets per Run</label>
76
+ <input type="number" id="iterations" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500" value="100" min="10">
77
+ </div>
78
+
79
+ <div>
80
+ <label class="block text-sm font-medium text-gray-700 mb-1">Simulation Runs</label>
81
+ <input type="number" id="runs" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500" value="10" min="1">
82
+ </div>
83
+
84
+ <div>
85
+ <label class="block text-sm font-medium text-gray-700 mb-1">Roulette Type</label>
86
+ <select id="roulette-type" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
87
+ <option value="european">European (Single Zero)</option>
88
+ <option value="american">American (Double Zero)</option>
89
+ </select>
90
+ </div>
91
+
92
+ <div class="pt-2">
93
+ <label class="block text-sm font-medium text-gray-700 mb-1">Simulation Speed</label>
94
+ <div class="flex space-x-4">
95
+ <label class="inline-flex items-center">
96
+ <input type="radio" name="speed" class="h-4 w-4 text-blue-600 focus:ring-blue-500" value="slow">
97
+ <span class="ml-2 text-gray-700">Slow</span>
98
+ </label>
99
+ <label class="inline-flex items-center">
100
+ <input type="radio" name="speed" class="h-4 w-4 text-blue-600 focus:ring-blue-500" value="normal" checked>
101
+ <span class="ml-2 text-gray-700">Normal</span>
102
+ </label>
103
+ <label class="inline-flex items-center">
104
+ <input type="radio" name="speed" class="h-4 w-4 text-blue-600 focus:ring-blue-500" value="fast">
105
+ <span class="ml-2 text-gray-700">Fast</span>
106
+ </label>
107
+ </div>
108
+ </div>
109
+
110
+ <div class="pt-2">
111
+ <label class="inline-flex items-center">
112
+ <input type="checkbox" id="live-graph" class="h-4 w-4 text-blue-600 focus:ring-blue-500" checked>
113
+ <span class="ml-2 text-gray-700">Live Graph Updates</span>
114
+ </label>
115
+ </div>
116
+ </div>
117
+
118
+ <div class="mt-6 pt-4 border-t">
119
+ <h3 class="text-lg font-medium text-gray-800 mb-3">Strategy Sources</h3>
120
+
121
+ <div class="space-y-3">
122
+ <div>
123
+ <label class="inline-flex items-center">
124
+ <input type="checkbox" id="web-search" class="h-4 w-4 text-blue-600 focus:ring-blue-500">
125
+ <span class="ml-2 text-gray-700">Enable Web Strategy Search</span>
126
+ </label>
127
+ </div>
128
+
129
+ <div id="url-inputs" class="space-y-3 hidden">
130
+ <div>
131
+ <label class="block text-sm font-medium text-gray-700 mb-1">Article URL</label>
132
+ <input type="text" id="article-url" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500" placeholder="https://example.com/strategy">
133
+ </div>
134
+
135
+ <div>
136
+ <label class="block text-sm font-medium text-gray-700 mb-1">Video URL</label>
137
+ <input type="text" id="video-url" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500" placeholder="https://youtube.com/watch?v=...">
138
+ </div>
139
+
140
+ <div>
141
+ <label class="block text-sm font-medium text-gray-700 mb-1">PDF Upload</label>
142
+ <div class="mt-1 flex justify-center px-6 pt-5 pb-6 border-2 border-gray-300 border-dashed rounded-md">
143
+ <div class="space-y-1 text-center">
144
+ <svg class="mx-auto h-12 w-12 text-gray-400" stroke="currentColor" fill="none" viewBox="0 0 48 48" aria-hidden="true">
145
+ <path d="M28 8H12a4 4 0 00-4 4v20m32-12v8m0 0v8a4 4 0 01-4 4H12a4 4 0 01-4-4v-4m32-4l-3.172-3.172a4 4 0 00-5.656 0L28 28M8 32l9.172-9.172a4 4 0 015.656 0L28 28m0 0l4 4m4-24h8m-4-4v8m-12 4h.02" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
146
+ </svg>
147
+ <div class="flex text-sm text-gray-600">
148
+ <label class="relative cursor-pointer bg-white rounded-md font-medium text-blue-600 hover:text-blue-500 focus-within:outline-none">
149
+ <span>Upload a file</span>
150
+ <input type="file" class="sr-only">
151
+ </label>
152
+ <p class="pl-1">or drag and drop</p>
153
+ </div>
154
+ <p class="text-xs text-gray-500">PDF up to 10MB</p>
155
+ </div>
156
+ </div>
157
+ </div>
158
+ </div>
159
+ </div>
160
+ </div>
161
+
162
+ <button id="run-simulation" class="mt-6 w-full bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 flex items-center justify-center">
163
+ <i class="fas fa-play-circle mr-2"></i> Run Simulation
164
+ </button>
165
+ </div>
166
+
167
+ <!-- Middle Panel - Strategy Selection -->
168
+ <div class="bg-white rounded-xl shadow-md p-6 lg:col-span-1">
169
+ <h2 class="text-xl font-semibold mb-4 text-gray-800 border-b pb-2">Select Strategies</h2>
170
+
171
+ <div class="mb-4">
172
+ <div class="flex border-b">
173
+ <button class="tab-btn px-4 py-2 text-sm font-medium tab-active" data-tab="builtin">Built-in</button>
174
+ <button class="tab-btn px-4 py-2 text-sm font-medium" data-tab="web">Web/AI</button>
175
+ <button class="tab-btn px-4 py-2 text-sm font-medium" data-tab="custom">Custom</button>
176
+ </div>
177
+ </div>
178
+
179
+ <div id="builtin-tab" class="tab-content space-y-3">
180
+ <div class="strategy-card bg-gray-50 p-4 rounded-lg border border-gray-200 cursor-pointer transition-all duration-200">
181
+ <div class="flex items-center">
182
+ <input type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500" value="martingale" checked>
183
+ <div class="ml-3">
184
+ <h3 class="text-sm font-medium text-gray-800">Martingale</h3>
185
+ <p class="text-xs text-gray-500">Double bet after loss, reset after win</p>
186
+ </div>
187
+ </div>
188
+ </div>
189
+
190
+ <div class="strategy-card bg-gray-50 p-4 rounded-lg border border-gray-200 cursor-pointer transition-all duration-200">
191
+ <div class="flex items-center">
192
+ <input type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500" value="reverse-martingale">
193
+ <div class="ml-3">
194
+ <h3 class="text-sm font-medium text-gray-800">Reverse Martingale</h3>
195
+ <p class="text-xs text-gray-500">Double bet after win, reset after loss</p>
196
+ </div>
197
+ </div>
198
+ </div>
199
+
200
+ <div class="strategy-card bg-gray-50 p-4 rounded-lg border border-gray-200 cursor-pointer transition-all duration-200">
201
+ <div class="flex items-center">
202
+ <input type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500" value="fibonacci">
203
+ <div class="ml-3">
204
+ <h3 class="text-sm font-medium text-gray-800">Fibonacci</h3>
205
+ <p class="text-xs text-gray-500">Follow Fibonacci sequence progression</p>
206
+ </div>
207
+ </div>
208
+ </div>
209
+
210
+ <div class="strategy-card bg-gray-50 p-4 rounded-lg border border-gray-200 cursor-pointer transition-all duration-200">
211
+ <div class="flex items-center">
212
+ <input type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500" value="dalembert">
213
+ <div class="ml-3">
214
+ <h3 class="text-sm font-medium text-gray-800">D'Alembert</h3>
215
+ <p class="text-xs text-gray-500">Increase by 1 after loss, decrease by 1 after win</p>
216
+ </div>
217
+ </div>
218
+ </div>
219
+
220
+ <div class="strategy-card bg-gray-50 p-4 rounded-lg border border-gray-200 cursor-pointer transition-all duration-200">
221
+ <div class="flex items-center">
222
+ <input type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500" value="flat">
223
+ <div class="ml-3">
224
+ <h3 class="text-sm font-medium text-gray-800">Flat Betting</h3>
225
+ <p class="text-xs text-gray-500">Constant bet amount</p>
226
+ </div>
227
+ </div>
228
+ </div>
229
+
230
+ <div class="strategy-card bg-gray-50 p-4 rounded-lg border border-gray-200 cursor-pointer transition-all duration-200">
231
+ <div class="flex items-center">
232
+ <input type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500" value="random">
233
+ <div class="ml-3">
234
+ <h3 class="text-sm font-medium text-gray-800">Random Betting</h3>
235
+ <p class="text-xs text-gray-500">Random bet amounts and types</p>
236
+ </div>
237
+ </div>
238
+ </div>
239
+ </div>
240
+
241
+ <div id="web-tab" class="tab-content hidden space-y-3">
242
+ <div class="text-center py-8 text-gray-500">
243
+ <i class="fas fa-globe text-4xl mb-3"></i>
244
+ <p>Enable "Web Strategy Search" to discover strategies from online sources</p>
245
+ </div>
246
+ </div>
247
+
248
+ <div id="custom-tab" class="tab-content hidden">
249
+ <div class="mb-4">
250
+ <label class="block text-sm font-medium text-gray-700 mb-1">Custom Strategy Code</label>
251
+ <textarea id="custom-strategy" class="w-full h-32 rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500" placeholder="// Implement your custom strategy here..."></textarea>
252
+ </div>
253
+ <button class="w-full bg-gray-200 hover:bg-gray-300 text-gray-800 font-medium py-2 px-4 rounded-md shadow-sm">
254
+ Add Custom Strategy
255
+ </button>
256
+ </div>
257
+ </div>
258
+
259
+ <!-- Right Panel - Results -->
260
+ <div class="bg-white rounded-xl shadow-md p-6 lg:col-span-1">
261
+ <h2 class="text-xl font-semibold mb-4 text-gray-800 border-b pb-2">Simulation Results</h2>
262
+
263
+ <div id="results-container" class="space-y-6">
264
+ <div class="text-center py-12 text-gray-400">
265
+ <i class="fas fa-chart-line text-5xl mb-4"></i>
266
+ <p class="text-lg">Run a simulation to see results</p>
267
+ </div>
268
+ </div>
269
+
270
+ <div id="simulation-progress" class="hidden mt-6">
271
+ <div class="flex justify-between mb-1">
272
+ <span class="text-sm font-medium text-gray-700">Progress</span>
273
+ <span id="progress-percent" class="text-sm font-medium text-gray-700">0%</span>
274
+ </div>
275
+ <div class="w-full bg-gray-200 rounded-full h-2.5">
276
+ <div id="progress-bar" class="progress-bar bg-blue-600 h-2.5 rounded-full" style="width: 0%"></div>
277
+ </div>
278
+ <div class="mt-2 text-sm text-gray-600">
279
+ <span id="progress-status">Initializing...</span>
280
+ </div>
281
+ </div>
282
+
283
+ <div class="mt-6 pt-4 border-t">
284
+ <div class="flex space-x-3">
285
+ <button id="export-csv" class="flex-1 bg-gray-200 hover:bg-gray-300 text-gray-800 font-medium py-2 px-4 rounded-md shadow-sm text-sm flex items-center justify-center" disabled>
286
+ <i class="fas fa-file-csv mr-2"></i> CSV
287
+ </button>
288
+ <button id="export-png" class="flex-1 bg-gray-200 hover:bg-gray-300 text-gray-800 font-medium py-2 px-4 rounded-md shadow-sm text-sm flex items-center justify-center" disabled>
289
+ <i class="fas fa-image mr-2"></i> PNG
290
+ </button>
291
+ <button id="export-zip" class="flex-1 bg-gray-200 hover:bg-gray-300 text-gray-800 font-medium py-2 px-4 rounded-md shadow-sm text-sm flex items-center justify-center" disabled>
292
+ <i class="fas fa-file-archive mr-2"></i> ZIP
293
+ </button>
294
+ </div>
295
+ </div>
296
+ </div>
297
+ </div>
298
+
299
+ <!-- Charts Section -->
300
+ <div class="mt-8 bg-white rounded-xl shadow-md p-6">
301
+ <h2 class="text-xl font-semibold mb-4 text-gray-800 border-b pb-2">Visualizations</h2>
302
+
303
+ <div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
304
+ <div>
305
+ <h3 class="text-lg font-medium text-gray-700 mb-2">Bankroll Progression</h3>
306
+ <div class="bg-gray-50 p-4 rounded-lg">
307
+ <canvas id="bankroll-chart" height="300"></canvas>
308
+ </div>
309
+ </div>
310
+
311
+ <div>
312
+ <h3 class="text-lg font-medium text-gray-700 mb-2">Final Bankroll Distribution</h3>
313
+ <div class="bg-gray-50 p-4 rounded-lg">
314
+ <canvas id="distribution-chart" height="300"></canvas>
315
+ </div>
316
+ </div>
317
+
318
+ <div>
319
+ <h3 class="text-lg font-medium text-gray-700 mb-2">Win/Loss Ratio</h3>
320
+ <div class="bg-gray-50 p-4 rounded-lg">
321
+ <canvas id="ratio-chart" height="300"></canvas>
322
+ </div>
323
+ </div>
324
+
325
+ <div>
326
+ <h3 class="text-lg font-medium text-gray-700 mb-2">Max Drawdown</h3>
327
+ <div class="bg-gray-50 p-4 rounded-lg">
328
+ <canvas id="drawdown-chart" height="300"></canvas>
329
+ </div>
330
+ </div>
331
+ </div>
332
+ </div>
333
+
334
+ <!-- Detailed Logs Section -->
335
+ <div class="mt-8 bg-white rounded-xl shadow-md p-6">
336
+ <h2 class="text-xl font-semibold mb-4 text-gray-800 border-b pb-2">Detailed Logs</h2>
337
+
338
+ <div class="overflow-x-auto">
339
+ <table class="min-w-full divide-y divide-gray-200">
340
+ <thead class="bg-gray-50">
341
+ <tr>
342
+ <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Run #</th>
343
+ <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Strategy</th>
344
+ <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Bet #</th>
345
+ <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Bet Type</th>
346
+ <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Amount</th>
347
+ <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Result</th>
348
+ <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Bankroll</th>
349
+ </tr>
350
+ </thead>
351
+ <tbody id="logs-body" class="bg-white divide-y divide-gray-200">
352
+ <tr>
353
+ <td colspan="7" class="px-6 py-4 text-center text-gray-500">No simulation data available</td>
354
+ </tr>
355
+ </tbody>
356
+ </table>
357
+ </div>
358
+
359
+ <div class="mt-4 flex justify-between items-center">
360
+ <div class="text-sm text-gray-500">
361
+ Showing <span id="logs-start">0</span> to <span id="logs-end">0</span> of <span id="logs-total">0</span> entries
362
+ </div>
363
+ <div class="flex space-x-2">
364
+ <button class="px-3 py-1 border rounded text-sm bg-gray-100 text-gray-700" disabled>Previous</button>
365
+ <button class="px-3 py-1 border rounded text-sm bg-gray-100 text-gray-700" disabled>Next</button>
366
+ </div>
367
+ </div>
368
+ </div>
369
+ </div>
370
+
371
+ <script>
372
+ // Initialize charts
373
+ const bankrollCtx = document.getElementById('bankroll-chart').getContext('2d');
374
+ const distributionCtx = document.getElementById('distribution-chart').getContext('2d');
375
+ const ratioCtx = document.getElementById('ratio-chart').getContext('2d');
376
+ const drawdownCtx = document.getElementById('drawdown-chart').getContext('2d');
377
+
378
+ const bankrollChart = new Chart(bankrollCtx, {
379
+ type: 'line',
380
+ data: { labels: [], datasets: [] },
381
+ options: {
382
+ responsive: true,
383
+ plugins: {
384
+ legend: { position: 'top' },
385
+ tooltip: {
386
+ mode: 'index',
387
+ intersect: false
388
+ }
389
+ },
390
+ scales: {
391
+ y: { beginAtZero: false }
392
+ }
393
+ }
394
+ });
395
+
396
+ const distributionChart = new Chart(distributionCtx, {
397
+ type: 'bar',
398
+ data: { labels: [], datasets: [] },
399
+ options: {
400
+ responsive: true,
401
+ plugins: {
402
+ legend: { display: false }
403
+ }
404
+ }
405
+ });
406
+
407
+ const ratioChart = new Chart(ratioCtx, {
408
+ type: 'doughnut',
409
+ data: { labels: ['Wins', 'Losses'], datasets: [] },
410
+ options: {
411
+ responsive: true,
412
+ plugins: {
413
+ legend: { position: 'right' }
414
+ }
415
+ }
416
+ });
417
+
418
+ const drawdownChart = new Chart(drawdownCtx, {
419
+ type: 'radar',
420
+ data: { labels: [], datasets: [] },
421
+ options: {
422
+ responsive: true,
423
+ plugins: {
424
+ legend: { position: 'top' }
425
+ }
426
+ }
427
+ });
428
+
429
+ // Tab switching
430
+ document.querySelectorAll('.tab-btn').forEach(btn => {
431
+ btn.addEventListener('click', () => {
432
+ document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('tab-active'));
433
+ document.querySelectorAll('.tab-content').forEach(c => c.classList.add('hidden'));
434
+
435
+ btn.classList.add('tab-active');
436
+ document.getElementById(`${btn.dataset.tab}-tab`).classList.remove('hidden');
437
+ });
438
+ });
439
+
440
+ // Web search toggle
441
+ document.getElementById('web-search').addEventListener('change', (e) => {
442
+ document.getElementById('url-inputs').classList.toggle('hidden', !e.target.checked);
443
+ });
444
+
445
+ // Strategy card hover effects
446
+ document.querySelectorAll('.strategy-card').forEach(card => {
447
+ card.addEventListener('mouseenter', () => {
448
+ card.classList.add('shadow-md');
449
+ });
450
+ card.addEventListener('mouseleave', () => {
451
+ card.classList.remove('shadow-md');
452
+ });
453
+ });
454
+
455
+ // Simulation logic
456
+ const strategies = {
457
+ martingale: {
458
+ name: "Martingale",
459
+ description: "Double bet after loss, reset after win",
460
+ initialize: (minBet) => ({ currentBet: minBet, lastResult: null }),
461
+ getBet: (state, bankroll, minBet) => {
462
+ if (state.lastResult === false) {
463
+ return { amount: Math.min(state.currentBet * 2, bankroll), type: "black" };
464
+ } else {
465
+ return { amount: minBet, type: "black" };
466
+ }
467
+ },
468
+ update: (state, result, minBet) => {
469
+ state.lastResult = result;
470
+ state.currentBet = result ? minBet : state.currentBet * 2;
471
+ }
472
+ },
473
+ "reverse-martingale": {
474
+ name: "Reverse Martingale",
475
+ description: "Double bet after win, reset after loss",
476
+ initialize: (minBet) => ({ currentBet: minBet, lastResult: null }),
477
+ getBet: (state, bankroll, minBet) => {
478
+ if (state.lastResult === true) {
479
+ return { amount: Math.min(state.currentBet * 2, bankroll), type: "black" };
480
+ } else {
481
+ return { amount: minBet, type: "black" };
482
+ }
483
+ },
484
+ update: (state, result, minBet) => {
485
+ state.lastResult = result;
486
+ state.currentBet = result ? state.currentBet * 2 : minBet;
487
+ }
488
+ },
489
+ fibonacci: {
490
+ name: "Fibonacci",
491
+ description: "Follow Fibonacci sequence progression",
492
+ initialize: (minBet) => ({ sequence: [minBet, minBet], position: 0, lastResult: null }),
493
+ getBet: (state, bankroll, minBet) => {
494
+ const amount = Math.min(state.sequence[state.position], bankroll);
495
+ return { amount, type: "black" };
496
+ },
497
+ update: (state, result, minBet) => {
498
+ if (result) {
499
+ // Move back two steps on win
500
+ state.position = Math.max(0, state.position - 2);
501
+ } else {
502
+ // Move forward one step on loss
503
+ state.position = Math.min(state.sequence.length - 1, state.position + 1);
504
+
505
+ // Extend sequence if needed
506
+ if (state.position === state.sequence.length - 1) {
507
+ const next = state.sequence[state.position] + state.sequence[state.position - 1];
508
+ state.sequence.push(next);
509
+ }
510
+ }
511
+ state.lastResult = result;
512
+ }
513
+ },
514
+ dalembert: {
515
+ name: "D'Alembert",
516
+ description: "Increase by 1 after loss, decrease by 1 after win",
517
+ initialize: (minBet) => ({ currentBet: minBet, lastResult: null }),
518
+ getBet: (state, bankroll, minBet) => {
519
+ return { amount: Math.min(state.currentBet, bankroll), type: "black" };
520
+ },
521
+ update: (state, result, minBet) => {
522
+ if (result) {
523
+ state.currentBet = Math.max(minBet, state.currentBet - minBet);
524
+ } else {
525
+ state.currentBet = state.currentBet + minBet;
526
+ }
527
+ state.lastResult = result;
528
+ }
529
+ },
530
+ flat: {
531
+ name: "Flat Betting",
532
+ description: "Constant bet amount",
533
+ initialize: () => ({}),
534
+ getBet: (state, bankroll, minBet) => {
535
+ return { amount: minBet, type: "black" };
536
+ },
537
+ update: () => {}
538
+ },
539
+ random: {
540
+ name: "Random Betting",
541
+ description: "Random bet amounts and types",
542
+ initialize: () => ({}),
543
+ getBet: (state, bankroll, minBet) => {
544
+ const types = ["red", "black", "even", "odd", "high", "low", "dozen1", "dozen2", "dozen3", "column1", "column2", "column3", "straight"];
545
+ const type = types[Math.floor(Math.random() * types.length)];
546
+ const amount = Math.min(Math.floor(Math.random() * 10) * minBet, bankroll);
547
+ return { amount, type };
548
+ },
549
+ update: () => {}
550
+ }
551
+ };
552
+
553
+ // Roulette probabilities
554
+ const rouletteProbabilities = {
555
+ european: {
556
+ "red": 18/37, "black": 18/37, "even": 18/37, "odd": 18/37,
557
+ "high": 18/37, "low": 18/37, "dozen1": 12/37, "dozen2": 12/37,
558
+ "dozen3": 12/37, "column1": 12/37, "column2": 12/37, "column3": 12/37,
559
+ "straight": 1/37
560
+ },
561
+ american: {
562
+ "red": 18/38, "black": 18/38, "even": 18/38, "odd": 18/38,
563
+ "high": 18/38, "low": 18/38, "dozen1": 12/38, "dozen2": 12/38,
564
+ "dozen3": 12/38, "column1": 12/38, "column2": 12/38, "column3": 12/38,
565
+ "straight": 1/38
566
+ }
567
+ };
568
+
569
+ // Payout multipliers
570
+ const payoutMultipliers = {
571
+ "red": 1, "black": 1, "even": 1, "odd": 1,
572
+ "high": 1, "low": 1, "dozen1": 2, "dozen2": 2,
573
+ "dozen3": 2, "column1": 2, "column2": 2, "column3": 2,
574
+ "straight": 35
575
+ };
576
+
577
+ // Run simulation
578
+ document.getElementById('run-simulation').addEventListener('click', async () => {
579
+ const bankroll = parseInt(document.getElementById('bankroll').value);
580
+ const minBet = parseInt(document.getElementById('min-bet').value);
581
+ const iterations = parseInt(document.getElementById('iterations').value);
582
+ const runs = parseInt(document.getElementById('runs').value);
583
+ const rouletteType = document.getElementById('roulette-type').value;
584
+ const liveGraph = document.getElementById('live-graph').checked;
585
+ const speed = document.querySelector('input[name="speed"]:checked').value;
586
+
587
+ // Get selected strategies
588
+ const selectedStrategies = [];
589
+ document.querySelectorAll('#builtin-tab input[type="checkbox"]:checked').forEach(checkbox => {
590
+ selectedStrategies.push(checkbox.value);
591
+ });
592
+
593
+ if (selectedStrategies.length === 0) {
594
+ alert("Please select at least one strategy to simulate");
595
+ return;
596
+ }
597
+
598
+ // Prepare UI
599
+ document.getElementById('simulation-progress').classList.remove('hidden');
600
+ const runButton = document.getElementById('run-simulation');
601
+ runButton.disabled = true;
602
+ runButton.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i> Running...';
603
+
604
+ // Clear previous results
605
+ document.getElementById('results-container').innerHTML = '';
606
+ document.getElementById('logs-body').innerHTML = '<tr><td colspan="7" class="px-6 py-4 text-center text-gray-500">Simulation in progress...</td></tr>';
607
+
608
+ bankrollChart.data.labels = Array.from({length: iterations}, (_, i) => i + 1);
609
+ bankrollChart.data.datasets = selectedStrategies.map(strategy => ({
610
+ label: strategies[strategy].name,
611
+ data: Array(iterations).fill(bankroll),
612
+ borderColor: getRandomColor(),
613
+ backgroundColor: 'rgba(0, 0, 0, 0)',
614
+ tension: 0.1
615
+ }));
616
+ bankrollChart.update();
617
+
618
+ distributionChart.data.labels = selectedStrategies.map(s => strategies[s].name);
619
+ distributionChart.data.datasets = [{
620
+ label: 'Final Bankroll',
621
+ data: selectedStrategies.map(() => bankroll),
622
+ backgroundColor: selectedStrategies.map(() => getRandomColor())
623
+ }];
624
+ distributionChart.update();
625
+
626
+ ratioChart.data.datasets = selectedStrategies.map(strategy => ({
627
+ label: strategies[strategy].name,
628
+ data: [50, 50],
629
+ backgroundColor: [getRandomColor(0.7), getRandomColor(0.7)]
630
+ }));
631
+ ratioChart.update();
632
+
633
+ drawdownChart.data.labels = ['Max Drawdown', 'Peak Winnings', 'Win Rate'];
634
+ drawdownChart.data.datasets = selectedStrategies.map(strategy => ({
635
+ label: strategies[strategy].name,
636
+ data: [0, 0, 50],
637
+ backgroundColor: getRandomColor(0.2),
638
+ borderColor: getRandomColor(),
639
+ pointBackgroundColor: getRandomColor(),
640
+ pointBorderColor: '#fff',
641
+ pointHoverBackgroundColor: '#fff',
642
+ pointHoverBorderColor: getRandomColor()
643
+ }));
644
+ drawdownChart.update();
645
+
646
+ // Initialize results
647
+ const allResults = {};
648
+ selectedStrategies.forEach(strategy => {
649
+ allResults[strategy] = {
650
+ name: strategies[strategy].name,
651
+ runs: [],
652
+ finalBankrolls: [],
653
+ maxDrawdowns: [],
654
+ peakWinnings: [],
655
+ winLossRatios: [],
656
+ bankruptcies: 0
657
+ };
658
+ });
659
+
660
+ // Determine speed delay
661
+ const speedDelays = {
662
+ slow: 50,
663
+ normal: 10,
664
+ fast: 0
665
+ };
666
+ const delay = speedDelays[speed];
667
+
668
+ // Run simulations
669
+ let completedRuns = 0;
670
+ const totalRuns = runs * selectedStrategies.length;
671
+
672
+ const updateProgress = (current, total, message) => {
673
+ const percent = Math.round((current / total) * 100);
674
+ document.getElementById('progress-bar').style.width = `${percent}%`;
675
+ document.getElementById('progress-percent').textContent = `${percent}%`;
676
+ document.getElementById('progress-status').textContent = message;
677
+ };
678
+
679
+ // Helper function to sleep
680
+ const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
681
+
682
+ // Run all simulations
683
+ for (let run = 0; run < runs; run++) {
684
+ for (const strategy of selectedStrategies) {
685
+ const state = strategies[strategy].initialize(minBet);
686
+ let currentBankroll = bankroll;
687
+ let peakBankroll = bankroll;
688
+ let maxDrawdown = 0;
689
+ let wins = 0;
690
+ let losses = 0;
691
+ let bankrupt = false;
692
+
693
+ const runResults = {
694
+ bets: [],
695
+ bankrollHistory: [],
696
+ drawdownHistory: []
697
+ };
698
+
699
+ for (let i = 0; i < iterations; i++) {
700
+ if (currentBankroll < minBet) {
701
+ bankrupt = true;
702
+ allResults[strategy].bankruptcies++;
703
+ break;
704
+ }
705
+
706
+ const bet = strategies[strategy].getBet(state, currentBankroll, minBet);
707
+ const winProbability = rouletteProbabilities[rouletteType][bet.type];
708
+ const result = Math.random() < winProbability;
709
+
710
+ if (result) {
711
+ currentBankroll += bet.amount * payoutMultipliers[bet.type];
712
+ wins++;
713
+ } else {
714
+ currentBankroll -= bet.amount;
715
+ losses++;
716
+ }
717
+
718
+ strategies[strategy].update(state, result, minBet);
719
+
720
+ // Track peak and drawdown
721
+ peakBankroll = Math.max(peakBankroll, currentBankroll);
722
+ const drawdown = peakBankroll - currentBankroll;
723
+ maxDrawdown = Math.max(maxDrawdown, drawdown);
724
+
725
+ // Store results
726
+ runResults.bets.push({
727
+ number: i + 1,
728
+ type: bet.type,
729
+ amount: bet.amount,
730
+ result: result ? 'win' : 'loss',
731
+ bankroll: currentBankroll
732
+ });
733
+
734
+ runResults.bankrollHistory.push(currentBankroll);
735
+ runResults.drawdownHistory.push(drawdown);
736
+
737
+ // Update UI if live graph is enabled
738
+ if (liveGraph && i % Math.max(1, Math.floor(iterations / 20)) === 0) {
739
+ updateCharts(allResults, runs, selectedStrategies);
740
+ if (delay > 0) await sleep(delay);
741
+ }
742
+ }
743
+
744
+ // Store run results
745
+ allResults[strategy].runs.push(runResults);
746
+ allResults[strategy].finalBankrolls.push(currentBankroll);
747
+ allResults[strategy].maxDrawdowns.push(maxDrawdown);
748
+ allResults[strategy].peakWinnings.push(peakBankroll - bankroll);
749
+ allResults[strategy].winLossRatios.push(wins / (wins + losses) || 0);
750
+
751
+ // Update progress
752
+ completedRuns++;
753
+ updateProgress(
754
+ completedRuns,
755
+ totalRuns,
756
+ `Running ${strategies[strategy].name} (${run + 1}/${runs})`
757
+ );
758
+
759
+ // Update charts after each run
760
+ updateCharts(allResults, runs, selectedStrategies);
761
+ if (delay > 0) await sleep(delay);
762
+ }
763
+ }
764
+
765
+ // Final update
766
+ updateCharts(allResults, runs, selectedStrategies);
767
+ displayResults(allResults, runs, bankroll);
768
+
769
+ // Enable export buttons
770
+ document.getElementById('export-csv').disabled = false;
771
+ document.getElementById('export-png').disabled = false;
772
+ document.getElementById('export-zip').disabled = false;
773
+
774
+ // Reset button
775
+ runButton.disabled = false;
776
+ runButton.innerHTML = '<i class="fas fa-play-circle mr-2"></i> Run Simulation';
777
+
778
+ // Show completion
779
+ updateProgress(totalRuns, totalRuns, 'Simulation completed!');
780
+ runButton.classList.add('pulse');
781
+ setTimeout(() => {
782
+ runButton.classList.remove('pulse');
783
+ }, 3000);
784
+ });
785
+
786
+ // Update charts with results
787
+ function updateCharts(results, runs, selectedStrategies) {
788
+ // Bankroll progression (average)
789
+ selectedStrategies.forEach((strategy, i) => {
790
+ if (results[strategy].runs.length === 0) return;
791
+
792
+ const iterations = results[strategy].runs[0].bankrollHistory.length;
793
+ const avgBankrolls = Array(iterations).fill(0);
794
+
795
+ results[strategy].runs.forEach(run => {
796
+ run.bankrollHistory.forEach((val, j) => {
797
+ avgBankrolls[j] += val / runs;
798
+ });
799
+ });
800
+
801
+ bankrollChart.data.datasets[i].data = avgBankrolls;
802
+ });
803
+ bankrollChart.update();
804
+
805
+ // Final bankroll distribution
806
+ distributionChart.data.datasets[0].data = selectedStrategies.map(strategy => {
807
+ if (results[strategy].finalBankrolls.length === 0) return 0;
808
+ const avg = results[strategy].finalBankrolls.reduce((a, b) => a + b, 0) / runs;
809
+ return Math.round(avg);
810
+ });
811
+ distributionChart.update();
812
+
813
+ // Win/Loss ratio
814
+ ratioChart.data.datasets = selectedStrategies.map((strategy, i) => {
815
+ if (results[strategy].winLossRatios.length === 0) return { data: [0, 0] };
816
+ const avgRatio = results[strategy].winLossRatios.reduce((a, b) => a + b, 0) / runs;
817
+ return {
818
+ label: results[strategy].name,
819
+ data: [avgRatio * 100, (1 - avgRatio) * 100],
820
+ backgroundColor: [getRandomColor(0.7), getRandomColor(0.7)]
821
+ };
822
+ });
823
+ ratioChart.update();
824
+
825
+ // Drawdown comparison
826
+ drawdownChart.data.datasets = selectedStrategies.map((strategy, i) => {
827
+ if (results[strategy].maxDrawdowns.length === 0) return { data: [0, 0, 0] };
828
+
829
+ const avgDrawdown = results[strategy].maxDrawdowns.reduce((a, b) => a + b, 0) / runs;
830
+ const avgPeak = results[strategy].peakWinnings.reduce((a, b) => a + b, 0) / runs;
831
+ const avgWinRate = results[strategy].winLossRatios.reduce((a, b) => a + b, 0) / runs * 100;
832
+
833
+ return {
834
+ label: results[strategy].name,
835
+ data: [avgDrawdown, avgPeak, avgWinRate],
836
+ backgroundColor: getRandomColor(0.2),
837
+ borderColor: getRandomColor(),
838
+ pointBackgroundColor: getRandomColor(),
839
+ pointBorderColor: '#fff',
840
+ pointHoverBackgroundColor: '#fff',
841
+ pointHoverBorderColor: getRandomColor()
842
+ };
843
+ });
844
+ drawdownChart.update();
845
+ }
846
+
847
+ // Display summary results
848
+ function displayResults(results, runs, initialBankroll) {
849
+ const container = document.getElementById('results-container');
850
+ container.innerHTML = '';
851
+
852
+ // Sort strategies by average final bankroll
853
+ const sortedStrategies = Object.keys(results).sort((a, b) => {
854
+ const avgA = results[a].finalBankrolls.reduce((sum, val) => sum + val, 0) / runs;
855
+ const avgB = results[b].finalBankrolls.reduce((sum, val) => sum + val, 0) / runs;
856
+ return avgB - avgA;
857
+ });
858
+
859
+ sortedStrategies.forEach(strategy => {
860
+ const data = results[strategy];
861
+ const avgFinal = data.finalBankrolls.reduce((sum, val) => sum + val, 0) / runs;
862
+ const avgDrawdown = data.maxDrawdowns.reduce((sum, val) => sum + val, 0) / runs;
863
+ const avgPeak = data.peakWinnings.reduce((sum, val) => sum + val, 0) / runs;
864
+ const avgWinRate = data.winLossRatios.reduce((sum, val) => sum + val, 0) / runs * 100;
865
+ const bankruptcyRate = (data.bankruptcies / runs) * 100;
866
+
867
+ const card = document.createElement('div');
868
+ card.className = 'bg-white rounded-lg shadow-sm border border-gray-200 p-4 fade-in';
869
+ card.innerHTML = `
870
+ <div class="flex justify-between items-start mb-2">
871
+ <h3 class="text-lg font-semibold text-gray-800">${data.name}</h3>
872
+ <span class="text-sm px-2 py-1 rounded-full ${avgFinal >= initialBankroll ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'}">
873
+ ${avgFinal >= initialBankroll ? '+' : ''}${Math.round(avgFinal - initialBankroll)} (${Math.round((avgFinal / initialBankroll - 1) * 100)}%)
874
+ </span>
875
+ </div>
876
+
877
+ <div class="grid grid-cols-2 gap-4 text-sm">
878
+ <div>
879
+ <p class="text-gray-500">Avg. Final Bankroll</p>
880
+ <p class="font-medium">${Math.round(avgFinal)}</p>
881
+ </div>
882
+ <div>
883
+ <p class="text-gray-500">Avg. Max Drawdown</p>
884
+ <p class="font-medium">${Math.round(avgDrawdown)}</p>
885
+ </div>
886
+ <div>
887
+ <p class="text-gray-500">Avg. Peak Winnings</p>
888
+ <p class="font-medium">+${Math.round(avgPeak)}</p>
889
+ </div>
890
+ <div>
891
+ <p class="text-gray-500">Win Rate</p>
892
+ <p class="font-medium">${avgWinRate.toFixed(1)}%</p>
893
+ </div>
894
+ </div>
895
+
896
+ <div class="mt-3">
897
+ <p class="text-sm text-gray-500 mb-1">Bankruptcy Rate</p>
898
+ <div class="w-full bg-gray-200 rounded-full h-2">
899
+ <div class="bg-red-500 h-2 rounded-full" style="width: ${bankruptcyRate}%"></div>
900
+ </div>
901
+ <p class="text-xs text-right text-gray-500 mt-1">${bankruptcyRate.toFixed(1)}% of runs</p>
902
+ </div>
903
+ `;
904
+
905
+ container.appendChild(card);
906
+ });
907
+
908
+ // Update logs table with sample data from first run of first strategy
909
+ if (sortedStrategies.length > 0) {
910
+ const firstStrategy = sortedStrategies[0];
911
+ if (results[firstStrategy].runs.length > 0) {
912
+ const firstRun = results[firstStrategy].runs[0];
913
+ const logsBody = document.getElementById('logs-body');
914
+ logsBody.innerHTML = '';
915
+
916
+ // Show only every 10th bet to keep table manageable
917
+ for (let i = 0; i < firstRun.bets.length; i += Math.max(1, Math.floor(firstRun.bets.length / 20))) {
918
+ const bet = firstRun.bets[i];
919
+ const row = document.createElement('tr');
920
+ row.innerHTML = `
921
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">1</td>
922
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${results[firstStrategy].name}</td>
923
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${bet.number}</td>
924
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${bet.type}</td>
925
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${bet.amount}</td>
926
+ <td class="px-6 py-4 whitespace-nowrap text-sm ${bet.result === 'win' ? 'text-green-600' : 'text-red-600'}">${bet.result}</td>
927
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${Math.round(bet.bankroll)}</td>
928
+ `;
929
+ logsBody.appendChild(row);
930
+ }
931
+
932
+ // Update pagination info
933
+ document.getElementById('logs-start').textContent = 1;
934
+ document.getElementById('logs-end').textContent = Math.min(20, firstRun.bets.length);
935
+ document.getElementById('logs-total').textContent = firstRun.bets.length;
936
+ }
937
+ }
938
+ }
939
+
940
+ // Helper functions
941
+ function getRandomColor(alpha = 1) {
942
+ const r = Math.floor(Math.random() * 200 + 55);
943
+ const g = Math.floor(Math.random() * 200 + 55);
944
+ const b = Math.floor(Math.random() * 200 + 55);
945
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
946
+ }
947
+
948
+ // Export functions (placeholder implementations)
949
+ document.getElementById('export-csv').addEventListener('click', () => {
950
+ alert('CSV export functionality would be implemented here');
951
+ });
952
+
953
+ document.getElementById('export-png').addEventListener('click', () => {
954
+ alert('PNG export functionality would be implemented here');
955
+ });
956
+
957
+ document.getElementById('export-zip').addEventListener('click', () => {
958
+ alert('ZIP export functionality would be implemented here');
959
+ });
960
+ </script>
961
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=johnfmarti/roulette-1" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
962
+ </html>