import * as echarts from 'echarts'; var chartDom = document.getElementById('main'); var myChart = echarts.init(chartDom); var option; function normalRandom(mean, stdDev) { let u = 0, v = 0; while (u === 0) u = Math.random(); while (v === 0) v = Math.random(); let num = Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v); return num * stdDev + mean; } function generateLapTime(iRating) { const minTime = 99; const maxTime = 117; const range = maxTime - minTime; let normalizedRating = (10000 - iRating) / 10000; let baseTime = minTime + normalizedRating * range * 0.9; // Increased variability for lower iRatings let stdDev = 0.5 + normalizedRating * 2; let randomFactor = normalRandom(0, stdDev); return Math.max(minTime, Math.min(maxTime, baseTime + randomFactor)); } function formatLapTime(seconds) { const minutes = Math.floor(seconds / 60); const remainingSeconds = (seconds % 60).toFixed(3).padStart(6, '0'); return `${minutes}:${remainingSeconds}`; } function movingAverage(data, windowSize) { const result = []; for (let i = 0; i < data.length; i++) { const start = Math.max(0, i - windowSize + 1); const end = i + 1; const window = data.slice(start, end); const average = window.reduce((sum, num) => sum + num, 0) / window.length; result.push(average); } return result; } // Generate data points const sampleSize = 100; const data = []; for (let i = 0; i < sampleSize; i++) { let iRating = Math.round(i * (10000 / sampleSize)); let normalizedRating = iRating / 10000; let lapTime = generateLapTime(iRating); // Calculate confidence interval based on iRating let confidenceInterval = 0.5 + (1 - normalizedRating) * 2.5; data.push({ iRating: iRating, lapTime: lapTime, lower: lapTime - confidenceInterval, upper: lapTime + confidenceInterval }); } // Prepare data for ECharts const xAxisData = data.map((item) => item.iRating); const rawSeriesData = data.map((item) => item.lapTime); const seriesData = movingAverage(rawSeriesData, 10); // Apply moving average const lowerBound = data.map((item) => item.lower); const upperBound = data.map((item) => item.upper - item.lower); // ECharts option option = { backgroundColor: '#1e1e27', title: { text: 'iRating vs Lap Time Confidence Band', left: 'center', top: '20px', textStyle: { color: '#fff', fontSize: 20 } }, tooltip: { trigger: 'axis', formatter: function (params) { const iRating = params[0].axisValue; const lapTime = params[2].data; const lower = params[0].data; const upper = params[1].data + lower; return `iRating: ${iRating}
Avg Lap Time: ${formatLapTime(lapTime)}
Range: ${formatLapTime(lower)} - ${formatLapTime(upper)}`; } }, xAxis: { type: 'category', data: xAxisData, name: 'iRating', nameLocation: 'middle', nameGap: 30, axisLabel: { color: '#fff', formatter: (value) => value.toLocaleString() }, axisLine: { lineStyle: { color: '#fff' } }, splitLine: { show: true, lineStyle: { color: 'rgba(255, 255, 255, 0.1)' } } }, yAxis: { type: 'value', name: 'Lap Time', nameLocation: 'middle', nameGap: 40, min: 98, max: 118, interval: 2, axisLabel: { formatter: function (value) { return formatLapTime(value); }, color: '#fff' }, axisLine: { lineStyle: { color: '#fff' } }, splitLine: { show: true, lineStyle: { color: 'rgba(255, 255, 255, 0.1)' } } }, series: [ { name: 'Lower Bound', type: 'line', data: lowerBound, lineStyle: { opacity: 0 }, stack: 'confidence-band', symbol: 'none' }, {