From 5e70e3398cbab83a1b1f33fc3465ceca1104778a Mon Sep 17 00:00:00 2001 From: Miodec Date: Wed, 7 Jan 2026 21:36:40 +0100 Subject: [PATCH] impr(test result): recalculate min max chart values when toggling a dataset --- frontend/src/ts/test/result.ts | 142 ++++++++++++++++++++------------- 1 file changed, 88 insertions(+), 54 deletions(-) diff --git a/frontend/src/ts/test/result.ts b/frontend/src/ts/test/result.ts index bbc6a414a..3ab88e459 100644 --- a/frontend/src/ts/test/result.ts +++ b/frontend/src/ts/test/result.ts @@ -50,6 +50,7 @@ import * as ConnectionState from "../states/connection"; import { currentQuote } from "./test-words"; let result: CompletedEvent; +let minChartVal: number; let maxChartVal: number; let useSmoothedBurst = true; @@ -62,7 +63,7 @@ export function toggleSmoothedBurst(): void { useSmoothedBurst = !useSmoothedBurst; Notifications.add(useSmoothedBurst ? "on" : "off", 1); if (TestState.resultVisible) { - void updateGraph().then(() => { + void updateChartData().then(() => { ChartController.result.update("resize"); }); } @@ -72,7 +73,7 @@ export function toggleUserFakeChartData(): void { useFakeChartData = !useFakeChartData; Notifications.add(useFakeChartData ? "on" : "off", 1); if (TestState.resultVisible) { - void updateGraph().then(() => { + void updateChartData().then(() => { ChartController.result.update("resize"); }); } @@ -80,7 +81,7 @@ export function toggleUserFakeChartData(): void { let resultAnnotation: AnnotationOptions<"line">[] = []; -async function updateGraph(): Promise { +async function updateChartData(): Promise { if (result.chartData === "toolong") return; const typingSpeedUnit = getTypingSpeedUnit(Config.typingSpeedUnit); @@ -130,29 +131,6 @@ async function updateGraph(): Promise { chartData2.pop(); } - maxChartVal = Math.max( - ...[ - Math.max(...chartData1), - Math.max(...chartData2), - Math.max(...chartData3), - ], - ); - - let minChartVal = 0; - - if (!Config.startGraphsAtZero) { - minChartVal = Math.min( - ...[ - Math.min(...chartData1), - Math.min(...chartData2), - Math.min(...chartData3), - ], - ); - - // Round down to nearest multiple of 10 - minChartVal = Math.floor(minChartVal / 10) * 10; - } - const subcolor = await ThemeColors.get("sub"); if (Config.funbox.length > 0) { @@ -197,16 +175,10 @@ async function updateGraph(): Promise { ChartController.result.getDataset("wpm").data = chartData1; ChartController.result.getDataset("wpm").label = Config.typingSpeedUnit; - ChartController.result.getScale("wpm").min = minChartVal; - ChartController.result.getScale("wpm").max = maxChartVal; ChartController.result.getDataset("raw").data = chartData2; - ChartController.result.getScale("raw").min = minChartVal; - ChartController.result.getScale("raw").max = maxChartVal; ChartController.result.getDataset("burst").data = chartData3; - ChartController.result.getScale("burst").min = minChartVal; - ChartController.result.getScale("burst").max = maxChartVal; ChartController.result.getDataset("error").data = result.chartData.err; ChartController.result.getScale("error").max = Math.max( @@ -302,7 +274,7 @@ function applyFakeChartData(): void { ChartController.result.getScale("error").max = Math.max(...fakeChartData.err); } -export async function updateGraphPBLine(): Promise { +export async function updateChartPBLine(): Promise { const themecolors = await ThemeColors.getAll(); const localPb = await DB.getLocalPB( result.mode, @@ -346,17 +318,6 @@ export async function updateGraphPBLine(): Promise { display: true, }, }); - const lpbRange = typingSpeedUnit.fromWpm(20); - if ( - maxChartVal >= parseFloat(chartlpb) - lpbRange && - maxChartVal <= parseFloat(chartlpb) + lpbRange - ) { - maxChartVal = Math.round(parseFloat(chartlpb) + lpbRange); - } - - ChartController.result.getScale("wpm").max = maxChartVal; - ChartController.result.getScale("raw").max = maxChartVal; - ChartController.result.getScale("burst").max = maxChartVal; } function updateWpmAndAcc(): void { @@ -1021,10 +982,12 @@ export async function update( updateQuoteSource(randomQuote); updateQuoteFavorite(randomQuote); await updateCrown(dontSave); - await updateGraph(); - await updateGraphPBLine(); - await updateTags(dontSave); + await updateChartData(); updateResultChartDataVisibility(); + updateMinMaxChartValues(); + await updateChartPBLine(); + applyMinMaxChartValues(); + await updateTags(dontSave); updateOther(difficultyFailed, failReason, afkDetected, isRepeated, tooShort); ((ChartController.result.options as PluginChartOptions<"line" | "scatter">) @@ -1166,7 +1129,73 @@ const resultChartDataVisibility = new LocalStorageWithSchema({ }, }); -function updateResultChartDataVisibility(update = false): void { +function updateMinMaxChartValues(): void { + const values = []; + + const datasets = { + wpm: ChartController.result.getDataset("wpm"), + burst: ChartController.result.getDataset("burst"), + raw: ChartController.result.getDataset("raw"), + }; + + if (!datasets.wpm.hidden) { + values.push(...datasets.wpm.data); + } + if (!datasets.burst.hidden) { + values.push(...datasets.burst.data); + } + if (!datasets.raw.hidden) { + values.push(...datasets.raw.data); + } + + maxChartVal = Math.max(...values); + + let maxAnnotation: null | number = null; + for (const annotation of resultAnnotation) { + if (annotation.display === undefined) continue; + if (annotation.value === undefined) continue; + // values.push(annotation.value as number); + if ( + maxAnnotation === null || + parseFloat(annotation.value as string) > maxAnnotation + ) { + maxAnnotation = parseFloat(annotation.value as string); + } + } + + if (maxAnnotation !== null) { + const typingSpeedUnit = getTypingSpeedUnit(Config.typingSpeedUnit); + const lpbRange = typingSpeedUnit.fromWpm(20); + if ( + maxChartVal >= maxAnnotation - lpbRange && + maxChartVal <= maxAnnotation + lpbRange + ) { + maxChartVal = Math.round(maxAnnotation + lpbRange); + } + } + + maxChartVal = Math.ceil(maxChartVal / 10) * 10; + + minChartVal = 0; + + if (!Config.startGraphsAtZero) { + minChartVal = Math.min(...values); + + // Round down to nearest multiple of 10 + minChartVal = Math.floor(minChartVal / 10) * 10; + } +} + +function applyMinMaxChartValues(): void { + ChartController.result.getScale("wpm").min = minChartVal; + ChartController.result.getScale("wpm").max = maxChartVal; + ChartController.result.getScale("raw").min = minChartVal; + ChartController.result.getScale("raw").max = maxChartVal; + ChartController.result.getScale("burst").min = minChartVal; + ChartController.result.getScale("burst").max = maxChartVal; +} + +function updateResultChartDataVisibility(): void { const vis = resultChartDataVisibility.get(); ChartController.result.getDataset("raw").hidden = !vis.raw; ChartController.result.getDataset("burst").hidden = !vis.burst; @@ -1180,8 +1209,6 @@ function updateResultChartDataVisibility(update = false): void { } } - if (update) ChartController.result.update(); - const buttons = $(".pageTest #result .chart .chartLegend button"); // Check if there are any tag PB annotations @@ -1274,7 +1301,7 @@ export function updateTagsAfterEdit( ); } -$(".pageTest #result .chart .chartLegend button").on("click", (event) => { +$(".pageTest #result .chart .chartLegend button").on("click", async (event) => { const $target = $(event.target); const id = $target.data("id") as string; @@ -1296,7 +1323,11 @@ $(".pageTest #result .chart .chartLegend button").on("click", (event) => { vis[id] = !vis[id]; resultChartDataVisibility.set(vis); - updateResultChartDataVisibility(true); + updateResultChartDataVisibility(); + updateMinMaxChartValues(); + applyMinMaxChartValues(); + void ChartController.result.updateColors(); + ChartController.result.update(); }); $(".pageTest #favoriteQuoteButton").on("click", async () => { @@ -1356,8 +1387,11 @@ ConfigEvent.subscribe(async ({ key }) => { resultAnnotation = []; updateWpmAndAcc(); - await updateGraph(); - await updateGraphPBLine(); + await updateChartData(); + await updateChartPBLine(); + updateResultChartDataVisibility(); + updateMinMaxChartValues(); + applyMinMaxChartValues(); void TestUI.applyBurstHeatmap(); ((ChartController.result.options as PluginChartOptions<"line" | "scatter">)