MarcRyan commited on
Commit
4637fbe
Β·
verified Β·
1 Parent(s): cee4955

Add 3 files

Browse files
Files changed (3) hide show
  1. README.md +7 -5
  2. index.html +677 -19
  3. prompts.txt +2 -0
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Stp
3
- emoji: πŸ‘
4
- colorFrom: blue
5
- colorTo: indigo
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: stp
3
+ emoji: 🐳
4
+ colorFrom: green
5
+ colorTo: green
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,677 @@
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>Soccer Team Performance Predictor</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/brain/0.6.3/brain.min.js"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
10
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
11
+ <style>
12
+ .neuron {
13
+ transition: all 0.3s ease;
14
+ }
15
+ .neuron:hover {
16
+ transform: scale(1.1);
17
+ }
18
+ .network-container {
19
+ perspective: 1000px;
20
+ }
21
+ .layer {
22
+ transform-style: preserve-3d;
23
+ }
24
+ .connection {
25
+ stroke-dasharray: 1000;
26
+ stroke-dashoffset: 1000;
27
+ animation: draw 1.5s forwards;
28
+ }
29
+ @keyframes draw {
30
+ to {
31
+ stroke-dashoffset: 0;
32
+ }
33
+ }
34
+ .progress-ring__circle {
35
+ transition: stroke-dashoffset 0.35s;
36
+ transform: rotate(-90deg);
37
+ transform-origin: 50% 50%;
38
+ }
39
+ .team-card:hover {
40
+ transform: translateY(-5px);
41
+ box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
42
+ }
43
+ .team-card {
44
+ transition: all 0.3s ease;
45
+ }
46
+ .soccer-pitch {
47
+ background: linear-gradient(to bottom, #4ade80, #22c55e);
48
+ position: relative;
49
+ overflow: hidden;
50
+ }
51
+ .soccer-pitch::before {
52
+ content: "";
53
+ position: absolute;
54
+ top: 0;
55
+ left: 50%;
56
+ width: 2px;
57
+ height: 100%;
58
+ background: white;
59
+ transform: translateX(-50%);
60
+ }
61
+ .soccer-pitch::after {
62
+ content: "";
63
+ position: absolute;
64
+ top: 50%;
65
+ left: 50%;
66
+ width: 100px;
67
+ height: 100px;
68
+ border: 2px solid white;
69
+ border-radius: 50%;
70
+ transform: translate(-50%, -50%);
71
+ }
72
+ </style>
73
+ </head>
74
+ <body class="bg-gray-50 min-h-screen">
75
+ <div class="container mx-auto px-4 py-8">
76
+ <header class="text-center mb-12">
77
+ <h1 class="text-4xl font-bold text-gray-800 mb-2">⚽ Soccer Team Performance Predictor</h1>
78
+ <p class="text-gray-600 max-w-2xl mx-auto">A neural network that predicts team loss probability based on key soccer performance metrics</p>
79
+ </header>
80
+
81
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
82
+ <!-- Configuration Panel -->
83
+ <div class="bg-white rounded-xl shadow-md p-6">
84
+ <h2 class="text-xl font-semibold text-gray-800 mb-4">Network Configuration</h2>
85
+ <div class="space-y-4">
86
+ <div>
87
+ <label class="block text-sm font-medium text-gray-700 mb-1">Hidden Layers</label>
88
+ <input type="range" id="hiddenLayersInput" min="1" max="5" value="3" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer">
89
+ <div class="flex justify-between text-xs text-gray-500">
90
+ <span>1</span>
91
+ <span>2</span>
92
+ <span>3</span>
93
+ <span>4</span>
94
+ <span>5</span>
95
+ </div>
96
+ </div>
97
+
98
+ <div>
99
+ <label class="block text-sm font-medium text-gray-700 mb-1">Neurons per Layer</label>
100
+ <input type="range" id="neuronsPerLayerInput" min="3" max="10" value="6" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer">
101
+ <div class="flex justify-between text-xs text-gray-500">
102
+ <span>3</span>
103
+ <span>4</span>
104
+ <span>5</span>
105
+ <span>6</span>
106
+ <span>7</span>
107
+ <span>8</span>
108
+ <span>9</span>
109
+ <span>10</span>
110
+ </div>
111
+ </div>
112
+
113
+ <div>
114
+ <label class="block text-sm font-medium text-gray-700 mb-1">Learning Rate</label>
115
+ <input type="range" id="learningRateInput" min="0.01" max="0.5" step="0.01" value="0.2" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer">
116
+ <div class="flex justify-between text-xs text-gray-500">
117
+ <span>0.01</span>
118
+ <span>0.25</span>
119
+ <span>0.5</span>
120
+ </div>
121
+ </div>
122
+
123
+ <div class="flex space-x-3 pt-2">
124
+ <button id="trainBtn" class="flex-1 bg-green-600 hover:bg-green-700 text-white py-2 px-4 rounded-lg flex items-center justify-center">
125
+ <i class="fas fa-brain mr-2"></i> Train Network
126
+ </button>
127
+ <button id="resetBtn" class="flex-1 bg-gray-200 hover:bg-gray-300 text-gray-800 py-2 px-4 rounded-lg flex items-center justify-center">
128
+ <i class="fas fa-redo mr-2"></i> Reset
129
+ </button>
130
+ </div>
131
+ </div>
132
+
133
+ <div class="mt-6">
134
+ <h3 class="text-sm font-medium text-gray-700 mb-2">Training Status</h3>
135
+ <div id="trainingStatus" class="text-sm text-gray-600 bg-gray-100 p-3 rounded-lg">
136
+ Network not trained yet
137
+ </div>
138
+ </div>
139
+ </div>
140
+
141
+ <!-- Network Visualization -->
142
+ <div class="bg-white rounded-xl shadow-md p-6">
143
+ <h2 class="text-xl font-semibold text-gray-800 mb-4">Network Architecture</h2>
144
+ <div id="networkVisualization" class="network-container h-64 flex justify-center items-center">
145
+ <svg id="networkSvg" width="100%" height="100%" viewBox="0 0 500 300"></svg>
146
+ </div>
147
+
148
+ <div class="mt-6">
149
+ <h3 class="text-sm font-medium text-gray-700 mb-2">Error Over Time</h3>
150
+ <div class="bg-gray-100 p-2 rounded-lg">
151
+ <canvas id="errorChart" height="150"></canvas>
152
+ </div>
153
+ </div>
154
+ </div>
155
+
156
+ <!-- Prediction Panel -->
157
+ <div class="bg-white rounded-xl shadow-md p-6">
158
+ <h2 class="text-xl font-semibold text-gray-800 mb-4">Make a Prediction</h2>
159
+ <div class="space-y-3">
160
+ <div>
161
+ <label class="block text-sm font-medium text-gray-700 mb-1">Goals Conceded per Game</label>
162
+ <input id="goalsConcededInput" type="number" step="0.1" class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-green-500 focus:border-green-500" placeholder="1.2">
163
+ </div>
164
+ <div>
165
+ <label class="block text-sm font-medium text-gray-700 mb-1">Shots on Target per Game</label>
166
+ <input id="shotsOnTargetInput" type="number" step="0.1" class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-green-500 focus:border-green-500" placeholder="5.5">
167
+ </div>
168
+ <div>
169
+ <label class="block text-sm font-medium text-gray-700 mb-1">Pass Accuracy %</label>
170
+ <input id="passAccuracyInput" type="number" step="0.1" class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-green-500 focus:border-green-500" placeholder="85.0">
171
+ </div>
172
+ <div>
173
+ <label class="block text-sm font-medium text-gray-700 mb-1">Tackles per Game</label>
174
+ <input id="tacklesInput" type="number" step="0.1" class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-green-500 focus:border-green-500" placeholder="15.0">
175
+ </div>
176
+
177
+ <button id="predictBtn" class="w-full bg-green-600 hover:bg-green-700 text-white py-2 px-4 rounded-lg mt-4 flex items-center justify-center">
178
+ <i class="fas fa-calculator mr-2"></i> Predict Loss Probability
179
+ </button>
180
+
181
+ <div id="predictionResult" class="mt-4 p-4 rounded-lg bg-green-50 hidden">
182
+ <h4 class="font-medium text-green-800 mb-1">Prediction Result</h4>
183
+ <p id="predictionText" class="text-green-600"></p>
184
+ <div class="mt-3 flex items-center">
185
+ <div class="w-12 h-12 mr-3">
186
+ <svg class="progress-ring" width="48" height="48">
187
+ <circle class="progress-ring__circle" stroke="#E5E7EB" stroke-width="4" fill="transparent" r="20" cx="24" cy="24"/>
188
+ <circle class="progress-ring__circle" stroke="#10B981" stroke-width="4" fill="transparent" r="20" cx="24" cy="24"/>
189
+ </svg>
190
+ </div>
191
+ <div class="text-2xl font-bold text-green-600" id="predictionPercentage">0%</div>
192
+ </div>
193
+ </div>
194
+ </div>
195
+ </div>
196
+ </div>
197
+
198
+ <!-- Team Cards -->
199
+ <div class="mt-12">
200
+ <h2 class="text-2xl font-bold text-gray-800 mb-6">Top European Clubs</h2>
201
+ <div id="teamPredictions" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6"></div>
202
+ </div>
203
+ </div>
204
+
205
+ <script>
206
+ document.addEventListener('DOMContentLoaded', function() {
207
+ // Configuration
208
+ const config = {
209
+ hiddenLayers: 3,
210
+ neuronsPerLayer: 6,
211
+ learningRate: 0.2,
212
+ iterations: 20000,
213
+ errorThresh: 0.005
214
+ };
215
+
216
+ // Sample soccer teams data
217
+ let soccerTeams = [
218
+ { name: "Manchester City", logo: "πŸ”΅", goalsConceded: 0.8, shotsOnTarget: 6.7, passAccuracy: 89.2, tackles: 12.3 },
219
+ { name: "Real Madrid", logo: "βšͺ", goalsConceded: 1.1, shotsOnTarget: 5.9, passAccuracy: 87.5, tackles: 14.2 },
220
+ { name: "Bayern Munich", logo: "πŸ”΄", goalsConceded: 0.9, shotsOnTarget: 6.3, passAccuracy: 88.1, tackles: 13.7 },
221
+ { name: "Liverpool", logo: "πŸ”΄", goalsConceded: 1.2, shotsOnTarget: 6.1, passAccuracy: 85.7, tackles: 15.8 },
222
+ { name: "Paris Saint-Germain", logo: "πŸ”΅", goalsConceded: 1.0, shotsOnTarget: 5.8, passAccuracy: 86.9, tackles: 11.9 },
223
+ { name: "Barcelona", logo: "πŸ”΅πŸ”΄", goalsConceded: 1.3, shotsOnTarget: 5.5, passAccuracy: 87.8, tackles: 12.5 },
224
+ { name: "Chelsea", logo: "πŸ”΅", goalsConceded: 1.4, shotsOnTarget: 4.9, passAccuracy: 84.3, tackles: 16.2 },
225
+ { name: "AC Milan", logo: "βš«πŸ”΄", goalsConceded: 1.2, shotsOnTarget: 4.7, passAccuracy: 83.5, tackles: 14.9 }
226
+ ];
227
+
228
+ // Initialize network
229
+ let net = new brain.NeuralNetwork();
230
+ let errorChart;
231
+ let trainingData = generateTrainingData();
232
+
233
+ // DOM Elements
234
+ const hiddenLayersInput = document.getElementById('hiddenLayersInput');
235
+ const neuronsPerLayerInput = document.getElementById('neuronsPerLayerInput');
236
+ const learningRateInput = document.getElementById('learningRateInput');
237
+ const trainBtn = document.getElementById('trainBtn');
238
+ const resetBtn = document.getElementById('resetBtn');
239
+ const goalsConcededInput = document.getElementById('goalsConcededInput');
240
+ const shotsOnTargetInput = document.getElementById('shotsOnTargetInput');
241
+ const passAccuracyInput = document.getElementById('passAccuracyInput');
242
+ const tacklesInput = document.getElementById('tacklesInput');
243
+ const predictBtn = document.getElementById('predictBtn');
244
+ const predictionResult = document.getElementById('predictionResult');
245
+ const predictionText = document.getElementById('predictionText');
246
+ const predictionPercentage = document.getElementById('predictionPercentage');
247
+ const teamPredictions = document.getElementById('teamPredictions');
248
+ const trainingStatus = document.getElementById('trainingStatus');
249
+
250
+ // Initialize UI
251
+ initUI();
252
+ drawNetwork();
253
+ initChart();
254
+ renderTeamCards();
255
+
256
+ // Event Listeners
257
+ hiddenLayersInput.addEventListener('input', updateConfig);
258
+ neuronsPerLayerInput.addEventListener('input', updateConfig);
259
+ learningRateInput.addEventListener('input', updateConfig);
260
+ trainBtn.addEventListener('click', trainNetwork);
261
+ resetBtn.addEventListener('click', resetNetwork);
262
+ predictBtn.addEventListener('click', predictLossProbability);
263
+
264
+ // Functions
265
+ function generateTrainingData() {
266
+ // Generate synthetic training data based on realistic soccer stats
267
+ const data = [];
268
+
269
+ for (let i = 0; i < 100; i++) {
270
+ // Generate random but realistic soccer stats
271
+ const goalsConceded = 0.5 + Math.random() * 2.5; // Between 0.5 and 3.0
272
+ const shotsOnTarget = 2.0 + Math.random() * 6.0; // Between 2.0 and 8.0
273
+ const passAccuracy = 70.0 + Math.random() * 25.0; // Between 70% and 95%
274
+ const tackles = 8.0 + Math.random() * 12.0; // Between 8 and 20
275
+
276
+ // Calculate a synthetic loss probability based on these stats
277
+ // Better stats (fewer goals conceded, more shots on target, higher pass accuracy, more tackles)
278
+ // should lead to lower loss probability
279
+ let lossProbability =
280
+ (goalsConceded / 3.0) * 0.4 + // Goals conceded contributes 40%
281
+ ((8.0 - shotsOnTarget) / 6.0) * 0.3 + // Shots on target contributes 30%
282
+ ((95.0 - passAccuracy) / 25.0) * 0.2 + // Pass accuracy contributes 20%
283
+ ((20.0 - tackles) / 12.0) * 0.1; // Tackles contributes 10%
284
+
285
+ // Add some randomness
286
+ lossProbability += (Math.random() - 0.5) * 0.1;
287
+
288
+ // Ensure between 0 and 1
289
+ lossProbability = Math.max(0, Math.min(1, lossProbability));
290
+
291
+ data.push({
292
+ input: {
293
+ goalsConceded: normalize(goalsConceded, 0.5, 3.0),
294
+ shotsOnTarget: normalize(shotsOnTarget, 2.0, 8.0),
295
+ passAccuracy: normalize(passAccuracy, 70.0, 95.0),
296
+ tackles: normalize(tackles, 8.0, 20.0)
297
+ },
298
+ output: {
299
+ loss: lossProbability
300
+ }
301
+ });
302
+ }
303
+
304
+ return data;
305
+ }
306
+
307
+ function normalize(value, min, max) {
308
+ return (value - min) / (max - min);
309
+ }
310
+
311
+ function denormalize(value, min, max) {
312
+ return value * (max - min) + min;
313
+ }
314
+
315
+ function initUI() {
316
+ // Set initial values from config
317
+ hiddenLayersInput.value = config.hiddenLayers;
318
+ neuronsPerLayerInput.value = config.neuronsPerLayer;
319
+ learningRateInput.value = config.learningRate;
320
+
321
+ // Initialize prediction progress ring
322
+ const circle = document.querySelector('.progress-ring__circle:last-child');
323
+ const radius = circle.r.baseVal.value;
324
+ const circumference = radius * 2 * Math.PI;
325
+
326
+ circle.style.strokeDasharray = circumference;
327
+ circle.style.strokeDashoffset = circumference;
328
+ }
329
+
330
+ function updateConfig() {
331
+ config.hiddenLayers = parseInt(hiddenLayersInput.value);
332
+ config.neuronsPerLayer = parseInt(neuronsPerLayerInput.value);
333
+ config.learningRate = parseFloat(learningRateInput.value);
334
+
335
+ drawNetwork();
336
+ }
337
+
338
+ function resetNetwork() {
339
+ net = new brain.NeuralNetwork();
340
+ trainingStatus.textContent = "Network reset - not trained";
341
+ trainingStatus.className = "text-sm text-gray-600 bg-gray-100 p-3 rounded-lg";
342
+
343
+ // Reset chart
344
+ if (errorChart) {
345
+ errorChart.data.labels = [];
346
+ errorChart.data.datasets[0].data = [];
347
+ errorChart.update();
348
+ }
349
+
350
+ // Hide prediction result
351
+ predictionResult.classList.add('hidden');
352
+ }
353
+
354
+ function trainNetwork() {
355
+ trainBtn.disabled = true;
356
+ trainBtn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i> Training...';
357
+ trainingStatus.textContent = "Training in progress...";
358
+ trainingStatus.className = "text-sm text-green-600 bg-green-100 p-3 rounded-lg";
359
+
360
+ // Configure network
361
+ net = new brain.NeuralNetwork({
362
+ hiddenLayers: [Array(config.hiddenLayers).fill(config.neuronsPerLayer)].flat(),
363
+ learningRate: config.learningRate,
364
+ iterations: config.iterations,
365
+ errorThresh: config.errorThresh,
366
+ log: true,
367
+ logPeriod: 1000,
368
+ callback: function(info) {
369
+ updateTrainingStatus(info.iterations, info.error);
370
+ updateChart(info.iterations, info.error);
371
+ },
372
+ callbackPeriod: 1000
373
+ });
374
+
375
+ // Train in a timeout to allow UI to update
376
+ setTimeout(() => {
377
+ net.train(trainingData, (err, info) => {
378
+ trainBtn.disabled = false;
379
+ trainBtn.innerHTML = '<i class="fas fa-brain mr-2"></i> Train Network';
380
+
381
+ if (err) {
382
+ trainingStatus.textContent = "Training failed: " + err;
383
+ trainingStatus.className = "text-sm text-red-600 bg-red-100 p-3 rounded-lg";
384
+ } else {
385
+ trainingStatus.textContent = `Training complete! Final error: ${info.error.toFixed(6)} after ${info.iterations} iterations`;
386
+ trainingStatus.className = "text-sm text-green-600 bg-green-100 p-3 rounded-lg";
387
+ }
388
+
389
+ // Animate network connections
390
+ animateNetwork();
391
+ });
392
+ }, 100);
393
+ }
394
+
395
+ function updateTrainingStatus(iterations, error) {
396
+ trainingStatus.textContent = `Training... Iteration: ${iterations}, Error: ${error.toFixed(6)}`;
397
+ }
398
+
399
+ function initChart() {
400
+ const ctx = document.getElementById('errorChart').getContext('2d');
401
+ errorChart = new Chart(ctx, {
402
+ type: 'line',
403
+ data: {
404
+ labels: [],
405
+ datasets: [{
406
+ label: 'Training Error',
407
+ data: [],
408
+ borderColor: 'rgb(16, 185, 129)',
409
+ backgroundColor: 'rgba(16, 185, 129, 0.1)',
410
+ borderWidth: 2,
411
+ tension: 0.4,
412
+ fill: true
413
+ }]
414
+ },
415
+ options: {
416
+ responsive: true,
417
+ maintainAspectRatio: false,
418
+ scales: {
419
+ y: {
420
+ beginAtZero: true,
421
+ title: {
422
+ display: true,
423
+ text: 'Error'
424
+ }
425
+ },
426
+ x: {
427
+ title: {
428
+ display: true,
429
+ text: 'Iterations'
430
+ }
431
+ }
432
+ },
433
+ plugins: {
434
+ legend: {
435
+ display: false
436
+ },
437
+ tooltip: {
438
+ callbacks: {
439
+ label: function(context) {
440
+ return `Error: ${context.parsed.y.toFixed(6)}`;
441
+ }
442
+ }
443
+ }
444
+ }
445
+ }
446
+ });
447
+ }
448
+
449
+ function updateChart(iteration, error) {
450
+ errorChart.data.labels.push(iteration);
451
+ errorChart.data.datasets[0].data.push(error);
452
+ errorChart.update();
453
+ }
454
+
455
+ function drawNetwork() {
456
+ const svg = document.getElementById('networkSvg');
457
+ svg.innerHTML = '';
458
+
459
+ const width = 500;
460
+ const height = 300;
461
+ const layerCount = config.hiddenLayers + 2; // Input + hidden + output
462
+ const neuronRadius = 15;
463
+
464
+ // Draw layers
465
+ for (let layer = 0; layer < layerCount; layer++) {
466
+ const isInput = layer === 0;
467
+ const isOutput = layer === layerCount - 1;
468
+
469
+ let neuronCount;
470
+ if (isInput) neuronCount = 4; // 4 input features
471
+ else if (isOutput) neuronCount = 1; // 1 output (loss probability)
472
+ else neuronCount = config.neuronsPerLayer;
473
+
474
+ const layerX = 50 + (width - 100) * (layer / (layerCount - 1));
475
+
476
+ // Draw neurons
477
+ for (let n = 0; n < neuronCount; n++) {
478
+ const neuronY = height / 2 + (n - (neuronCount - 1) / 2) * 40;
479
+
480
+ // Neuron circle
481
+ const neuron = document.createElementNS("http://www.w3.org/2000/svg", "circle");
482
+ neuron.setAttribute("cx", layerX);
483
+ neuron.setAttribute("cy", neuronY);
484
+ neuron.setAttribute("r", neuronRadius);
485
+ neuron.setAttribute("class", "neuron");
486
+
487
+ if (isInput) {
488
+ neuron.setAttribute("fill", "#4ADE80"); // Green for input
489
+ } else if (isOutput) {
490
+ neuron.setAttribute("fill", "#3B82F6"); // Blue for output
491
+ } else {
492
+ neuron.setAttribute("fill", "#F59E0B"); // Yellow for hidden
493
+ }
494
+
495
+ svg.appendChild(neuron);
496
+
497
+ // Neuron label
498
+ if (isInput) {
499
+ const labels = ["Goals Conceded", "Shots on Target", "Pass %", "Tackles"];
500
+ const text = document.createElementNS("http://www.w3.org/2000/svg", "text");
501
+ text.setAttribute("x", layerX - 50);
502
+ text.setAttribute("y", neuronY + 5);
503
+ text.setAttribute("text-anchor", "end");
504
+ text.setAttribute("class", "text-xs font-medium fill-gray-700");
505
+ text.textContent = labels[n];
506
+ svg.appendChild(text);
507
+ } else if (isOutput) {
508
+ const text = document.createElementNS("http://www.w3.org/2000/svg", "text");
509
+ text.setAttribute("x", layerX + 50);
510
+ text.setAttribute("y", neuronY + 5);
511
+ text.setAttribute("text-anchor", "start");
512
+ text.setAttribute("class", "text-xs font-medium fill-gray-700");
513
+ text.textContent = "Loss %";
514
+ svg.appendChild(text);
515
+ }
516
+ }
517
+ }
518
+ }
519
+
520
+ function animateNetwork() {
521
+ const svg = document.getElementById('networkSvg');
522
+ const connections = [];
523
+
524
+ const width = 500;
525
+ const height = 300;
526
+ const layerCount = config.hiddenLayers + 2;
527
+ const neuronRadius = 15;
528
+
529
+ // Create connections between layers
530
+ for (let layer = 0; layer < layerCount - 1; layer++) {
531
+ const isFirstLayer = layer === 0;
532
+ const isLastLayer = layer === layerCount - 2;
533
+
534
+ let fromNeuronCount;
535
+ if (isFirstLayer) fromNeuronCount = 4;
536
+ else fromNeuronCount = config.neuronsPerLayer;
537
+
538
+ let toNeuronCount;
539
+ if (isLastLayer) toNeuronCount = 1;
540
+ else toNeuronCount = config.neuronsPerLayer;
541
+
542
+ const fromLayerX = 50 + (width - 100) * (layer / (layerCount - 1));
543
+ const toLayerX = 50 + (width - 100) * ((layer + 1) / (layerCount - 1));
544
+
545
+ for (let from = 0; from < fromNeuronCount; from++) {
546
+ const fromY = height / 2 + (from - (fromNeuronCount - 1) / 2) * 40;
547
+
548
+ for (let to = 0; to < toNeuronCount; to++) {
549
+ const toY = height / 2 + (to - (toNeuronCount - 1) / 2) * 40;
550
+
551
+ const line = document.createElementNS("http://www.w3.org/2000/svg", "line");
552
+ line.setAttribute("x1", fromLayerX + neuronRadius);
553
+ line.setAttribute("y1", fromY);
554
+ line.setAttribute("x2", toLayerX - neuronRadius);
555
+ line.setAttribute("y2", toY);
556
+ line.setAttribute("stroke", "#9CA3AF");
557
+ line.setAttribute("stroke-width", "1");
558
+ line.setAttribute("class", "connection");
559
+ svg.appendChild(line);
560
+
561
+ connections.push(line);
562
+ }
563
+ }
564
+ }
565
+
566
+ // Animate connections with staggered delay
567
+ connections.forEach((conn, i) => {
568
+ setTimeout(() => {
569
+ conn.style.strokeDashoffset = "0";
570
+ }, i * 20);
571
+ });
572
+ }
573
+
574
+ function predictLossProbability() {
575
+ if (!net.trainOpts) {
576
+ predictionText.textContent = "Please train the network first";
577
+ predictionResult.classList.remove('hidden');
578
+ predictionResult.className = "mt-4 p-4 rounded-lg bg-yellow-50";
579
+ return;
580
+ }
581
+
582
+ // Get input values
583
+ const goalsConceded = parseFloat(goalsConcededInput.value) || 1.2;
584
+ const shotsOnTarget = parseFloat(shotsOnTargetInput.value) || 5.5;
585
+ const passAccuracy = parseFloat(passAccuracyInput.value) || 85.0;
586
+ const tackles = parseFloat(tacklesInput.value) || 15.0;
587
+
588
+ // Normalize inputs
589
+ const normalizedInput = {
590
+ goalsConceded: normalize(goalsConceded, 0.5, 3.0),
591
+ shotsOnTarget: normalize(shotsOnTarget, 2.0, 8.0),
592
+ passAccuracy: normalize(passAccuracy, 70.0, 95.0),
593
+ tackles: normalize(tackles, 8.0, 20.0)
594
+ };
595
+
596
+ // Make prediction
597
+ const output = net.run(normalizedInput);
598
+ const lossProbability = output.loss;
599
+ const percentage = Math.round(lossProbability * 100);
600
+
601
+ // Display result
602
+ predictionText.textContent = `Based on the team's stats (Goals Conceded: ${goalsConceded.toFixed(1)}, Shots on Target: ${shotsOnTarget.toFixed(1)}, Pass Accuracy: ${passAccuracy.toFixed(1)}%, Tackles: ${tackles.toFixed(1)}), the predicted loss probability is:`;
603
+ predictionPercentage.textContent = `${percentage}%`;
604
+
605
+ // Update progress ring
606
+ const circle = document.querySelector('.progress-ring__circle:last-child');
607
+ const radius = circle.r.baseVal.value;
608
+ const circumference = radius * 2 * Math.PI;
609
+ const offset = circumference - (percentage / 100) * circumference;
610
+
611
+ circle.style.strokeDashoffset = offset;
612
+
613
+ // Set color based on probability
614
+ if (percentage > 70) {
615
+ circle.style.stroke = "#EF4444"; // red
616
+ predictionPercentage.className = "text-2xl font-bold text-red-600";
617
+ } else if (percentage > 50) {
618
+ circle.style.stroke = "#F59E0B"; // orange
619
+ predictionPercentage.className = "text-2xl font-bold text-yellow-600";
620
+ } else {
621
+ circle.style.stroke = "#10B981"; // green
622
+ predictionPercentage.className = "text-2xl font-bold text-green-600";
623
+ }
624
+
625
+ predictionResult.classList.remove('hidden');
626
+ predictionResult.className = "mt-4 p-4 rounded-lg bg-green-50";
627
+ }
628
+
629
+ function renderTeamCards() {
630
+ teamPredictions.innerHTML = '';
631
+
632
+ soccerTeams.forEach(team => {
633
+ const card = document.createElement('div');
634
+ card.className = 'bg-white rounded-lg shadow-md p-4 team-card hover:shadow-lg transition-all';
635
+ card.innerHTML = `
636
+ <div class="flex items-center mb-3">
637
+ <div class="text-2xl mr-3">${team.logo}</div>
638
+ <h3 class="font-semibold text-gray-800">${team.name}</h3>
639
+ </div>
640
+ <div class="grid grid-cols-2 gap-2 text-sm mb-3">
641
+ <div><span class="text-gray-500">Goals Conceded:</span> ${team.goalsConceded.toFixed(1)}</div>
642
+ <div><span class="text-gray-500">Shots on Target:</span> ${team.shotsOnTarget.toFixed(1)}</div>
643
+ <div><span class="text-gray-500">Pass %:</span> ${team.passAccuracy.toFixed(1)}%</div>
644
+ <div><span class="text-gray-500">Tackles:</span> ${team.tackles.toFixed(1)}</div>
645
+ </div>
646
+ <div class="flex items-center">
647
+ <button class="w-full bg-green-100 hover:bg-green-200 text-green-800 py-2 px-3 rounded flex items-center justify-center predict-btn" data-team='${JSON.stringify(team)}'>
648
+ <i class="fas fa-calculator mr-2 text-xs"></i> Predict Performance
649
+ </button>
650
+ </div>
651
+ `;
652
+ teamPredictions.appendChild(card);
653
+ });
654
+
655
+ // Add event listeners to predict buttons
656
+ document.querySelectorAll('.predict-btn').forEach(btn => {
657
+ btn.addEventListener('click', function() {
658
+ const team = JSON.parse(this.getAttribute('data-team'));
659
+ goalsConcededInput.value = team.goalsConceded;
660
+ shotsOnTargetInput.value = team.shotsOnTarget;
661
+ passAccuracyInput.value = team.passAccuracy;
662
+ tacklesInput.value = team.tackles;
663
+
664
+ if (net.trainOpts) {
665
+ predictLossProbability();
666
+ } else {
667
+ predictionText.textContent = "Please train the network first";
668
+ predictionResult.classList.remove('hidden');
669
+ predictionResult.className = "mt-4 p-4 rounded-lg bg-yellow-50";
670
+ }
671
+ });
672
+ });
673
+ }
674
+ });
675
+ </script>
676
+ <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=MarcRyan/stp" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
677
+ </html>
prompts.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ put this in a browser <!DOCTYPE html> <html> <head> <title>My app</title> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta charset="utf-8"> <style> body { display: flex; justify-content: center; align-items: center; overflow: hidden; height: 100dvh; font-family: "Arial", sans-serif; text-align: center; } .arrow { position: absolute; bottom: 32px; left: 0px; width: 100px; transform: rotate(30deg); } h1 { font-size: 50px; } h1 span { color: #acacac; font-size: 32px; } </style> </head> <body> <h1> <span>I'm ready to work,</span><br /> Ask me anything. </h1> <img src="https://enzostvs-deepsite.hf.space/arrow.svg" class="arrow" /> <script></script> </body> </html>
2
+ make this but for soccer - <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Baseball Team Performance Predictor</title> <script src="https://cdn.tailwindcss.com"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/brain/0.6.3/brain.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> <style> .neuron { transition: all 0.3s ease; } .neuron:hover { transform: scale(1.1); } .network-container { perspective: 1000px; } .layer { transform-style: preserve-3d; } .connection { stroke-dasharray: 1000; stroke-dashoffset: 1000; animation: draw 1.5s forwards; } @keyframes draw { to { stroke-dashoffset: 0; } } .progress-ring__circle { transition: stroke-dashoffset 0.35s; transform: rotate(-90deg); transform-origin: 50% 50%; } .team-card:hover { transform: translateY(-5px); box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1); } .team-card { transition: all 0.3s ease; } </style> </head> <body class="bg-gray-50 min-h-screen"> <div class="container mx-auto px-4 py-8"> <header class="text-center mb-12"> <h1 class="text-4xl font-bold text-gray-800 mb-2">⚾ Baseball Team Performance Predictor</h1> <p class="text-gray-600 max-w-2xl mx-auto">A neural network that predicts team loss probability based on key performance metrics</p> </header> <div class="grid grid-cols-1 lg:grid-cols-3 gap-8"> <!-- Configuration Panel --> <div class="bg-white rounded-xl shadow-md p-6"> <h2 class="text-xl font-semibold text-gray-800 mb-4">Network Configuration</h2> <div class="space-y-4"> <div> <label class="block text-sm font-medium text-gray-700 mb-1">Hidden Layers</label> <input type="range" id="hiddenLayersInput" min="1" max="5" value="3" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer"> <div class="flex justify-between text-xs text-gray-500"> <span>1</span> <span>2</span> <span>3</span> <span>4</span> <span>5</span> </div> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-1">Neurons per Layer</label> <input type="range" id="neuronsPerLayerInput" min="3" max="10" value="6" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer"> <div class="flex justify-between text-xs text-gray-500"> <span>3</span> <span>4</span> <span>5</span> <span>6</span> <span>7</span> <span>8</span> <span>9</span> <span>10</span> </div> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-1">Learning Rate</label> <input type="range" id="learningRateInput" min="0.01" max="0.5" step="0.01" value="0.2" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer"> <div class="flex justify-between text-xs text-gray-500"> <span>0.01</span> <span>0.25</span> <span>0.5</span> </div> </div> <div class="flex space-x-3 pt-2"> <button id="trainBtn" class="flex-1 bg-blue-600 hover:bg-blue-700 text-white py-2 px-4 rounded-lg flex items-center justify-center"> <i class="fas fa-brain mr-2"></i> Train Network </button> <button id="resetBtn" class="flex-1 bg-gray-200 hover:bg-gray-300 text-gray-800 py-2 px-4 rounded-lg flex items-center justify-center"> <i class="fas fa-redo mr-2"></i> Reset </button> </div> </div> <div class="mt-6"> <h3 class="text-sm font-medium text-gray-700 mb-2">Training Status</h3> <div id="trainingStatus" class="text-sm text-gray-600 bg-gray-100 p-3 rounded-lg"> Network not trained yet </div> </div> </div> <!-- Network Visualization --> <div class="bg-white rounded-xl shadow-md p-6"> <h2 class="text-xl font-semibold text-gray-800 mb-4">Network Architecture</h2> <div id="networkVisualization" class="network-container h-64 flex justify-center items-center"> <svg id="networkSvg" width="100%" height="100%" viewBox="0 0 500 300"></svg> </div> <div class="mt-6"> <h3 class="text-sm font-medium text-gray-700 mb-2">Error Over Time</h3> <div class="bg-gray-100 p-2 rounded-lg"> <canvas id="errorChart" height="150"></canvas> </div> </div> </div> <!-- Prediction Panel --> <div class="bg-white rounded-xl shadow-md p-6"> <h2 class="text-xl font-semibold text-gray-800 mb-4">Make a Prediction</h2> <div class="space-y-3"> <div> <label class="block text-sm font-medium text-gray-700 mb-1">Team ERA</label> <input id="eraInput" type="number" step="0.01" class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500" placeholder="4.50"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-1">Team Batting Average</label> <input id="baInput" type="number" step="0.001" class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500" placeholder="0.250"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-1">Home Runs</label> <input id="hrInput" type="number" class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500" placeholder="150"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-1">Fielding Errors</label> <input id="errorsInput" type="number" class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500" placeholder="100"> </div> <button id="predictBtn" class="w-full bg-green-600 hover:bg-green-700 text-white py-2 px-4 rounded-lg mt-4 flex items-center justify-center"> <i class="fas fa-calculator mr-2"></i> Predict Loss Probability </button> <div id="predictionResult" class="mt-4 p-4 rounded-lg bg-blue-50 hidden"> <h4 class="font-medium text-blue-800 mb-1">Prediction Result</h4> <p id="predictionText" class="text-blue-600"></p> <div class="mt-3 flex items-center"> <div class="w-12 h-12 mr-3"> <svg class="progress-ring" width="48" height="48"> <circle class="progress-ring__circle" stroke="#E5E7EB" stroke-width="4" fill="transparent" r="20" cx="24" cy="24"/> <circle class="progress-ring__circle" stroke="#3B82F6" stroke-width="4" fill="transparent" r="20" cx="24" cy="24"/> </svg> </div> <div class="text-2xl font-bold text-blue-600" id="predictionPercentage">0%</div> </div> </div> </div> </div> </div> <!-- Team Cards --> <div class="mt-12"> <h2 class="text-2xl font-bold text-gray-800 mb-6">MLB Teams</h2> <div id="teamPredictions" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6"></div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Configuration const config = { hiddenLayers: 3, neuronsPerLayer: 6, learningRate: 0.2, iterations: 20000, errorThresh: 0.005 }; // Sample baseball teams data let baseballTeams = [ { name: "New York Yankees", logo: "πŸ†", era: 3.75, ba: 0.257, hr: 245, errors: 85 }, { name: "Los Angeles Dodgers", logo: "πŸ”΅", era: 3.42, ba: 0.263, hr: 235, errors: 78 }, { name: "Houston Astros", logo: "🌟", era: 3.68, ba: 0.261, hr: 221, errors: 92 }, { name: "Atlanta Braves", logo: "πŸ”΄", era: 3.89, ba: 0.255, hr: 239, errors: 87 }, { name: "Boston Red Sox", logo: "🧦", era: 4.12, ba: 0.249, hr: 198, errors: 105 }, { name: "Chicago Cubs", logo: "🐻", era: 4.05, ba: 0.242, hr: 187, errors: 112 }, { name: "San Francisco Giants", logo: "πŸŒ‰", era: 3.95, ba: 0.247, hr: 176, errors: 98 }, { name: "St. Louis Cardinals", logo: "🐦", era: 3.78, ba: 0.254, hr: 203, errors: 89 } ]; // Initialize network let net = new brain.NeuralNetwork(); let errorChart; let trainingData = generateTrainingData(); // DOM Elements const hiddenLayersInput = document.getElementById('hiddenLayersInput'); const neuronsPerLayerInput = document.getElementById('neuronsPerLayerInput'); const learningRateInput = document.getElementById('learningRateInput'); const trainBtn = document.getElementById('trainBtn'); const resetBtn = document.getElementById('resetBtn'); const eraInput = document.getElementById('eraInput'); const baInput = document.getElementById('baInput'); const hrInput = document.getElementById('hrInput'); const errorsInput = document.getElementById('errorsInput'); const predictBtn = document.getElementById('predictBtn'); const predictionResult = document.getElementById('predictionResult'); const predictionText = document.getElementById('predictionText'); const predictionPercentage = document.getElementById('predictionPercentage'); const teamPredictions = document.getElementById('teamPredictions'); const trainingStatus = document.getElementById('trainingStatus'); // Initialize UI initUI(); drawNetwork(); initChart(); renderTeamCards(); // Event Listeners hiddenLayersInput.addEventListener('input', updateConfig); neuronsPerLayerInput.addEventListener('input', updateConfig); learningRateInput.addEventListener('input', updateConfig); trainBtn.addEventListener('click', trainNetwork); resetBtn.addEventListener('click', resetNetwork); predictBtn.addEventListener('click', predictLossProbability); // Functions function generateTrainingData() { // Generate synthetic training data based on realistic baseball stats const data = []; for (let i = 0; i < 100; i++) { // Generate random but realistic baseball stats const era = 2.5 + Math.random() * 3.5; // ERA between 2.5 and 6.0 const ba = 0.220 + Math.random() * 0.080; // BA between .220 and .300 const hr = 100 + Math.random() * 200; // HR between 100 and 300 const errors = 50 + Math.random() * 100; // Errors between 50 and 150 // Calculate a synthetic loss probability based on these stats // Better stats (lower ERA, higher BA, more HR, fewer errors) should lead to lower loss probability let lossProbability = (era / 6.0) * 0.4 + // ERA contributes 40% ((0.300 - ba) / 0.080) * 0.3 + // BA contributes 30% ((300 - hr) / 200) * 0.2 + // HR contributes 20% (errors / 150) * 0.1; // Errors contribute 10% // Add some randomness lossProbability += (Math.random() - 0.5) * 0.1; // Ensure between 0 and 1 lossProbability = Math.max(0, Math.min(1, lossProbability)); data.push({ input: { era: normalize(era, 2.5, 6.0), ba: normalize(ba, 0.220, 0.300), hr: normalize(hr, 100, 300), errors: normalize(errors, 50, 150) }, output: { loss: lossProbability } }); } return data; } function normalize(value, min, max) { return (value - min) / (max - min); } function denormalize(value, min, max) { return value * (max - min) + min; } function initUI() { // Set initial values from config hiddenLayersInput.value = config.hiddenLayers; neuronsPerLayerInput.value = config.neuronsPerLayer; learningRateInput.value = config.learningRate; // Initialize prediction progress ring const circle = document.querySelector('.progress-ring__circle:last-child'); const radius = circle.r.baseVal.value; const circumference = radius * 2 * Math.PI; circle.style.strokeDasharray = circumference; circle.style.strokeDashoffset = circumference; } function updateConfig() { config.hiddenLayers = parseInt(hiddenLayersInput.value); config.neuronsPerLayer = parseInt(neuronsPerLayerInput.value); config.learningRate = parseFloat(learningRateInput.value); drawNetwork(); } function resetNetwork() { net = new brain.NeuralNetwork(); trainingStatus.textContent = "Network reset - not trained"; trainingStatus.className = "text-sm text-gray-600 bg-gray-100 p-3 rounded-lg"; // Reset chart if (errorChart) { errorChart.data.labels = []; errorChart.data.datasets[0].data = []; errorChart.update(); } // Hide prediction result predictionResult.classList.add('hidden'); } function trainNetwork() { trainBtn.disabled = true; trainBtn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i> Training...'; trainingStatus.textContent = "Training in progress..."; trainingStatus.className = "text-sm text-blue-600 bg-blue-100 p-3 rounded-lg"; // Configure network net = new brain.NeuralNetwork({ hiddenLayers: [Array(config.hiddenLayers).fill(config.neuronsPerLayer)].flat(), learningRate: config.learningRate, iterations: config.iterations, errorThresh: config.errorThresh, log: true, logPeriod: 1000, callback: function(info) { updateTrainingStatus(info.iterations, info.error); updateChart(info.iterations, info.error); }, callbackPeriod: 1000 }); // Train in a timeout to allow UI to update setTimeout(() => { net.train(trainingData, (err, info) => { trainBtn.disabled = false; trainBtn.innerHTML = '<i class="fas fa-brain mr-2"></i> Train Network'; if (err) { trainingStatus.textContent = "Training failed: " + err; trainingStatus.className = "text-sm text-red-600 bg-red-100 p-3 rounded-lg"; } else { trainingStatus.textContent = `Training complete! Final error: ${info.error.toFixed(6)} after ${info.iterations} iterations`; trainingStatus.className = "text-sm text-green-600 bg-green-100 p-3 rounded-lg"; } // Animate network connections animateNetwork(); }); }, 100); } function updateTrainingStatus(iterations, error) { trainingStatus.textContent = `Training... Iteration: ${iterations}, Error: ${error.toFixed(6)}`; } function initChart() { const ctx = document.getElementById('errorChart').getContext('2d'); errorChart = new Chart(ctx, { type: 'line', data: { labels: [], datasets: [{ label: 'Training Error', data: [], borderColor: 'rgb(99, 102, 241)', backgroundColor: 'rgba(99, 102, 241, 0.1)', borderWidth: 2, tension: 0.4, fill: true }] }, options: { responsive: true, maintainAspectRatio: false, scales: { y: { beginAtZero: true, title: { display: true, text: 'Error' } }, x: { title: { display: true, text: 'Iterations' } } }, plugins: { legend: { display: false }, tooltip: { callbacks: { label: function(context) { return `Error: ${context.parsed.y.toFixed(6)}`; } } } } } }); } function updateChart(iteration, error) { errorChart.data.labels.push(iteration); errorChart.data.datasets[0].data.push(error); errorChart.update(); } function drawNetwork() { const svg = document.getElementById('networkSvg'); svg.innerHTML = ''; const width = 500; const height = 300; const layerCount = config.hiddenLayers + 2; // Input + hidden + output const neuronRadius = 15; // Draw layers for (let layer = 0; layer < layerCount; layer++) { const isInput = layer === 0; const isOutput = layer === layerCount - 1; let neuronCount; if (isInput) neuronCount = 4; // 4 input features else if (isOutput) neuronCount = 1; // 1 output (loss probability) else neuronCount = config.neuronsPerLayer; const layerX = 50 + (width - 100) * (layer / (layerCount - 1)); // Draw neurons for (let n = 0; n < neuronCount; n++) { const neuronY = height / 2 + (n - (neuronCount - 1) / 2) * 40; // Neuron circle const neuron = document.createElementNS("http://www.w3.org/2000/svg", "circle"); neuron.setAttribute("cx", layerX); neuron.setAttribute("cy", neuronY); neuron.setAttribute("r", neuronRadius); neuron.setAttribute("class", "neuron"); if (isInput) { neuron.setAttribute("fill", "#60A5FA"); // Blue for input } else if (isOutput) { neuron.setAttribute("fill", "#10B981"); // Green for output } else { neuron.setAttribute("fill", "#F59E0B"); // Yellow for hidden } svg.appendChild(neuron); // Neuron label if (isInput) { const labels = ["ERA", "BA", "HR", "Errors"]; const text = document.createElementNS("http://www.w3.org/2000/svg", "text"); text.setAttribute("x", layerX - 50); text.setAttribute("y", neuronY + 5); text.setAttribute("text-anchor", "end"); text.setAttribute("class", "text-xs font-medium fill-gray-700"); text.textContent = labels[n]; svg.appendChild(text); } else if (isOutput) { const text = document.createElementNS("http://www.w3.org/2000/svg", "text"); text.setAttribute("x", layerX + 50); text.setAttribute("y", neuronY + 5); text.setAttribute("text-anchor", "start"); text.setAttribute("class", "text-xs font-medium fill-gray-700"); text.textContent = "Loss %"; svg.appendChild(text); } } } } function animateNetwork() { const svg = document.getElementById('networkSvg'); const connections = []; const width = 500; const height = 300; const layerCount = config.hiddenLayers + 2; const neuronRadius = 15; // Create connections between layers for (let layer = 0; layer < layerCount - 1; layer++) { const isFirstLayer = layer === 0; const isLastLayer = layer === layerCount - 2; let fromNeuronCount; if (isFirstLayer) fromNeuronCount = 4; else fromNeuronCount = config.neuronsPerLayer; let toNeuronCount; if (isLastLayer) toNeuronCount = 1; else toNeuronCount = config.neuronsPerLayer; const fromLayerX = 50 + (width - 100) * (layer / (layerCount - 1)); const toLayerX = 50 + (width - 100) * ((layer + 1) / (layerCount - 1)); for (let from = 0; from < fromNeuronCount; from++) { const fromY = height / 2 + (from - (fromNeuronCount - 1) / 2) * 40; for (let to = 0; to < toNeuronCount; to++) { const toY = height / 2 + (to - (toNeuronCount - 1) / 2) * 40; const line = document.createElementNS("http://www.w3.org/2000/svg", "line"); line.setAttribute("x1", fromLayerX + neuronRadius); line.setAttribute("y1", fromY); line.setAttribute("x2", toLayerX - neuronRadius); line.setAttribute("y2", toY); line.setAttribute("stroke", "#9CA3AF"); line.setAttribute("stroke-width", "1"); line.setAttribute("class", "connection"); svg.appendChild(line); connections.push(line); } } } // Animate connections with staggered delay connections.forEach((conn, i) => { setTimeout(() => { conn.style.strokeDashoffset = "0"; }, i * 20); }); } function predictLossProbability() { if (!net.trainOpts) { predictionText.textContent = "Please train the network first"; predictionResult.classList.remove('hidden'); predictionResult.className = "mt-4 p-4 rounded-lg bg-yellow-50"; return; } // Get input values const era = parseFloat(eraInput.value) || 4.50; const ba = parseFloat(baInput.value) || 0.250; const hr = parseInt(hrInput.value) || 150; const errors = parseInt(errorsInput.value) || 100; // Normalize inputs const normalizedInput = { era: normalize(era, 2.5, 6.0), ba: normalize(ba, 0.220, 0.300), hr: normalize(hr, 100, 300), errors: normalize(errors, 50, 150) }; // Make prediction const output = net.run(normalizedInput); const lossProbability = output.loss; const percentage = Math.round(lossProbability * 100); // Display result predictionText.textContent = `Based on the team's stats (ERA: ${era.toFixed(2)}, BA: ${ba.toFixed(3)}, HR: ${hr}, Errors: ${errors}), the predicted loss probability is:`; predictionPercentage.textContent = `${percentage}%`; // Update progress ring const circle = document.querySelector('.progress-ring__circle:last-child'); const radius = circle.r.baseVal.value; const circumference = radius * 2 * Math.PI; const offset = circumference - (percentage / 100) * circumference; circle.style.strokeDashoffset = offset; // Set color based on probability if (percentage > 70) { circle.style.stroke = "#EF4444"; // red predictionPercentage.className = "text-2xl font-bold text-red-600"; } else if (percentage > 50) { circle.style.stroke = "#F59E0B"; // orange predictionPercentage.className = "text-2xl font-bold text-yellow-600"; } else { circle.style.stroke = "#10B981"; // green predictionPercentage.className = "text-2xl font-bold text-green-600"; } predictionResult.classList.remove('hidden'); predictionResult.className = "mt-4 p-4 rounded-lg bg-blue-50"; } function renderTeamCards() { teamPredictions.innerHTML = ''; baseballTeams.forEach(team => { const card = document.createElement('div'); card.className = 'bg-white rounded-lg shadow-md p-4 team-card hover:shadow-lg transition-all'; card.innerHTML = ` <div class="flex items-center mb-3"> <div class="text-2xl mr-3">${team.logo}</div> <h3 class="font-semibold text-gray-800">${team.name}</h3> </div> <div class="grid grid-cols-2 gap-2 text-sm mb-3"> <div><span class="text-gray-500">ERA:</span> ${team.era.toFixed(2)}</div> <div><span class="text-gray-500">BA:</span> ${team.ba.toFixed(3)}</div> <div><span class="text-gray-500">HR:</span> ${team.hr}</div> <div><span class="text-gray-500">Errors:</span> ${team.errors}</div> </div> <div class="flex items-center"> <button class="w-full bg-blue-100 hover:bg-blue-200 text-blue-800 py-2 px-3 rounded flex items-center justify-center predict-btn" data-team='${JSON.stringify(team)}'> <i class="fas fa-calculator mr-2 text-xs"></i> Predict Performance </button> </div> `; teamPredictions.appendChild(card); }); // Add event listeners to predict buttons document.querySelectorAll('.predict-btn').forEach(btn => { btn.addEventListener('click', function() { const team = JSON.parse(this.getAttribute('data-team')); eraInput.value = team.era; baInput.value = team.ba; hrInput.value = team.hr; errorsInput.value = team.errors; if (net.trainOpts) { predictLossProbability(); } else { predictionText.textContent = "Please train the network first"; predictionResult.classList.remove('hidden'); predictionResult.className = "mt-4 p-4 rounded-lg bg-yellow-50"; } }); }); } }); </script> </body> </html>