Add 2 files
Browse files- index.html +383 -56
- 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 |
-
|
| 68 |
-
|
| 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="
|
| 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">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|
| 189 |
-
|
|
|
|
|
|
|
| 190 |
</div>
|
| 191 |
<div>
|
| 192 |
-
<label class="block text-xs font-medium text-gray-500 mb-1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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">
|
| 270 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 271 |
</div>
|
|
|
|
|
|
|
| 272 |
<div class="bg-green-50 p-4 rounded-lg">
|
| 273 |
-
<h3 class="font-medium text-green-800 mb-1
|
| 274 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 275 |
</div>
|
|
|
|
|
|
|
| 276 |
<div class="bg-yellow-50 p-4 rounded-lg">
|
| 277 |
-
<h3 class="font-medium text-yellow-800 mb-1
|
| 278 |
-
|
| 279 |
-
|
| 280 |
-
|
| 281 |
-
|
| 282 |
-
|
|
|
|
| 283 |
</div>
|
| 284 |
</div>
|
| 285 |
</div>
|
|
@@ -290,7 +404,7 @@
|
|
| 290 |
// Configuration
|
| 291 |
const config = {
|
| 292 |
hiddenLayers: 3,
|
| 293 |
-
neuronsPerLayer:
|
| 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 |
-
{
|
| 302 |
-
|
| 303 |
-
|
| 304 |
-
|
| 305 |
-
|
| 306 |
-
|
| 307 |
-
|
| 308 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
[
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|
| 440 |
lossProbability = (
|
| 441 |
-
(0.
|
| 442 |
-
(0.
|
| 443 |
-
(0.
|
| 444 |
-
(0.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 445 |
);
|
| 446 |
} else if (weight === 'defense') {
|
| 447 |
-
// More weight on defensive stats
|
| 448 |
lossProbability = (
|
| 449 |
-
(0.
|
| 450 |
-
(0.
|
| 451 |
-
(0.
|
| 452 |
-
(0.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 453 |
);
|
| 454 |
} else {
|
| 455 |
// Balanced approach
|
| 456 |
lossProbability = (
|
| 457 |
-
(0.
|
| 458 |
-
(0.
|
| 459 |
-
(0.
|
| 460 |
-
(0.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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-
|
| 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 601 |
];
|
| 602 |
|
| 603 |
const output = net.run(input);
|
|
@@ -646,7 +973,7 @@
|
|
| 646 |
|
| 647 |
// Calculate layer positions
|
| 648 |
const layers = [
|
| 649 |
-
{ neurons:
|
| 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',
|
| 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 +
|
| 716 |
text.setAttribute('text-anchor', 'middle');
|
| 717 |
text.setAttribute('fill', 'white');
|
| 718 |
-
text.setAttribute('font-size', '
|
| 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]
|
| 724 |
} else if (l === layerCount - 1 && layer.stats) {
|
| 725 |
-
text.textContent = layer.stats[n]
|
| 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
|