MarcRyan commited on
Commit
f00e65a
·
verified ·
1 Parent(s): 5fc2e3a

Add 2 files

Browse files
Files changed (2) hide show
  1. index.html +383 -56
  2. prompts.txt +1 -0
index.html CHANGED
@@ -55,17 +55,38 @@
55
  transform: rotate(-90deg);
56
  transform-origin: 50% 50%;
57
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  </style>
59
  </head>
60
  <body class="bg-gray-50 min-h-screen">
61
  <div class="container mx-auto px-4 py-8">
62
  <header class="mb-12 text-center">
63
  <h1 class="text-4xl font-bold text-green-600 mb-2">
64
- <i class="fas fa-futbol mr-3"></i>Soccer Prediction Engine
65
  </h1>
66
  <p class="text-gray-600 max-w-3xl mx-auto">
67
- Neural network-powered analysis to predict likely losing teams based on soccer performance metrics.
68
- Adjust parameters and see how the network learns from football statistics.
69
  </p>
70
  </header>
71
 
@@ -91,14 +112,13 @@
91
 
92
  <div>
93
  <label class="block text-sm font-medium text-gray-700 mb-1">Neurons per Layer</label>
94
- <input type="range" id="neuronsPerLayer" min="2" max="12" value="6" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer">
95
  <div class="flex justify-between text-xs text-gray-500 mt-1">
96
  <span>2</span>
97
- <span>4</span>
98
  <span>6</span>
99
- <span>8</span>
100
- <span>10</span>
101
  <span>12</span>
 
 
102
  </div>
103
  </div>
104
 
@@ -180,22 +200,85 @@
180
  <i class="fas fa-chart-line mr-2 text-green-500"></i>Team Performance Input
181
  </h3>
182
  <div class="grid grid-cols-2 gap-2">
 
 
 
 
 
 
 
 
 
 
 
 
 
183
  <div>
184
- <label class="block text-xs font-medium text-gray-500 mb-1">Goals Conceded</label>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
  <input type="number" id="goalsConcededInput" min="20" max="80" step="1" value="40" class="w-full px-2 py-1 border rounded text-sm">
186
  </div>
187
  <div>
188
- <label class="block text-xs font-medium text-gray-500 mb-1">Shots on Target</label>
189
- <input type="number" id="shotsOnTargetInput" min="100" max="300" step="1" value="180" class="w-full px-2 py-1 border rounded text-sm">
 
 
190
  </div>
191
  <div>
192
- <label class="block text-xs font-medium text-gray-500 mb-1">Pass Accuracy %</label>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
193
  <input type="number" id="passAccuracyInput" min="70" max="90" step="0.1" value="80" class="w-full px-2 py-1 border rounded text-sm">
194
  </div>
195
  <div>
196
- <label class="block text-xs font-medium text-gray-500 mb-1">Yellow Cards</label>
 
 
 
 
 
 
 
 
 
 
197
  <input type="number" id="yellowCardsInput" min="30" max="100" step="1" value="60" class="w-full px-2 py-1 border rounded text-sm">
198
  </div>
 
 
 
 
 
 
199
  </div>
200
  </div>
201
 
@@ -265,21 +348,52 @@
265
  <i class="fas fa-info-circle mr-2 text-green-500"></i>Key Soccer Metrics
266
  </h2>
267
  <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
 
268
  <div class="bg-blue-50 p-4 rounded-lg">
269
- <h3 class="font-medium text-blue-800 mb-1">Goals Conceded</h3>
270
- <p class="text-sm text-blue-600">Total goals allowed per season. Higher = worse defensive performance.</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
271
  </div>
 
 
272
  <div class="bg-green-50 p-4 rounded-lg">
273
- <h3 class="font-medium text-green-800 mb-1">Shots on Target</h3>
274
- <p class="text-sm text-green-600">Shots that reach the goal. Higher = better offensive performance.</p>
 
 
 
 
 
275
  </div>
 
 
276
  <div class="bg-yellow-50 p-4 rounded-lg">
277
- <h3 class="font-medium text-yellow-800 mb-1">Pass Accuracy %</h3>
278
- <p class="text-sm text-yellow-600">Percentage of successful passes. Higher = better team coordination.</p>
279
- </div>
280
- <div class="bg-red-50 p-4 rounded-lg">
281
- <h3 class="font-medium text-red-800 mb-1">Yellow Cards</h3>
282
- <p class="text-sm text-red-600">Disciplinary issues. Higher = more defensive problems and suspensions.</p>
 
283
  </div>
284
  </div>
285
  </div>
@@ -290,7 +404,7 @@
290
  // Configuration
