AI Prediction
${playerData.aiPrediction}
`;
}
}
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");
}