kickvista / script.js
luizdal18's picture
enhance evrything make it work as a premium
5008a6c verified
=======
// Premium player data with enhanced metrics and real-time updates
const premiumPlayers = {
"top-scorer": {
name: "Erling Haaland",
team: "Manchester City",
image: "http://static.photos/sport/200x200/101",
stats: [
{ stat: 'Goals', value: 94, max: 100 },
{ stat: 'Assists', value: 31, max: 50 },
{ stat: 'Pass Accuracy', value: 85, max: 100 },
{ stat: 'Dribbles', value: 68, max: 100 },
{ stat: 'Tackles', value: 22, max: 50 },
{ stat: 'Duels Win %', value: 71, max: 100 },
{ stat: 'Expected Goals', value: 88, max: 100 },
{ stat: 'Shot Conversion', value: 92, max: 100 },
{ stat: 'Aerial Duels', value: 84, max: 100 }
],
marketValue: "€180M",
form: "8.4/10",
aiPrediction: "92% chance of Golden Boot"
},
"top-assists": {
name: "Kevin De Bruyne",
team: "Manchester City",
image: "http://static.photos/sport/200x200/102",
stats: [
{ stat: 'Goals', value: 21, max: 100 },
{ stat: 'Assists', value: 49, max: 50 },
{ stat: 'Pass Accuracy', value: 93, max: 100 },
{ stat: 'Dribbles', value: 82, max: 100 },
{ stat: 'Tackles', value: 37, max: 50 },
{ stat: 'Duels Win %', value: 63, max: 100 },
{ stat: 'Key Passes', value: 95, max: 100 },
{ stat: 'Through Balls', value: 91, max: 100 },
{ stat: 'Chances Created', value: 89, max: 100 }
],
marketValue: "€90M",
form: "8.7/10",
aiPrediction: "Top 3 in Assists next season"
},
"top-passer": {
name: "Rodri",
team: "Manchester City",
image: "http://static.photos/sport/200x200/103",
stats: [
{ stat: 'Goals', value: 15, max: 100 },
{ stat: 'Assists', value: 22, max: 50 },
{ stat: 'Pass Accuracy', value: 96, max: 100 },
{ stat: 'Dribbles', value: 86, max: 100 },
{ stat: 'Tackles', value: 72, max: 50 },
{ stat: 'Duels Win %', value: 79, max: 100 },
{ stat: 'Long Passes', value: 94, max: 100 },
{ stat: 'Passes Completed', value: 97, max: 100 },
{ stat: 'Possession Won', value: 88, max: 100 }
],
marketValue: "€110M",
form: "8.9/10",
aiPrediction: "Best Defensive Midfielder in Europe"
},
"top-defender": {
name: "Virgil van Dijk",
team: "Liverpool",
image: "http://static.photos/sport/200x200/104",
stats: [
{ stat: 'Goals', value: 7, max: 100 },
{ stat: 'Assists', value: 5, max: 50 },
{ stat: 'Pass Accuracy', value: 92, max: 100 },
{ stat: 'Dribbles', value: 58, max: 100 },
{ stat: 'Tackles', value: 83, max: 50 },
{ stat: 'Duels Win %', value: 86, max: 100 },
{ stat: 'Aerial Duels', value: 95, max: 100 },
{ stat: 'Interceptions', value: 89, max: 100 },
{ stat: 'Clearances', value: 91, max: 100 },
{ stat: 'Blocks', value: 87, max: 100 },
{ stat: 'Recoveries', value: 93, max: 100 }
],
marketValue: "€75M",
form: "8.6/10",
aiPrediction: "Return to peak defensive form"
},
"top-creator": {
name: "Lionel Messi",
team: "Inter Miami",
image: "http://static.photos/sport/200x200/105",
stats: [
{ stat: 'Goals', value: 28, max: 100 },
{ stat: 'Assists', value: 42, max: 50 },
{ stat: 'Pass Accuracy', value: 89, max: 100 },
{ stat: 'Dribbles', value: 95, max: 100 },
{ stat: 'Tackles', value: 26, max: 50 },
{ stat: 'Duels Win %', value: 72, max: 100 },
{ stat: 'Key Passes', value: 97, max: 100 },
{ stat: 'Chances Created', value: 94, max: 100 },
{ stat: 'Free Kicks', value: 93, max: 100 },
{ stat: 'Dribbles Success', value: 91, max: 100 }
],
marketValue: "€60M",
form: "8.8/10",
aiPrediction: "Top creator in MLS with 15+ assists"
},
"top-goalkeeper": {
name: "Alisson Becker",
team: "Liverpool",
image: "http://static.photos/sport/200x200/106",
stats: [
{ stat: 'Clean Sheets', value: 78, max: 100 },
{ stat: 'Saves', value: 86, max: 100 },
{ stat: 'Pass Accuracy', value: 88, max: 100 },
{ stat: 'Goals Conceded', value: 24, max: 100 },
{ stat: 'Penalty Saves', value: 82, max: 100 },
{ stat: 'Claims', value: 91, max: 100 },
{ stat: 'Sweeper Actions', value: 87, max: 100 },
{ stat: 'Distribution', value: 89, max: 100 },
{ stat: 'Reflex Saves', value: 94, max: 100 },
{ stat: 'Aerial Duels', value: 92, max: 100 },
{ stat: 'Command Area', value: 95, max: 100 }
],
marketValue: "€70M",
form: "8.5/10",
aiPrediction: "Golden Glove contender in Premier League"
}
};
document.addEventListener('DOMContentLoaded', function() {
// Load initial premium player data
loadPremiumPlayerData('top-scorer');
});
function loadPremiumPlayerData(playerType) {
// Enhanced loading animation
const placeholder = document.getElementById('chart-placeholder');
placeholder.innerHTML = '<div class="flex items-center gap-3"><div class="animate-spin rounded-full h-6 w-6 border-b-2 border-blue-600"></div><span>Loading premium analytics...</span></div>';
placeholder.style.display = 'block';
// Show real-time data indicator
const liveIndicator = document.querySelector('.flex.items-center.gap-2');
if (liveIndicator) {
liveIndicator.classList.add('animate-pulse');
}
// Simulate API delay with enhanced UX
setTimeout(() => {
// Hide placeholder
placeholder.style.display = 'none';
// Get premium player data
const playerData = premiumPlayers[playerType];
// Draw enhanced radar chart
drawPremiumRadarChart(playerData);
// Update additional info panels
updatePlayerInfo(playerData);
}, 600);
}
function updatePlayerInfo(playerData) {
// Update player info card if it exists
const infoCard = document.querySelector('.player-info-card');
if (infoCard) {
infoCard.innerHTML = `
<div class="flex items-center gap-4 mb-4">
<img src="${playerData.image}" alt="${playerData.name}" class="w-16 h-16 rounded-xl object-cover">
<div>
<h3 class="text-xl font-bold">${playerData.name}</h3>
<p class="text-gray-600">${playerData.team}</p>
</div>
</div>
<div class="grid grid-cols-2 gap-4 text-sm">
<div class="bg-blue-50 p-3 rounded-lg">
<div class="text-blue-600 font-semibold">Market Value</div>
<div class="text-gray-800">${playerData.marketValue}</div>
<div class="bg-green-50 p-3 rounded-lg">
<div class="text-green-600 font-semibold">Current Form</div>
<div class="text-gray-800">${playerData.form}</div>
</div>
<div class="mt-4 bg-purple-50 p-3 rounded-lg">
<div class="text-purple-600 font-semibold">AI Prediction</div>
<div class="text-gray-800">${playerData.aiPrediction}</div>
`;
}
}
function drawPremiumRadarChart(playerData) {
// Enhanced radar chart with premium features
d3.select("#player-radar-chart svg").remove();
const data = playerData.stats;
const playerName = playerData.name;
const playerTeam = playerData.team;
// Premium dimensions and margins
const margin = { top: 120, right: 120, bottom: 120, left: 120 };
const width = Math.min(800, window.innerWidth - 80) - margin.left - margin.right;
const height = Math.min(width, window.innerHeight - margin.top - margin.bottom - 40);
const radius = Math.min(width, height) / 2;
// Create enhanced SVG
const svg = d3.select("#player-radar-chart")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", `translate(${margin.left + width/2}, ${margin.top + height/2})`);
// Enhanced levels and axes
const levels = 6;
const angleSlice = Math.PI * 2 / data.length;
// Premium scale with smooth interpolation
const rScale = d3.scaleLinear()
.range([0, radius])
.domain([0, 100]);
// Draw premium circular grid with gradient effects
for (let level = 1; level <= levels; level++) {
const levelFactor = radius * level / levels;
// Enhanced grid lines
svg.selectAll(".premium-levels")
.data(data)
.enter()
.append("line")
.attr("x1", (d, i) => levelFactor * Math.cos(angleSlice * i - Math.PI / 2))
.attr("y1", (d, i) => levelFactor * Math.sin(angleSlice * i - Math.PI / 2))
.attr("x2", (d, i) => levelFactor * Math.cos(angleSlice * (i + 1) - Math.PI / 2))
.attr("y2", (d, i) => levelFactor * Math.sin(angleSlice * (i + 1) - Math.PI / 2))
.attr("stroke", level === levels ? "#3b82f6" : "#e2e8f0")
.attr("stroke-width", level === levels ? 2 : 1)
.attr("stroke-opacity", 0.6);
// Premium level circles with gradient
svg.append("circle")
.attr("cx", 0)
.attr("cy", 0)
.attr("r", levelFactor)
.attr("fill", "none")
.attr("stroke", level === levels ? "#3b82f6" : "#e2e8f0")
.attr("stroke-width", level === levels ? 2 : 0.5)
.attr("stroke-opacity", 0.4);
}
// Enhanced axes with premium styling
const axis = svg.selectAll(".premium-axis")
.data(data)
.enter()
.append("g")
.attr("class", "premium-axis");
axis.append("line")
.attr("x1", 0)
.attr("y1", 0)
.attr("x2", (d, i) => radius * Math.cos(angleSlice * i - Math.PI / 2))
.attr("y2", (d, i) => radius * Math.sin(angleSlice * i - Math.PI / 2))
.attr("stroke", "#94a3b8")
.attr("stroke-width", 1)
.attr("stroke-opacity", 0.5);
// Premium axis labels
axis.append("text")
.attr("class", "premium-axis-label")
.attr("x", (d, i) => (radius + 30) * Math.cos(angleSlice * i - Math.PI / 2))
.attr("y", (d, i) => (radius + 30) * Math.sin(angleSlice * i - Math.PI / 2))
.attr("dy", "0.35em")
.attr("text-anchor", "middle")
.text(d => d.stat)
.attr("fill", "#475569")
.attr("font-size", "13px")
.attr("font-weight", "600");
// Enhanced radar line with premium styling
const radarLine = d3.line()
.x((d, i) => rScale(d.value) * Math.cos(angleSlice * i - Math.PI / 2))
.y((d, i) => rScale(d.value) * Math.sin(angleSlice * i - Math.PI / 2))
.curve(d3.curveCatmullRomClosed);
// Premium radar group
const radarGroup = svg.append("g")
.attr("class", "premium-radar-group");
// Enhanced radar area with gradient
radarGroup.append("path")
.datum(data)
.attr("class", "premium-radar-area")
.attr("d", radarLine)
.attr("fill", "url(#radar-gradient)")
.attr("stroke", "url(#radar-line-gradient)")
.attr("stroke-width", 3);
// Enhanced data points
radarGroup.selectAll(".premium-radar-circle")
.data(data)
.enter()
.append("circle")
.attr("class", "premium-radar-circle")
.attr("cx", (d, i) => rScale(d.value) * Math.cos(angleSlice * i - Math.PI / 2))
.attr("cy", (d, i) => rScale(d.value) * Math.sin(angleSlice * i - Math.PI / 2))
.attr("r", 6)
.attr("fill", "url(#point-gradient)")
.attr("stroke", "#ffffff")
.attr("stroke-width", 2);
// Premium player name with enhanced styling
svg.append("text")
.attr("class", "premium-player-name")
.attr("x", 0)
.attr("y", -height/2 + 40)
.attr("text-anchor", "middle")
.text(`${playerName} | ${playerTeam}")
.attr("fill", "#1e293b")
.attr("font-size", "22px")
.attr("font-weight", "bold");
// Enhanced value labels
radarGroup.selectAll(".premium-value-label")
.data(data)
.enter()
.append("text")
.attr("class", "premium-value-label")
.attr("x", (d, i) => (rScale(d.value) + 20) * Math.cos(angleSlice * i - Math.PI / 2))
.attr("y", (d, i) => (rScale(d.value) + 20) * Math.sin(angleSlice * i - Math.PI / 2))
.attr("dy", "0.35em")
.attr("text-anchor", "middle")
.text(d => d.value)
.attr("fill", "#3b82f6")
.attr("font-size", "14px")
.attr("font-weight", "bold");
}
function initializePremiumCharts() {
// Initialize the performance trend chart
const ctx = document.getElementById('performanceChart');
if (ctx) {
const chartLoader = document.getElementById('chartLoader');
if (chartLoader) chartLoader.style.display = 'none';
new Chart(ctx, {
type: 'line',
data: {
labels: ['Aug', 'Sep', 'Oct', 'Nov', 'Dec', 'Jan', 'Feb'],
datasets: [{
label: 'Form Rating',
data: [7.8, 8.2, 8.6, 8.9, 8.7, 8.8, 9.1],
borderColor: '#3b82f6',
backgroundColor: 'rgba(59, 130, 246, 0.1),
tension: 0.4,
fill: true,
pointBackgroundColor: '#3b82f6',
pointBorderColor: '#ffffff',
pointBorderWidth: 2,
pointRadius: 4,
pointHoverRadius: 6
}]
},
options: {
responsive: true,
plugins: {
legend: {
display: false
},
tooltip: {
backgroundColor: 'rgba(0, 0, 0, 0.8),
titleColor: '#ffffff',
bodyColor: '#ffffff'
}
},
scales: {
y: {
beginAtZero: false,
min: 7,
max: 10,
grid: {
color: 'rgba(0, 0, 0, 0.05),
border: {
dash: [4, 4]
}
},
x: {
grid: {
display: false
}
}
}
}
});
}
}
function drawRadarChart(playerData) {
// Clear previous chart
d3.select("#player-radar-chart svg").remove();
const data = playerData.stats;
const playerName = playerData.name;
const playerTeam = playerData.team;
// Set up dimensions
const margin = { top: 100, right: 100, bottom: 100, left: 100 };
const width = Math.min(700, window.innerWidth - 40) - margin.left - margin.right;
const height = Math.min(width, window.innerHeight - margin.top - margin.bottom - 20);
const radius = Math.min(width, height) / 2;
// Create SVG
const svg = d3.select("#player-radar-chart")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", `translate(${margin.left + width/2}, ${margin.top + height/2})`);
// Levels and axes
const levels = 5;
const angleSlice = Math.PI * 2 / data.length;
// Scale for the radius
const rScale = d3.scaleLinear()
.range([0, radius])
.domain([0, 100]);
// Draw circular grid lines
for (let level = 1; level <= levels; level++) {
const levelFactor = radius * level / levels;
svg.selectAll(".levels")
.data(data)
.enter()
.append("line")
.attr("x1", (d, i) => levelFactor * Math.cos(angleSlice * i - Math.PI / 2))
.attr("y1", (d, i) => levelFactor * Math.sin(angleSlice * i - Math.PI / 2))
.attr("x2", (d, i) => levelFactor * Math.cos(angleSlice * (i + 1) - Math.PI / 2))
.attr("y2", (d, i) => levelFactor * Math.sin(angleSlice * (i + 1) - Math.PI / 2))
.attr("stroke", "#e2e8f0")
.attr("stroke-width", 1);
// Draw level circles
svg.append("circle")
.attr("cx", 0)
.attr("cy", 0)
.attr("r", levelFactor)
.attr("fill", "none")
.attr("stroke", "#e2e8f0")
.attr("stroke-width", 0.5);
}
// Draw axes
const axis = svg.selectAll(".axis")
.data(data)
.enter()
.append("g")
.attr("class", "axis");
axis.append("line")
.attr("x1", 0)
.attr("y1", 0)
.attr("x2", (d, i) => radius * Math.cos(angleSlice * i - Math.PI / 2))
.attr("y2", (d, i) => radius * Math.sin(angleSlice * i - Math.PI / 2))
.attr("stroke", "#94a3b8")
.attr("stroke-width", 1);
// Draw axis labels
axis.append("text")
.attr("class", "axis-label")
.attr("x", (d, i) => (radius + 20) * Math.cos(angleSlice * i - Math.PI / 2))
.attr("y", (d, i) => (radius + 20) * Math.sin(angleSlice * i - Math.PI / 2))
.attr("dy", "0.35em")
.attr("text-anchor", "middle")
.text(d => d.stat)
.attr("fill", "#64748b")
.attr("font-size", "12px");
// Draw radar area
const radarLine = d3.line()
.x((d, i) => rScale(d.value) * Math.cos(angleSlice * i - Math.PI / 2))
.y((d, i) => rScale(d.value) * Math.sin(angleSlice * i - Math.PI / 2))
.curve(d3.curveLinearClosed);
// Create a group for the radar
const radarGroup = svg.append("g")
.attr("class", "radar-group");
// Draw the radar area
radarGroup.append("path")
.datum(data)
.attr("class", "radar-area")
.attr("d", radarLine)
.attr("fill", "rgba(59, 130, 246, 0.4)")
.attr("stroke", "rgba(59, 130, 246, 1)")
.attr("stroke-width", 2);
// Draw data points
radarGroup.selectAll(".radar-circle")
.data(data)
.enter()
.append("circle")
.attr("class", "radar-circle")
.attr("cx", (d, i) => rScale(d.value) * Math.cos(angleSlice * i - Math.PI / 2))
.attr("cy", (d, i) => rScale(d.value) * Math.sin(angleSlice * i - Math.PI / 2))
.attr("r", 4)
.attr("fill", "rgba(59, 130, 246, 1)")
.attr("stroke", "#fff")
.attr("stroke-width", 1);
// Add player name
svg.append("text")
.attr("class", "player-name")
.attr("x", 0)
.attr("y", -height/2 + 30)
.attr("text-anchor", "middle")
.text(`${playerName} - ${playerTeam}`)
.attr("fill", "#1e293b")
.attr("font-size", "18px")
.attr("font-weight", "bold");
// Add value labels
radarGroup.selectAll(".value-label")
.data(data)
.enter()
.append("text")
.attr("class", "value-label")
.attr("x", (d, i) => (rScale(d.value) + 15) * Math.cos(angleSlice * i - Math.PI / 2))
.attr("y", (d, i) => (rScale(d.value) + 15) * Math.sin(angleSlice * i - Math.PI / 2))
.attr("dy", "0.35em")
.attr("text-anchor", "middle")
.text(d => d.value)
.attr("fill", "#64748b")
.attr("font-size", "11px")
.attr("font-weight", "bold");
}