Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Greyhound Race Predictor</title> | |
<script src="https://cdn.tailwindcss.com"></script> | |
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.0.0"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-datalabels/2.2.0/chartjs-plugin-datalabels.min.js"></script> | |
<style> | |
/* Custom scrollbar */ | |
::-webkit-scrollbar { | |
width: 8px; | |
height: 8px; | |
} | |
::-webkit-scrollbar-track { | |
background: #f1f1f1; | |
border-radius: 10px; | |
} | |
::-webkit-scrollbar-thumb { | |
background: #888; | |
border-radius: 10px; | |
} | |
::-webkit-scrollbar-thumb:hover { | |
background: #555; | |
} | |
/* Custom slider */ | |
input[type="range"] { | |
-webkit-appearance: none; | |
height: 8px; | |
background: #e2e8f0; | |
border-radius: 5px; | |
background-image: linear-gradient(#3b82f6, #3b82f6); | |
background-size: 50% 100%; | |
background-repeat: no-repeat; | |
} | |
input[type="range"]::-webkit-slider-thumb { | |
-webkit-appearance: none; | |
height: 20px; | |
width: 20px; | |
border-radius: 50%; | |
background: #3b82f6; | |
cursor: pointer; | |
box-shadow: 0 0 2px 0 #555; | |
transition: background .3s ease-in-out; | |
} | |
input[type="range"]::-webkit-slider-runnable-track { | |
-webkit-appearance: none; | |
box-shadow: none; | |
border: none; | |
background: transparent; | |
} | |
/* Radar chart styling */ | |
.radar-chart-container { | |
position: relative; | |
height: 400px; | |
width: 100%; | |
} | |
/* Animation for tabs */ | |
.tab-content { | |
display: none; | |
} | |
.tab-content.active { | |
display: block; | |
animation: fadeIn 0.3s ease-in-out; | |
} | |
@keyframes fadeIn { | |
from { opacity: 0; } | |
to { opacity: 1; } | |
} | |
/* Custom tooltip */ | |
.tooltip { | |
position: relative; | |
display: inline-block; | |
} | |
.tooltip .tooltiptext { | |
visibility: hidden; | |
width: 200px; | |
background-color: #333; | |
color: #fff; | |
text-align: center; | |
border-radius: 6px; | |
padding: 5px; | |
position: absolute; | |
z-index: 1; | |
bottom: 125%; | |
left: 50%; | |
margin-left: -100px; | |
opacity: 0; | |
transition: opacity 0.3s; | |
} | |
.tooltip:hover .tooltiptext { | |
visibility: visible; | |
opacity: 1; | |
} | |
</style> | |
</head> | |
<body class="bg-gray-100 min-h-screen"> | |
<div class="container mx-auto px-4 py-8 max-w-7xl"> | |
<!-- Header --> | |
<header class="bg-blue-600 text-white rounded-lg shadow-md mb-8"> | |
<div class="px-6 py-4"> | |
<h1 class="text-3xl font-bold">Greyhound Race Predictor</h1> | |
<p class="mt-2">Advanced algorithm to predict race outcomes based on key performance metrics</p> | |
</div> | |
</header> | |
<!-- Tabs Navigation --> | |
<div class="flex border-b border-gray-300 mb-6"> | |
<button class="tab-btn py-2 px-4 font-medium text-blue-600 border-b-2 border-blue-600" data-tab="input">Dog Data Input</button> | |
<button class="tab-btn py-2 px-4 font-medium text-gray-500 hover:text-blue-600" data-tab="results">Prediction Results</button> | |
</div> | |
<!-- Formula Explanation --> | |
<div class="bg-white rounded-lg shadow-md p-6 mb-8"> | |
<h2 class="text-xl font-semibold mb-4 text-blue-600">Prediction Data</h2> | |
<div class="bg-blue-50 p-4 rounded-lg"> | |
<p class="font-medium mb-2"></p> | |
<p class="mb-4"></p> | |
<p class="mb-2">Each metric is rated on a scale of 0-10:</p> | |
<ul class="list-disc pl-5 space-y-1"> | |
<li><span class="font-medium">Form:</span> Recent race positions (higher values for better positions)</li> | |
<li><span class="font-medium">Speed:</span> Recent race times compared to competitors (higher for faster times)</li> | |
<li><span class="font-medium">Consistency:</span> How reliably the dog performs in races (higher for more consistent results)</li> | |
<li><span class="font-medium">Track:</span> Experience and performance at this particular track (higher for better track history)</li> | |
<li><span class="font-medium">Recency:</span> How recent and relevant the form data is (higher for more recent good form)</li> | |
</ul> | |
</div> | |
</div> | |
<!-- Input Tab --> | |
<div id="input" class="tab-content active"> | |
<!-- Dog Input Forms --> | |
<div class="space-y-6 mb-8" id="dogFormsContainer"> | |
<!-- Dog forms will be added here dynamically --> | |
</div> | |
<!-- Action Buttons --> | |
<div class="flex flex-wrap gap-4 mb-8"> | |
<button id="calculateBtn" class="bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-6 rounded-lg shadow-md transition duration-300"> | |
Calculate Predictions | |
</button> | |
<button id="clearBtn" class="bg-gray-500 hover:bg-gray-600 text-white font-medium py-2 px-6 rounded-lg shadow-md transition duration-300"> | |
Clear All Data | |
</button> | |
<button id="sampleBtn" class="bg-green-600 hover:bg-green-700 text-white font-medium py-2 px-6 rounded-lg shadow-md transition duration-300"> | |
Load Sample Data | |
</button> | |
<button id="addDogBtn" class="bg-purple-600 hover:bg-purple-700 text-white font-medium py-2 px-6 rounded-lg shadow-md transition duration-300"> | |
Add Another Dog | |
</button> | |
</div> | |
</div> | |
<!-- Results Tab --> | |
<div id="results" class="tab-content"> | |
<!-- Text Results --> | |
<div class="bg-white rounded-lg shadow-md p-6 mb-8"> | |
<h2 class="text-xl font-semibold mb-4 text-blue-600">Prediction Results</h2> | |
<div id="resultsText" class="bg-gray-50 p-4 rounded-lg max-h-96 overflow-y-auto border border-gray-200"> | |
<!-- Results will be displayed here --> | |
<p class="text-gray-500 italic">No predictions calculated yet. Enter dog data and click "Calculate Predictions".</p> | |
</div> | |
</div> | |
<!-- Charts --> | |
<div class="grid grid-cols-1 gap-8"> | |
<!-- Probability Chart --> | |
<div class="bg-white rounded-lg shadow-md p-6"> | |
<h2 class="text-xl font-semibold mb-4 text-blue-600">Win Probability</h2> | |
<div class="h-96"> | |
<canvas id="probabilityChart"></canvas> | |
</div> | |
</div> | |
<!-- Radar Chart --> | |
<div class="bg-white rounded-lg shadow-md p-6"> | |
<h2 class="text-xl font-semibold mb-4 text-blue-600">Top Dogs Metrics Comparison</h2> | |
<div class="radar-chart-container"> | |
<canvas id="radarChart"></canvas> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<script> | |
// Initialize app | |
document.addEventListener('DOMContentLoaded', function() { | |
// Constants | |
const MAX_DOGS = 8; | |
const METRICS = ['form', 'speed', 'consistency', 'track', 'recency']; | |
const METRIC_LABELS = ['Form', 'Speed', 'Consistency', 'Track', 'Recency']; | |
const METRIC_WEIGHTS = [0.8, 0.7, 0.6, 0.5, 0.4]; | |
// State | |
let dogsData = []; | |
let dogCount = 0; | |
let probabilityChart = null; | |
let radarChart = null; | |
// DOM Elements | |
const dogFormsContainer = document.getElementById('dogFormsContainer'); | |
const resultsText = document.getElementById('resultsText'); | |
const calculateBtn = document.getElementById('calculateBtn'); | |
const clearBtn = document.getElementById('clearBtn'); | |
const sampleBtn = document.getElementById('sampleBtn'); | |
const addDogBtn = document.getElementById('addDogBtn'); | |
const tabBtns = document.querySelectorAll('.tab-btn'); | |
const tabContents = document.querySelectorAll('.tab-content'); | |
// Initialize with 6 dogs (standard race size) | |
for (let i = 0; i < 6; i++) { | |
addDogForm(); | |
} | |
// Event Listeners | |
calculateBtn.addEventListener('click', calculatePredictions); | |
clearBtn.addEventListener('click', clearAllData); | |
sampleBtn.addEventListener('click', loadSampleData); | |
addDogBtn.addEventListener('click', addDogForm); | |
// Tab switching | |
tabBtns.forEach(btn => { | |
btn.addEventListener('click', () => { | |
const tabId = btn.getAttribute('data-tab'); | |
// Update active tab button | |
tabBtns.forEach(tb => { | |
tb.classList.remove('text-blue-600', 'border-blue-600'); | |
tb.classList.add('text-gray-500'); | |
}); | |
btn.classList.add('text-blue-600', 'border-blue-600'); | |
btn.classList.remove('text-gray-500'); | |
// Show selected tab content | |
tabContents.forEach(content => { | |
content.classList.remove('active'); | |
}); | |
document.getElementById(tabId).classList.add('active'); | |
}); | |
}); | |
// Functions | |
function addDogForm() { | |
if (dogCount >= MAX_DOGS) { | |
alert(`Maximum of ${MAX_DOGS} dogs allowed.`); | |
return; | |
} | |
const dogNum = dogCount + 1; | |
const dogId = `dog-${dogNum}`; | |
// Initialize dog data | |
dogsData[dogCount] = { | |
id: dogId, | |
name: '', | |
form: 5, | |
speed: 5, | |
consistency: 5, | |
track: 5, | |
recency: 5 | |
}; | |
// Create form HTML | |
const dogForm = document.createElement('div'); | |
dogForm.className = 'bg-white rounded-lg shadow-md p-6'; | |
dogForm.id = dogId; | |
dogForm.innerHTML = ` | |
<div class="flex justify-between items-center mb-4"> | |
<h3 class="text-lg font-medium text-gray-800">Dog ${dogNum}</h3> | |
<button class="remove-dog-btn text-red-500 hover:text-red-700" data-dog-id="${dogId}"> | |
Remove | |
</button> | |
</div> | |
<div class="mb-4"> | |
<label for="${dogId}-name" class="block text-sm font-medium text-gray-700 mb-1">Dog Name</label> | |
<input type="text" id="${dogId}-name" class="dog-name-input 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="Enter dog name"> | |
</div> | |
${METRICS.map((metric, idx) => ` | |
<div class="mb-3"> | |
<div class="flex justify-between mb-1"> | |
<label for="${dogId}-${metric}" class="block text-sm font-medium text-gray-700"> | |
${METRIC_LABELS[idx]} | |
<span class="tooltip"> | |
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 inline ml-1" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> | |
</svg> | |
<span class="tooltiptext">${getMetricTooltip(METRIC_LABELS[idx])}</span> | |
</span> | |
</label> | |
<span id="${dogId}-${metric}-value" class="text-sm font-medium text-blue-600">5.0</span> | |
</div> | |
<input type="range" id="${dogId}-${metric}" class="w-full metric-slider" min="0" max="10" step="0.1" value="5" data-dog-id="${dogId}" data-metric="${metric}"> | |
</div> | |
`).join('')} | |
`; | |
dogFormsContainer.appendChild(dogForm); | |
dogCount++; | |
// Add event listeners for this dog's inputs | |
document.getElementById(`${dogId}-name`).addEventListener('input', updateDogName); | |
METRICS.forEach(metric => { | |
const slider = document.getElementById(`${dogId}-${metric}`); | |
slider.addEventListener('input', updateMetricValue); | |
}); | |
// Add event listener for remove button | |
document.querySelector(`button[data-dog-id="${dogId}"]`).addEventListener('click', removeDogForm); | |
} | |
function getMetricTooltip(metric) { | |
const tips = { | |
'Form': 'Recent race positions (higher values for better positions)', | |
'Speed': 'Recent race times compared to competitors (higher for faster times)', | |
'Consistency': 'How reliably the dog performs in races (higher for more consistent results)', | |
'Track': 'Experience and performance at this particular track (higher for better track history)', | |
'Recency': 'How recent and relevant the form data is (higher for more recent good form)' | |
}; | |
return tips[metric] || ''; | |
} | |
function updateDogName(e) { | |
const dogId = e.target.closest('.bg-white').id; | |
const dogIndex = dogsData.findIndex(dog => dog.id === dogId); | |
if (dogIndex !== -1) { | |
dogsData[dogIndex].name = e.target.value; | |
} | |
} | |
function updateMetricValue(e) { | |
const value = parseFloat(e.target.value); | |
const metric = e.target.getAttribute('data-metric'); | |
const dogId = e.target.getAttribute('data-dog-id'); | |
const dogIndex = dogsData.findIndex(dog => dog.id === dogId); | |
// Update the displayed value | |
document.getElementById(`${dogId}-${metric}-value`).textContent = value.toFixed(1); | |
// Update the data model | |
if (dogIndex !== -1) { | |
dogsData[dogIndex][metric] = value; | |
} | |
} | |
function removeDogForm(e) { | |
const dogId = e.target.getAttribute('data-dog-id'); | |
const dogIndex = dogsData.findIndex(dog => dog.id === dogId); | |
if (dogIndex !== -1) { | |
// Remove from DOM | |
document.getElementById(dogId).remove(); | |
// Remove from data model | |
dogsData.splice(dogIndex, 1); | |
dogCount--; | |
// Reindex remaining dogs | |
const remainingForms = document.querySelectorAll('#dogFormsContainer > div'); | |
remainingForms.forEach((form, index) => { | |
const newDogNum = index + 1; | |
form.querySelector('h3').textContent = `Dog ${newDogNum}`; | |
}); | |
} | |
} | |
function clearAllData() { | |
// Clear all dog forms | |
dogFormsContainer.innerHTML = ''; | |
// Reset data | |
dogsData = []; | |
dogCount = 0; | |
// Reinitialize with 6 dogs | |
for (let i = 0; i < 6; i++) { | |
addDogForm(); | |
} | |
// Clear results | |
resultsText.innerHTML = '<p class="text-gray-500 italic">No predictions calculated yet. Enter dog data and click "Calculate Predictions".</p>'; | |
// Clear charts | |
if (probabilityChart) { | |
probabilityChart.destroy(); | |
probabilityChart = null; | |
} | |
if (radarChart) { | |
radarChart.destroy(); | |
radarChart = null; | |
} | |
// Switch to input tab | |
document.querySelector('.tab-btn[data-tab="input"]').click(); | |
} | |
function loadSampleData() { | |
// Sample data based on the race card | |
const sampleData = [ | |
{ name: "DA BOLD ROSE", form: 6.5, speed: 7.0, consistency: 8.0, track: 8.0, recency: 7.0 }, | |
{ name: "DOUBLE DROP", form: 7.0, speed: 8.5, consistency: 9.0, track: 8.0, recency: 7.5 }, | |
{ name: "QUENAGH MANILLA", form: 4.5, speed: 6.0, consistency: 6.5, track: 7.0, recency: 6.0 }, | |
{ name: "FLASHING MELODY", form: 7.0, speed: 8.5, consistency: 7.5, track: 7.5, recency: 8.0 }, | |
{ name: "DRYLAND ROXY", form: 6.0, speed: 6.5, consistency: 7.0, track: 7.0, recency: 6.5 }, | |
{ name: "GEM FRIENDLY", form: 9.5, speed: 8.0, consistency: 9.5, track: 8.0, recency: 9.0 } | |
]; | |
// Clear existing data | |
clearAllData(); | |
// Load sample data | |
sampleData.forEach((data, index) => { | |
if (index < dogCount) { | |
const dogId = dogsData[index].id; | |
// Set name | |
document.getElementById(`${dogId}-name`).value = data.name; | |
dogsData[index].name = data.name; | |
// Set metrics | |
METRICS.forEach(metric => { | |
document.getElementById(`${dogId}-${metric}`).value = data[metric]; | |
document.getElementById(`${dogId}-${metric}-value`).textContent = data[metric].toFixed(1); | |
dogsData[index][metric] = data[metric]; | |
}); | |
} | |
}); | |
} | |
function calculatePredictions() { | |
// Filter out dogs without names | |
const validDogs = dogsData.filter(dog => dog.name.trim() !== ''); | |
if (validDogs.length < 2) { | |
alert("Please enter data for at least 2 dogs."); | |
return; | |
} | |
// Calculate scores | |
const results = validDogs.map(dog => { | |
const score = METRICS.reduce((sum, metric, idx) => { | |
return sum + (dog[metric] * METRIC_WEIGHTS[idx]); | |
}, 0); | |
return { | |
name: dog.name, | |
score: score, | |
form: dog.form, | |
speed: dog.speed, | |
consistency: dog.consistency, | |
track: dog.track, | |
recency: dog.recency | |
}; | |
}); | |
// Calculate win percentages | |
const totalScore = results.reduce((sum, dog) => sum + dog.score, 0); | |
results.forEach(dog => { | |
dog.percentage = (dog.score / totalScore) * 100; | |
}); | |
// Sort by percentage (descending) | |
results.sort((a, b) => b.percentage - a.percentage); | |
// Display results | |
displayTextResults(results); | |
createCharts(results); | |
// Switch to results tab | |
document.querySelector('.tab-btn[data-tab="results"]').click(); | |
} | |
function displayTextResults(results) { | |
let html = ` | |
<h3 class="text-xl font-bold mb-4 text-center">GREYHOUND RACE WIN PROBABILITY PREDICTIONS</h3> | |
<div class="border-b border-gray-300 mb-6"></div> | |
`; | |
// Display each dog's results | |
results.forEach((dog, index) => { | |
html += ` | |
<div class="mb-6 pb-4 ${index < results.length - 1 ? 'border-b border-gray-200' : ''}"> | |
<div class="flex items-center mb-2"> | |
<span class="bg-blue-600 text-white font-bold rounded-full w-8 h-8 flex items-center justify-center mr-3">${index + 1}</span> | |
<h4 class="text-lg font-semibold">${dog.name}</h4> | |
</div> | |
<div class="grid grid-cols-1 md:grid-cols-2 gap-4"> | |
<div> | |
<p class="text-sm text-gray-600">Win Probability: <span class="font-medium text-blue-600">${dog.percentage.toFixed(2)}%</span></p> | |
<p class="text-sm text-gray-600">Total Score: <span class="font-medium text-blue-600">${dog.score.toFixed(2)}</span></p> | |
</div> | |
<div> | |
<p class="text-sm font-medium mb-1">Metrics (0-10 scale):</p> | |
<div class="grid grid-cols-2 gap-2"> | |
<p class="text-sm text-gray-600">Form: <span class="font-medium">${dog.form.toFixed(1)}</span></p> | |
<p class="text-sm text-gray-600">Speed: <span class="font-medium">${dog.speed.toFixed(1)}</span></p> | |
<p class="text-sm text-gray-600">Consistency: <span class="font-medium">${dog.consistency.toFixed(1)}</span></p> | |
<p class="text-sm text-gray-600">Track: <span class="font-medium">${dog.track.toFixed(1)}</span></p> | |
<p class="text-sm text-gray-600">Recency: <span class="font-medium">${dog.recency.toFixed(1)}</span></p> | |
</div> | |
</div> | |
</div> | |
</div> | |
`; | |
}); | |
// Summary | |
html += ` | |
<div class="mt-6 pt-4 border-t border-gray-300"> | |
<h4 class="text-lg font-semibold mb-2">ANALYSIS SUMMARY</h4> | |
<div class="border-b border-gray-300 mb-3 w-1/4"></div> | |
`; | |
if (results[0].percentage - results[1].percentage > 5) { | |
html += ` | |
<p class="text-gray-700">${results[0].name} is the clear favorite with a ${results[0].percentage.toFixed(2)}% chance of winning.</p> | |
`; | |
} else { | |
html += ` | |
<p class="text-gray-700">The race appears competitive between ${results[0].name} (${results[0].percentage.toFixed(2)}%) and ${results[1].name} (${results[1].percentage.toFixed(2)}%).</p> | |
`; | |
} | |
html += `</div>`; | |
resultsText.innerHTML = html; | |
} | |
function createCharts(results) { | |
// Destroy existing charts if they exist | |
if (probabilityChart) { | |
probabilityChart.destroy(); | |
} | |
if (radarChart) { | |
radarChart.destroy(); | |
} | |
// Create probability chart | |
createProbabilityChart(results); | |
// Create radar chart (only for top 3 dogs) | |
createRadarChart(results.slice(0, 3)); | |
} | |
function createProbabilityChart(results) { | |
const ctx = document.getElementById('probabilityChart').getContext('2d'); | |
// Limit to top 6 dogs for better visualization | |
const displayResults = results.slice(0, 6); | |
const data = { | |
labels: displayResults.map(dog => dog.name), | |
datasets: [{ | |
label: 'Win Probability %', | |
data: displayResults.map(dog => dog.percentage), | |
backgroundColor: [ | |
'rgba(239, 68, 68, 0.7)', | |
'rgba(249, 115, 22, 0.7)', | |
'rgba(234, 179, 8, 0.7)', | |
'rgba(16, 185, 129, 0.7)', | |
'rgba(59, 130, 246, 0.7)', | |
'rgba(139, 92, 246, 0.7)' | |
], | |
borderColor: [ | |
'rgba(239, 68, 68, 1)', | |
'rgba(249, 115, 22, 1)', | |
'rgba(234, 179, 8, 1)', | |
'rgba(16, 185, 129, 1)', | |
'rgba(59, 130, 246, 1)', | |
'rgba(139, 92, 246, 1)' | |
], | |
borderWidth: 1 | |
}] | |
}; | |
const options = { | |
indexAxis: 'y', | |
responsive: true, | |
maintainAspectRatio: false, | |
plugins: { | |
legend: { | |
display: false | |
}, | |
tooltip: { | |
callbacks: { | |
label: function(context) { | |
return `${context.parsed.x}% win probability`; | |
} | |
} | |
}, | |
datalabels: { | |
anchor: 'end', | |
align: 'end', | |
formatter: (value) => `${value.toFixed(1)}%`, | |
color: '#1f2937', | |
font: { | |
weight: 'bold' | |
} | |
} | |
}, | |
scales: { | |
x: { | |
beginAtZero: true, | |
max: Math.min(100, Math.ceil(Math.max(...displayResults.map(dog => dog.percentage)) * 1.2)), | |
title: { | |
display: true, | |
text: 'Win Probability (%)' | |
} | |
}, | |
y: { | |
ticks: { | |
autoSkip: false | |
} | |
} | |
} | |
}; | |
probabilityChart = new Chart(ctx, { | |
type: 'bar', | |
data: data, | |
options: options, | |
plugins: [ChartDataLabels] | |
}); | |
} | |
function createRadarChart(results) { | |
const ctx = document.getElementById('radarChart').getContext('2d'); | |
const data = { | |
labels: METRIC_LABELS, | |
datasets: results.map((dog, index) => ({ | |
label: dog.name, | |
data: [dog.form, dog.speed, dog.consistency, dog.track, dog.recency], | |
backgroundColor: [ | |
'rgba(239, 68, 68, 0.2)', | |
'rgba(234, 179, 8, 0.2)', | |
'rgba(59, 130, 246, 0.2)' | |
][index], | |
borderColor: [ | |
'rgba(239, 68, 68, 1)', | |
'rgba(234, 179, 8, 1)', | |
'rgba(59, 130, 246, 1)' | |
][index], | |
borderWidth: 2, | |
pointBackgroundColor: [ | |
'rgba(239, 68, 68, 1)', | |
'rgba(234, 179, 8, 1)', | |
'rgba(59, 130, 246, 1)' | |
][index], | |
pointRadius: 4 | |
})) | |
}; | |
const options = { | |
responsive: true, | |
maintainAspectRatio: false, | |
plugins: { | |
legend: { | |
position: 'top', | |
}, | |
tooltip: { | |
callbacks: { | |
label: function(context) { | |
return `${context.dataset.label}: ${context.raw}`; | |
} | |
} | |
} | |
}, | |
scales: { | |
r: { | |
angleLines: { | |
display: true | |
}, | |
suggestedMin: 0, | |
suggestedMax: 10, | |
ticks: { | |
stepSize: 2 | |
} | |
} | |
} | |
}; | |
radarChart = new Chart(ctx, { | |
type: 'radar', | |
data: data, | |
options: options | |
}); | |
} | |
}); | |
</script> | |
<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=LMLK/greyhound-race-predictor" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
</html> |