feat: add RPM vs. Force and Speed vs. RPM charts to shift point analysis

This commit is contained in:
Jan-Peter von Hunnius 2026-06-06 08:16:10 +02:00
parent 87e5bcae5b
commit 3fa5a1441a

View file

@ -43,10 +43,41 @@ onMounted(async () => {
}
})
const colors = ['#4f8ff7', '#34d399', '#fbbf24', '#f87171', '#a78bfa', '#60a5fa', '#f472b6']
const rpmVsAccelChartData = computed(() => {
if (!analysis.value) return null
const curves = analysis.value.gear_curves.filter((g) => g.gear >= 2)
return {
datasets: curves.map((curve, i) => ({
label: `${curve.gear_display} (${curve.run_label})`,
data: curve.data_points.map((p) => ({ x: p.rpm, y: p.acceleration_g })),
borderColor: colors[i % colors.length],
backgroundColor: colors[i % colors.length] + '20',
showLine: true,
fill: false,
tension: 0.3,
pointRadius: 0,
borderWidth: 2,
})),
}
})
const rpmVsAccelChartOptions = {
responsive: true,
plugins: {
legend: { labels: { color: '#8b8fa3' } },
title: { display: true, text: 'RPM vs. Force', color: '#e2e4ea' },
},
scales: {
x: { ticks: { color: '#8b8fa3' }, grid: { color: '#2a2e3f' }, title: { display: true, text: 'RPM', color: '#8b8fa3' } },
y: { ticks: { color: '#8b8fa3' }, grid: { color: '#2a2e3f' }, title: { display: true, text: 'Force (g)', color: '#8b8fa3' } },
},
}
const gearCurvesChartData = computed(() => {
if (!analysis.value) return null
const curves = analysis.value.gear_curves.filter((g) => g.gear >= 2)
const colors = ['#4f8ff7', '#34d399', '#fbbf24', '#f87171', '#a78bfa', '#60a5fa', '#f472b6']
return {
datasets: curves.map((curve, i) => ({
label: `${curve.gear_display} (${curve.run_label})`,
@ -66,11 +97,41 @@ const gearCurvesOptions = {
responsive: true,
plugins: {
legend: { labels: { color: '#8b8fa3' } },
title: { display: true, text: 'Gear Acceleration Curves', color: '#e2e4ea' },
title: { display: true, text: 'Speed vs. Force', color: '#e2e4ea' },
},
scales: {
x: { ticks: { color: '#8b8fa3' }, grid: { color: '#2a2e3f' }, title: { display: true, text: 'Speed (km/h)', color: '#8b8fa3' } },
y: { ticks: { color: '#8b8fa3' }, grid: { color: '#2a2e3f' }, title: { display: true, text: 'Acceleration (g)', color: '#8b8fa3' } },
y: { ticks: { color: '#8b8fa3' }, grid: { color: '#2a2e3f' }, title: { display: true, text: 'Force (g)', color: '#8b8fa3' } },
},
}
const speedVsRpmChartData = computed(() => {
if (!analysis.value) return null
const curves = analysis.value.gear_curves.filter((g) => g.gear >= 2)
return {
datasets: curves.map((curve, i) => ({
label: `${curve.gear_display} (${curve.run_label})`,
data: curve.data_points.map((p) => ({ x: p.speed_kmh, y: p.rpm })),
borderColor: colors[i % colors.length],
backgroundColor: colors[i % colors.length] + '20',
showLine: true,
fill: false,
tension: 0.3,
pointRadius: 0,
borderWidth: 2,
})),
}
})
const speedVsRpmChartOptions = {
responsive: true,
plugins: {
legend: { labels: { color: '#8b8fa3' } },
title: { display: true, text: 'Speed vs. RPM (Gear Ratios)', color: '#e2e4ea' },
},
scales: {
x: { ticks: { color: '#8b8fa3' }, grid: { color: '#2a2e3f' }, title: { display: true, text: 'Speed (km/h)', color: '#8b8fa3' } },
y: { ticks: { color: '#8b8fa3' }, grid: { color: '#2a2e3f' }, title: { display: true, text: 'RPM', color: '#8b8fa3' } },
},
}
@ -157,11 +218,21 @@ const crossoverChartOptions = {
</div>
</div>
<!-- Gear Acceleration Curves Chart -->
<!-- RPM vs. Force Chart -->
<div v-if="rpmVsAccelChartData" class="card mb-3">
<Scatter :data="rpmVsAccelChartData" :options="rpmVsAccelChartOptions" />
</div>
<!-- Speed vs. Force Chart -->
<div v-if="gearCurvesChartData" class="card mb-3">
<Scatter :data="gearCurvesChartData" :options="gearCurvesOptions" />
</div>
<!-- Speed vs. RPM Chart -->
<div v-if="speedVsRpmChartData" class="card mb-3">
<Scatter :data="speedVsRpmChartData" :options="speedVsRpmChartOptions" />
</div>
<!-- Crossover Points Chart -->
<div v-if="crossoverChartData" class="card mb-3">
<Bar :data="crossoverChartData" :options="crossoverChartOptions" />