291
  const config = {
292
  hiddenLayers: 3,
293
- neuronsPerLayer: 6,
294
  learningRate: 0.2,
295
  iterations: 20000,
296
  errorThresh: 0.005
@@ -298,14 +412,134 @@
298
 
299
  // Sample soccer team data (in a real app, this would come from an API)
300
  const soccerTeams = [
301
- { name: "Manchester City", logo: "⚽", goalsConceded: 32, shotsOnTarget: 280, passAccuracy: 89.2, yellowCards: 45 },
302
- { name: "Liverpool", logo: "⚽", goalsConceded: 38, shotsOnTarget: 265, passAccuracy: 85.7, yellowCards: 52 },
303
- { name: "Chelsea", logo: "⚽", goalsConceded: 45, shotsOnTarget: 240, passAccuracy: 84.1, yellowCards: 58 },
304
- { name: "Tottenham", logo: "⚽", goalsConceded: 48, shotsOnTarget: 225, passAccuracy: 82.3, yellowCards: 62 },
305
- { name: "Arsenal", logo: "⚽", goalsConceded: 42, shotsOnTarget: 235, passAccuracy: 83.5, yellowCards: 55 },
306
- { name: "Manchester Utd", logo: "⚽", goalsConceded: 51, shotsOnTarget: 210, passAccuracy: 81.8, yellowCards: 68 },
307
- { name: "Leicester", logo: "⚽", goalsConceded: 54, shotsOnTarget: 195, passAccuracy: 79.6, yellowCards: 72 },
308
- { name: "West Ham", logo: "⚽", goalsConceded: 58, shotsOnTarget: 185, passAccuracy: 78.2, yellowCards: 78 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
309
  ];
310
 
311
  // DOM Elements
@@ -315,10 +549,21 @@
315
  const learningRateInput = document.getElementById('learningRate');
316
  const trainBtn = document.getElementById('trainBtn');
317
  const resetBtn = document.getElementById('resetBtn');
 
 
318
  const goalsConcededInput = document.getElementById('goalsConcededInput');
319
  const shotsOnTargetInput = document.getElementById('shotsOnTargetInput');
 
 
 
320
  const passAccuracyInput = document.getElementById('passAccuracyInput');
 
 
 
 
321
  const yellowCardsInput = document.getElementById('yellowCardsInput');
 
 
322
  const lossPercentage = document.getElementById('lossPercentage');
323
  const confidenceBar = document.getElementById('confidenceBar');
324
  const predictionText = document.getElementById('predictionText');
@@ -346,7 +591,12 @@
346
  resetBtn.addEventListener('click', resetNetwork);
347
 
348
  // Add input event listeners for all stat inputs
349
- [goalsConcededInput, shotsOnTargetInput, passAccuracyInput, yellowCardsInput].forEach(input => {
 
 
 
 
 
350
  input.addEventListener('input', () => {
351
  // Only predict if network is trained
352
  if (net.trainOpts) {
@@ -429,35 +679,67 @@
429
  // Random stats within realistic ranges
430
  const goalsConceded = Math.floor(randomInRange(20, 80));
431
  const shotsOnTarget = Math.floor(randomInRange(100, 300));
 
 
 
432
  const passAccuracy = randomInRange(70, 90);
 
 
 
 
433
  const yellowCards = Math.floor(randomInRange(30, 100));
 
434
 
435
  // Calculate loss probability based on stats
436
  let lossProbability;
437
 
438
  if (weight === 'offense') {
439
- // More weight on offensive stats (shots on target and pass accuracy)
440
  lossProbability = (
441
- (0.2 * normalize(goalsConceded, 20, 80)) +
442
- (0.4 * (1 - normalize(shotsOnTarget, 100, 300))) +
443
- (0.3 * (1 - normalize(passAccuracy, 70, 90))) +
444
- (0.1 * normalize(yellowCards, 30, 100))
 
 
 
 
 
 
 
 
445
  );
446
  } else if (weight === 'defense') {
447
- // More weight on defensive stats (goals conceded and yellow cards)
448
  lossProbability = (
449
- (0.5 * normalize(goalsConceded, 20, 80)) +
450
- (0.1 * (1 - normalize(shotsOnTarget, 100, 300))) +
451
- (0.2 * (1 - normalize(passAccuracy, 70, 90))) +
452
- (0.2 * normalize(yellowCards, 30, 100))
 
 
 
 
 
 
 
 
453
  );
454
  } else {
455
  // Balanced approach
456
  lossProbability = (
457
- (0.35 * normalize(goalsConceded, 20, 80)) +
458
- (0.3 * (1 - normalize(shotsOnTarget, 100, 300))) +
459
- (0.2 * (1 - normalize(passAccuracy, 70, 90))) +
460
- (0.15 * normalize(yellowCards, 30, 100))
 
 
 
 
 
 
 
 
461
  );
462
  }
463
 
@@ -473,8 +755,16 @@
473
  input: [
474
  normalize(goalsConceded, 20, 80),
475
  normalize(shotsOnTarget, 100, 300),
 
 
 
476
  normalize(passAccuracy, 70, 90),
477
- normalize(yellowCards, 30, 100)
 
 
 
 
 
478
  ],
479
  output: [outcome]
480
  });
@@ -484,16 +774,33 @@
484
  }
485
 
486
  function predictLossProbability() {
 
487
  const goalsConceded = parseFloat(goalsConcededInput.value);
488
  const shotsOnTarget = parseFloat(shotsOnTargetInput.value);
 
 
 
489
  const passAccuracy = parseFloat(passAccuracyInput.value);
 
 
 
 
490
  const yellowCards = parseFloat(yellowCardsInput.value);
 
491
 
492
  const input = [
493
  normalize(goalsConceded, 20, 80),
494
  normalize(shotsOnTarget, 100, 300),
 
 
 
495
  normalize(passAccuracy, 70, 90),
496
- normalize(yellowCards, 30, 100)
 
 
 
 
 
497
  ];
498
 
499
  const output = net.run(input);
@@ -535,10 +842,12 @@
535
  <div class="text-2xl mr-3">${team.logo}</div>
536
  <h3 class="font-semibold text-gray-800">${team.name}</h3>
537
  </div>
538
- <div class="grid grid-cols-2 gap-2 text-sm mb-3">
539
  <div><span class="text-gray-500">Conceded:</span> ${team.goalsConceded}</div>
540
  <div><span class="text-gray-500">Shots:</span> ${team.shotsOnTarget}</div>
 
541
  <div><span class="text-gray-500">Pass %:</span> ${team.passAccuracy.toFixed(1)}</div>
 
542
  <div><span class="text-gray-500">Yellows:</span> ${team.yellowCards}</div>
543
  </div>
544
  <div class="flex items-center">
@@ -577,10 +886,20 @@
577
  document.querySelectorAll('.predict-btn').forEach(btn => {
578
  btn.addEventListener('click', function() {
579
  const team = JSON.parse(this.getAttribute('data-team'));
 
 
580
  goalsConcededInput.value = team.goalsConceded;
581
  shotsOnTargetInput.value = team.shotsOnTarget;
 
 
 
582
  passAccuracyInput.value = team.passAccuracy;
 
 
 
 
583
  yellowCardsInput.value = team.yellowCards;
 
584
 
585
  if (net.trainOpts) {
586
  predictLossProbability();
@@ -596,8 +915,16 @@
596
  const input = [
597
  normalize(team.goalsConceded, 20, 80),
598
  normalize(team.shotsOnTarget, 100, 300),
 
 
 
599
  normalize(team.passAccuracy, 70, 90),
600
- normalize(team.yellowCards, 30, 100)
 
 
 
 
 
601
  ];
602
 
603
  const output = net.run(input);
@@ -646,7 +973,7 @@
646
 
647
  // Calculate layer positions
648
  const layers = [
649
- { neurons: 4, label: 'Input', stats: ['Conceded', 'Shots', 'Pass %', 'Cards'] },
650
  ...Array(config.hiddenLayers).fill().map((_, i) => ({
651
  neurons: config.neuronsPerLayer,
652
  label: `Hidden ${i + 1}`
@@ -695,7 +1022,7 @@
695
  const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
696
  circle.setAttribute('cx', x);
697
  circle.setAttribute('cy', y);
698
- circle.setAttribute('r', 18);
699
 
700
  // Color input/output layers differently
701
  if (l === 0) {
@@ -712,17 +1039,17 @@
712
  // Create neuron text
713
  const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
714
  text.setAttribute('x', x);
715
- text.setAttribute('y', y + 5);
716
  text.setAttribute('text-anchor', 'middle');
717
  text.setAttribute('fill', 'white');
718
- text.setAttribute('font-size', '10');
719
  text.setAttribute('font-weight', 'bold');
720
 
721
  // Show stat names for input layer
722
  if (l === 0 && layer.stats) {
723
- text.textContent = layer.stats[n].substring(0, 3);
724
  } else if (l === layerCount - 1 && layer.stats) {
725
- text.textContent = layer.stats[n].substring(0, 3);
726
  } else {
727
  text.textContent = `${layer.label[0]}${n + 1}`;
728
  }
 
55
  transform: rotate(-90deg);
56
  transform-origin: 50% 50%;
57
  }
58
+ .stat-badge {
59
+ font-size: 0.7rem;
60
+ padding: 0.2rem 0.4rem;
61
+ border-radius: 0.25rem;
62
+ }
63
+ .offensive-stat {
64
+ background-color: #3B82F6;
65
+ color: white;
66
+ }
67
+ .defensive-stat {
68
+ background-color: #EF4444;
69
+ color: white;
70
+ }
71
+ .teamwork-stat {
72
+ background-color: #10B981;
73
+ color: white;
74
+ }
75
+ .discipline-stat {
76
+ background-color: #F59E0B;
77
+ color: white;
78
+ }
79
  </style>
80
  </head>
81
  <body class="bg-gray-50 min-h-screen">
82
  <div class="container mx-auto px-4 py-8">
83
  <header class="mb-12 text-center">
84
  <h1 class="text-4xl font-bold text-green-600 mb-2">
85
+ <i class="fas fa-futbol mr-3"></i>Advanced Soccer Prediction Engine
86
  </h1>
87
  <p class="text-gray-600 max-w-3xl mx-auto">
88
+ Comprehensive neural network analysis using 12 key performance metrics to predict match outcomes.
89
+ The system learns from extensive soccer statistics to provide accurate loss probability predictions.
90
  </p>
91
  </header>
92
 
 
112
 
113
  <div>
114
  <label class="block text-sm font-medium text-gray-700 mb-1">Neurons per Layer</label>
115
+ <input type="range" id="neuronsPerLayer" min="2" max="20" value="12" 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 mt-1">
117
  <span>2</span>
 
118
  <span>6</span>
 
 
119
  <span>12</span>
120
+ <span>16</span>
121
+ <span>20</span>
122
  </div>
123
  </div>
124
 
 
200
  <i class="fas fa-chart-line mr-2 text-green-500"></i>Team Performance Input
201
  </h3>
202
  <div class="grid grid-cols-2 gap-2">
203
+ <!-- Offensive Stats -->
204
+ <div>
205
+ <label class="block text-xs font-medium text-gray-500 mb-1 flex items-center">
206
+ <span class="stat-badge offensive-stat mr-1">OFF</span> Shots on Target
207
+ </label>
208
+ <input type="number" id="shotsOnTargetInput" min="100" max="300" step="1" value="180" class="w-full px-2 py-1 border rounded text-sm">
209
+ </div>
210
+ <div>
211
+ <label class="block text-xs font-medium text-gray-500 mb-1 flex items-center">
212
+ <span class="stat-badge offensive-stat mr-1">OFF</span> Goals Scored
213
+ </label>
214
+ <input type="number" id="goalsScoredInput" min="30" max="100" step="1" value="65" class="w-full px-2 py-1 border rounded text-sm">
215
+ </div>
216
  <div>
217
+ <label class="block text-xs font-medium text-gray-500 mb-1 flex items-center">
218
+ <span class="stat-badge offensive-stat mr-1">OFF</span> Key Passes
219
+ </label>
220
+ <input type="number" id="keyPassesInput" min="200" max="600" step="1" value="400" class="w-full px-2 py-1 border rounded text-sm">
221
+ </div>
222
+ <div>
223
+ <label class="block text-xs font-medium text-gray-500 mb-1 flex items-center">
224
+ <span class="stat-badge offensive-stat mr-1">OFF</span> Dribbles
225
+ </label>
226
+ <input type="number" id="dribblesInput" min="100" max="500" step="1" value="300" class="w-full px-2 py-1 border rounded text-sm">
227
+ </div>
228
+
229
+ <!-- Defensive Stats -->
230
+ <div>
231
+ <label class="block text-xs font-medium text-gray-500 mb-1 flex items-center">
232
+ <span class="stat-badge defensive-stat mr-1">DEF</span> Goals Conceded
233
+ </label>
234
  <input type="number" id="goalsConcededInput" min="20" max="80" step="1" value="40" class="w-full px-2 py-1 border rounded text-sm">
235
  </div>
236
  <div>
237
+ <label class="block text-xs font-medium text-gray-500 mb-1 flex items-center">
238
+ <span class="stat-badge defensive-stat mr-1">DEF</span> Tackles
239
+ </label>
240
+ <input type="number" id="tacklesInput" min="300" max="800" step="1" value="500" class="w-full px-2 py-1 border rounded text-sm">
241
  </div>
242
  <div>
243
+ <label class="block text-xs font-medium text-gray-500 mb-1 flex items-center">
244
+ <span class="stat-badge defensive-stat mr-1">DEF</span> Interceptions
245
+ </label>
246
+ <input type="number" id="interceptionsInput" min="200" max="600" step="1" value="400" class="w-full px-2 py-1 border rounded text-sm">
247
+ </div>
248
+ <div>
249
+ <label class="block text-xs font-medium text-gray-500 mb-1 flex items-center">
250
+ <span class="stat-badge defensive-stat mr-1">DEF</span> Clearances
251
+ </label>
252
+ <input type="number" id="clearancesInput" min="300" max="900" step="1" value="600" class="w-full px-2 py-1 border rounded text-sm">
253
+ </div>
254
+
255
+ <!-- Teamwork Stats -->
256
+ <div>
257
+ <label class="block text-xs font-medium text-gray-500 mb-1 flex items-center">
258
+ <span class="stat-badge teamwork-stat mr-1">TMW</span> Pass Accuracy %
259
+ </label>
260
  <input type="number" id="passAccuracyInput" min="70" max="90" step="0.1" value="80" class="w-full px-2 py-1 border rounded text-sm">
261
  </div>
262
  <div>
263
+ <label class="block text-xs font-medium text-gray-500 mb-1 flex items-center">
264
+ <span class="stat-badge teamwork-stat mr-1">TMW</span> Cross Accuracy %
265
+ </label>
266
+ <input type="number" id="crossAccuracyInput" min="20" max="50" step="0.1" value="35" class="w-full px-2 py-1 border rounded text-sm">
267
+ </div>
268
+
269
+ <!-- Discipline Stats -->
270
+ <div>
271
+ <label class="block text-xs font-medium text-gray-500 mb-1 flex items-center">
272
+ <span class="stat-badge discipline-stat mr-1">DSC</span> Yellow Cards
273
+ </label>
274
  <input type="number" id="yellowCardsInput" min="30" max="100" step="1" value="60" class="w-full px-2 py-1 border rounded text-sm">
275
  </div>
276
+ <div>
277
+ <label class="block text-xs font-medium text-gray-500 mb-1 flex items-center">
278
+ <span class="stat-badge discipline-stat mr-1">DSC</span> Red Cards
279
+ </label>
280
+ <input type="number" id="redCardsInput" min="0" max="10" step="1" value="3" class="w-full px-2 py-1 border rounded text-sm">
281
+ </div>
282
  </div>
283
  </div>
284
 
 
348
  <i class="fas fa-info-circle mr-2 text-green-500"></i>Key Soccer Metrics
349
  </h2>
350
  <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
351
+ <!-- Offensive Stats -->
352
  <div class="bg-blue-50 p-4 rounded-lg">
353
+ <h3 class="font-medium text-blue-800 mb-1 flex items-center">
354
+ <span class="stat-badge offensive-stat mr-2">OFF</span> Offensive Metrics
355
+ </h3>
356
+ <ul class="text-sm text-blue-600 space-y-1">
357
+ <li><strong>Shots on Target:</strong> Direct attempts on goal</li>
358
+ <li><strong>Goals Scored:</strong> Total goals per season</li>
359
+ <li><strong>Key Passes:</strong> Passes leading to shots</li>
360
+ <li><strong>Dribbles:</strong> Successful player runs</li>
361
+ </ul>
362
+ </div>
363
+
364
+ <!-- Defensive Stats -->
365
+ <div class="bg-red-50 p-4 rounded-lg">
366
+ <h3 class="font-medium text-red-800 mb-1 flex items-center">
367
+ <span class="stat-badge defensive-stat mr-2">DEF</span> Defensive Metrics
368
+ </h3>
369
+ <ul class="text-sm text-red-600 space-y-1">
370
+ <li><strong>Goals Conceded:</strong> Goals allowed</li>
371
+ <li><strong>Tackles:</strong> Successful defensive challenges</li>
372
+ <li><strong>Interceptions:</strong> Passes intercepted</li>
373
+ <li><strong>Clearances:</strong> Defensive removals</li>
374
+ </ul>
375
  </div>
376
+
377
+ <!-- Teamwork Stats -->
378
  <div class="bg-green-50 p-4 rounded-lg">
379
+ <h3 class="font-medium text-green-800 mb-1 flex items-center">
380
+ <span class="stat-badge teamwork-stat mr-2">TMW</span> Teamwork Metrics
381
+ </h3>
382
+ <ul class="text-sm text-green-600 space-y-1">
383
+ <li><strong>Pass Accuracy:</strong> Successful pass percentage</li>
384
+ <li><strong>Cross Accuracy:</strong> Successful crosses</li>
385
+ </ul>
386
  </div>
387
+
388
+ <!-- Discipline Stats -->
389
  <div class="bg-yellow-50 p-4 rounded-lg">
390
+ <h3 class="font-medium text-yellow-800 mb-1 flex items-center">
391
+ <span class="stat-badge discipline-stat mr-2">DSC</span> Discipline Metrics
392
+ </h3>
393
+ <ul class="text-sm text-yellow-600 space-y-1">
394
+ <li><strong>Yellow Cards:</strong> Cautions received</li>
395
+ <li><strong>Red Cards:</strong> Ejections received</li>
396
+ </ul>
397
  </div>
398
  </div>
399
  </div>
 
404
  // Configuration
405
  const config = {
406
  hiddenLayers: 3,
407
+ neuronsPerLayer: 12,
408
  learningRate: 0.2,
409
  iterations: 20000,
410
  errorThresh: 0.005
 
412
 
413
  // Sample soccer team data (in a real app, this would come from an API)
414
  const soccerTeams = [
415
+ {
416
+ name: "Manchester City",
417
+ logo: "⚽",
418
+ goalsConceded: 32,
419
+ shotsOnTarget: 280,
420
+ goalsScored: 85,
421
+ keyPasses: 450,
422
+ dribbles: 350,
423
+ passAccuracy: 89.2,
424
+ crossAccuracy: 38.5,
425
+ tackles: 520,
426
+ interceptions: 480,
427
+ clearances: 580,
428
+ yellowCards: 45,
429
+ redCards: 1
430
+ },
431
+ {
432
+ name: "Liverpool",
433
+ logo: "⚽",
434
+ goalsConceded: 38,
435
+ shotsOnTarget: 265,
436
+ goalsScored: 78,
437
+ keyPasses: 420,
438
+ dribbles: 320,
439
+ passAccuracy: 85.7,
440
+ crossAccuracy: 36.2,
441
+ tackles: 550,
442
+ interceptions: 460,
443
+ clearances: 620,
444
+ yellowCards: 52,
445
+ redCards: 2
446
+ },
447
+ {
448
+ name: "Chelsea",
449
+ logo: "⚽",
450
+ goalsConceded: 45,
451
+ shotsOnTarget: 240,
452
+ goalsScored: 70,
453
+ keyPasses: 400,
454
+ dribbles: 290,
455
+ passAccuracy: 84.1,
456
+ crossAccuracy: 34.8,
457
+ tackles: 580,
458
+ interceptions: 440,
459
+ clearances: 650,
460
+ yellowCards: 58,
461
+ redCards: 3
462
+ },
463
+ {
464
+ name: "Tottenham",
465
+ logo: "⚽",
466
+ goalsConceded: 48,
467
+ shotsOnTarget: 225,
468
+ goalsScored: 68,
469
+ keyPasses: 380,
470
+ dribbles: 270,
471
+ passAccuracy: 82.3,
472
+ crossAccuracy: 33.5,
473
+ tackles: 600,
474
+ interceptions: 420,
475
+ clearances: 680,
476
+ yellowCards: 62,
477
+ redCards: 4
478
+ },
479
+ {
480
+ name: "Arsenal",
481
+ logo: "⚽",
482
+ goalsConceded: 42,
483
+ shotsOnTarget: 235,
484
+ goalsScored: 72,
485
+ keyPasses: 390,
486
+ dribbles: 280,
487
+ passAccuracy: 83.5,
488
+ crossAccuracy: 35.1,
489
+ tackles: 570,
490
+ interceptions: 430,
491
+ clearances: 630,
492
+ yellowCards: 55,
493
+ redCards: 2
494
+ },
495
+ {
496
+ name: "Manchester Utd",
497
+ logo: "⚽",
498
+ goalsConceded: 51,
499
+ shotsOnTarget: 210,
500
+ goalsScored: 65,
501
+ keyPasses: 370,
502
+ dribbles: 260,
503
+ passAccuracy: 81.8,
504
+ crossAccuracy: 32.7,
505
+ tackles: 620,
506
+ interceptions: 410,
507
+ clearances: 700,
508
+ yellowCards: 68,
509
+ redCards: 5
510
+ },
511
+ {
512
+ name: "Leicester",
513
+ logo: "⚽",
514
+ goalsConceded: 54,
515
+ shotsOnTarget: 195,
516
+ goalsScored: 60,
517
+ keyPasses: 350,
518
+ dribbles: 240,
519
+ passAccuracy: 79.6,
520
+ crossAccuracy: 31.2,
521
+ tackles: 640,
522
+ interceptions: 400,
523
+ clearances: 720,
524
+ yellowCards: 72,
525
+ redCards: 6
526
+ },
527
+ {
528
+ name: "West Ham",
529
+ logo: "⚽",
530
+ goalsConceded: 58,
531
+ shotsOnTarget: 185,
532
+ goalsScored: 58,
533
+ keyPasses: 340,
534
+ dribbles: 230,
535
+ passAccuracy: 78.2,
536
+ crossAccuracy: 30.5,
537
+ tackles: 660,
538
+ interceptions: 390,
539
+ clearances: 750,
540
+ yellowCards: 78,
541
+ redCards: 7
542
+ }
543
  ];
544
 
545
  // DOM Elements
 
549
  const learningRateInput = document.getElementById('learningRate');
550
  const trainBtn = document.getElementById('trainBtn');
551
  const resetBtn = document.getElementById('resetBtn');
552
+
553
+ // Input elements for all 12 stats
554
  const goalsConcededInput = document.getElementById('goalsConcededInput');
555
  const shotsOnTargetInput = document.getElementById('shotsOnTargetInput');
556
+ const goalsScoredInput = document.getElementById('goalsScoredInput');
557
+ const keyPassesInput = document.getElementById('keyPassesInput');
558
+ const dribblesInput = document.getElementById('dribblesInput');
559
  const passAccuracyInput = document.getElementById('passAccuracyInput');
560
+ const crossAccuracyInput = document.getElementById('crossAccuracyInput');
561
+ const tacklesInput = document.getElementById('tacklesInput');
562
+ const interceptionsInput = document.getElementById('interceptionsInput');
563
+ const clearancesInput = document.getElementById('clearancesInput');
564
  const yellowCardsInput = document.getElementById('yellowCardsInput');
565
+ const redCardsInput = document.getElementById('redCardsInput');
566
+
567
  const lossPercentage = document.getElementById('lossPercentage');
568
  const confidenceBar = document.getElementById('confidenceBar');
569
  const predictionText = document.getElementById('predictionText');
 
591
  resetBtn.addEventListener('click', resetNetwork);
592
 
593
  // Add input event listeners for all stat inputs
594
+ [
595
+ goalsConcededInput, shotsOnTargetInput, goalsScoredInput,
596
+ keyPassesInput, dribblesInput, passAccuracyInput,
597
+ crossAccuracyInput, tacklesInput, interceptionsInput,
598
+ clearancesInput, yellowCardsInput, redCardsInput
599
+ ].forEach(input => {
600
  input.addEventListener('input', () => {
601
  // Only predict if network is trained
602
  if (net.trainOpts) {
 
679
  // Random stats within realistic ranges
680
  const goalsConceded = Math.floor(randomInRange(20, 80));
681
  const shotsOnTarget = Math.floor(randomInRange(100, 300));
682
+ const goalsScored = Math.floor(randomInRange(30, 100));
683
+ const keyPasses = Math.floor(randomInRange(200, 600));
684
+ const dribbles = Math.floor(randomInRange(100, 500));
685
  const passAccuracy = randomInRange(70, 90);
686
+ const crossAccuracy = randomInRange(20, 50);
687
+ const tackles = Math.floor(randomInRange(300, 800));
688
+ const interceptions = Math.floor(randomInRange(200, 600));
689
+ const clearances = Math.floor(randomInRange(300, 900));
690
  const yellowCards = Math.floor(randomInRange(30, 100));
691
+ const redCards = Math.floor(randomInRange(0, 10));
692
 
693
  // Calculate loss probability based on stats
694
  let lossProbability;
695
 
696
  if (weight === 'offense') {
697
+ // More weight on offensive stats
698
  lossProbability = (
699
+ (0.1 * normalize(goalsConceded, 20, 80)) +
700
+ (0.2 * (1 - normalize(shotsOnTarget, 100, 300))) +
701
+ (0.2 * (1 - normalize(goalsScored, 30, 100))) +
702
+ (0.15 * (1 - normalize(keyPasses, 200, 600))) +
703
+ (0.15 * (1 - normalize(dribbles, 100, 500))) +
704
+ (0.1 * (1 - normalize(passAccuracy, 70, 90))) +
705
+ (0.05 * (1 - normalize(crossAccuracy, 20, 50))) +
706
+ (0.025 * normalize(tackles, 300, 800)) +
707
+ (0.025 * normalize(interceptions, 200, 600)) +
708
+ (0.025 * normalize(clearances, 300, 900)) +
709
+ (0.025 * normalize(yellowCards, 30, 100)) +
710
+ (0.025 * normalize(redCards, 0, 10))
711
  );
712
  } else if (weight === 'defense') {
713
+ // More weight on defensive stats
714
  lossProbability = (
715
+ (0.3 * normalize(goalsConceded, 20, 80)) +
716
+ (0.05 * (1 - normalize(shotsOnTarget, 100, 300))) +
717
+ (0.05 * (1 - normalize(goalsScored, 30, 100))) +
718
+ (0.05 * (1 - normalize(keyPasses, 200, 600))) +
719
+ (0.05 * (1 - normalize(dribbles, 100, 500))) +
720
+ (0.1 * (1 - normalize(passAccuracy, 70, 90))) +
721
+ (0.05 * (1 - normalize(crossAccuracy, 20, 50))) +
722
+ (0.1 * normalize(tackles, 300, 800)) +
723
+ (0.1 * normalize(interceptions, 200, 600)) +
724
+ (0.1 * normalize(clearances, 300, 900)) +
725
+ (0.05 * normalize(yellowCards, 30, 100)) +
726
+ (0.05 * normalize(redCards, 0, 10))
727
  );
728
  } else {
729
  // Balanced approach
730
  lossProbability = (
731
+ (0.15 * normalize(goalsConceded, 20, 80)) +
732
+ (0.1 * (1 - normalize(shotsOnTarget, 100, 300))) +
733
+ (0.1 * (1 - normalize(goalsScored, 30, 100))) +
734
+ (0.1 * (1 - normalize(keyPasses, 200, 600))) +
735
+ (0.1 * (1 - normalize(dribbles, 100, 500))) +
736
+ (0.1 * (1 - normalize(passAccuracy, 70, 90))) +
737
+ (0.05 * (1 - normalize(crossAccuracy, 20, 50))) +
738
+ (0.1 * normalize(tackles, 300, 800)) +
739
+ (0.1 * normalize(interceptions, 200, 600)) +
740
+ (0.05 * normalize(clearances, 300, 900)) +
741
+ (0.025 * normalize(yellowCards, 30, 100)) +
742
+ (0.025 * normalize(redCards, 0, 10))
743
  );
744
  }
745
 
 
755
  input: [
756
  normalize(goalsConceded, 20, 80),
757
  normalize(shotsOnTarget, 100, 300),
758
+ normalize(goalsScored, 30, 100),
759
+ normalize(keyPasses, 200, 600),
760
+ normalize(dribbles, 100, 500),
761
  normalize(passAccuracy, 70, 90),
762
+ normalize(crossAccuracy, 20, 50),
763
+ normalize(tackles, 300, 800),
764
+ normalize(interceptions, 200, 600),
765
+ normalize(clearances, 300, 900),
766
+ normalize(yellowCards, 30, 100),
767
+ normalize(redCards, 0, 10)
768
  ],
769
  output: [outcome]
770
  });
 
774
  }
775
 
776
  function predictLossProbability() {
777
+ // Get all 12 input values
778
  const goalsConceded = parseFloat(goalsConcededInput.value);
779
  const shotsOnTarget = parseFloat(shotsOnTargetInput.value);
780
+ const goalsScored = parseFloat(goalsScoredInput.value);
781
+ const keyPasses = parseFloat(keyPassesInput.value);
782
+ const dribbles = parseFloat(dribblesInput.value);
783
  const passAccuracy = parseFloat(passAccuracyInput.value);
784
+ const crossAccuracy = parseFloat(crossAccuracyInput.value);
785
+ const tackles = parseFloat(tacklesInput.value);
786
+ const interceptions = parseFloat(interceptionsInput.value);
787
+ const clearances = parseFloat(clearancesInput.value);
788
  const yellowCards = parseFloat(yellowCardsInput.value);
789
+ const redCards = parseFloat(redCardsInput.value);
790
 
791
  const input = [
792
  normalize(goalsConceded, 20, 80),
793
  normalize(shotsOnTarget, 100, 300),
794
+ normalize(goalsScored, 30, 100),
795
+ normalize(keyPasses, 200, 600),
796
+ normalize(dribbles, 100, 500),
797
  normalize(passAccuracy, 70, 90),
798
+ normalize(crossAccuracy, 20, 50),
799
+ normalize(tackles, 300, 800),
800
+ normalize(interceptions, 200, 600),
801
+ normalize(clearances, 300, 900),
802
+ normalize(yellowCards, 30, 100),
803
+ normalize(redCards, 0, 10)
804
  ];
805
 
806
  const output = net.run(input);
 
842
  <div class="text-2xl mr-3">${team.logo}</div>
843
  <h3 class="font-semibold text-gray-800">${team.name}</h3>
844
  </div>
845
+ <div class="grid grid-cols-2 gap-2 text-xs mb-3">
846
  <div><span class="text-gray-500">Conceded:</span> ${team.goalsConceded}</div>
847
  <div><span class="text-gray-500">Shots:</span> ${team.shotsOnTarget}</div>
848
+ <div><span class="text-gray-500">Goals:</span> ${team.goalsScored}</div>
849
  <div><span class="text-gray-500">Pass %:</span> ${team.passAccuracy.toFixed(1)}</div>
850
+ <div><span class="text-gray-500">Tackles:</span> ${team.tackles}</div>
851
  <div><span class="text-gray-500">Yellows:</span> ${team.yellowCards}</div>
852
  </div>
853
  <div class="flex items-center">
 
886
  document.querySelectorAll('.predict-btn').forEach(btn => {
887
  btn.addEventListener('click', function() {
888
  const team = JSON.parse(this.getAttribute('data-team'));
889
+
890
+ // Set all 12 input values
891
  goalsConcededInput.value = team.goalsConceded;
892
  shotsOnTargetInput.value = team.shotsOnTarget;
893
+ goalsScoredInput.value = team.goalsScored;
894
+ keyPassesInput.value = team.keyPasses;
895
+ dribblesInput.value = team.dribbles;
896
  passAccuracyInput.value = team.passAccuracy;
897
+ crossAccuracyInput.value = team.crossAccuracy;
898
+ tacklesInput.value = team.tackles;
899
+ interceptionsInput.value = team.interceptions;
900
+ clearancesInput.value = team.clearances;
901
  yellowCardsInput.value = team.yellowCards;
902
+ redCardsInput.value = team.redCards;
903
 
904
  if (net.trainOpts) {
905
  predictLossProbability();
 
915
  const input = [
916
  normalize(team.goalsConceded, 20, 80),
917
  normalize(team.shotsOnTarget, 100, 300),
918
+ normalize(team.goalsScored, 30, 100),
919
+ normalize(team.keyPasses, 200, 600),
920
+ normalize(team.dribbles, 100, 500),
921
  normalize(team.passAccuracy, 70, 90),
922
+ normalize(team.crossAccuracy, 20, 50),
923
+ normalize(team.tackles, 300, 800),
924
+ normalize(team.interceptions, 200, 600),
925
+ normalize(team.clearances, 300, 900),
926
+ normalize(team.yellowCards, 30, 100),
927
+ normalize(team.redCards, 0, 10)
928
  ];
929
 
930
  const output = net.run(input);
 
973
 
974
  // Calculate layer positions
975
  const layers = [
976
+ { neurons: 12, label: 'Input', stats: ['Conceded', 'Shots', 'Goals', 'KeyP', 'Drib', 'Pass%', 'Cross%', 'Tack', 'Int', 'Clear', 'Yel', 'Red'] },
977
  ...Array(config.hiddenLayers).fill().map((_, i) => ({
978
  neurons: config.neuronsPerLayer,
979
  label: `Hidden ${i + 1}`
 
1022
  const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
1023
  circle.setAttribute('cx', x);
1024
  circle.setAttribute('cy', y);
1025
+ circle.setAttribute('r', 15);
1026
 
1027
  // Color input/output layers differently
1028
  if (l === 0) {
 
1039
  // Create neuron text
1040
  const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
1041
  text.setAttribute('x', x);
1042
+ text.setAttribute('y', y + 4);
1043
  text.setAttribute('text-anchor', 'middle');
1044
  text.setAttribute('fill', 'white');
1045
+ text.setAttribute('font-size', '8');
1046
  text.setAttribute('font-weight', 'bold');
1047
 
1048
  // Show stat names for input layer
1049
  if (l === 0 && layer.stats) {
1050
+ text.textContent = layer.stats[n];
1051
  } else if (l === layerCount - 1 && layer.stats) {
1052
+ text.textContent = layer.stats[n];
1053
  } else {
1054
  text.textContent = `${layer.label[0]}${n + 1}`;
1055
  }
prompts.txt CHANGED
@@ -0,0 +1 @@
 
 
1
+ triple the amount of inputs