diff --git a/ts/routes/deck-options/SimulatorModal.svelte b/ts/routes/deck-options/SimulatorModal.svelte index c8d93cc73..1ec477b13 100644 --- a/ts/routes/deck-options/SimulatorModal.svelte +++ b/ts/routes/deck-options/SimulatorModal.svelte @@ -17,6 +17,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html SimulateSubgraph, SimulateWorkloadSubgraph, type Point, + type WorkloadPoint, } from "../graphs/simulator"; import * as tr from "@generated/ftl"; import { renderSimulationChart, renderWorkloadChart } from "../graphs/simulator"; @@ -65,7 +66,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html let svg: HTMLElement | SVGElement | null = null; let simulationNumber = 0; - let points: Point[] = []; + let points: (WorkloadPoint | Point)[] = []; const newCardsIgnoreReviewLimit = state.newCardsIgnoreReviewLimit; let smooth = true; let suspendLeeches = $config.leechAction == DeckConfig_Config_LeechAction.SUSPEND; @@ -215,13 +216,14 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html memorized: v, count: resp!.reviewCount[dr], label: simulationNumber, + learnSpan: simulateFsrsRequest.daysToSimulate, })), ); tableData = renderWorkloadChart( svg as SVGElement, bounds, - points, + points as WorkloadPoint[], simulateWorkloadSubgraph, ); } @@ -300,7 +302,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html tableData = render_function( svg as SVGElement, bounds, - pointsToRender, + // This cast shouldn't matter because we aren't switching between modes in the same modal + pointsToRender as WorkloadPoint[], (workload ? simulateWorkloadSubgraph : simulateSubgraph) as any as never, ); } diff --git a/ts/routes/graphs/simulator.ts b/ts/routes/graphs/simulator.ts index 794b23a71..052e3fe6f 100644 --- a/ts/routes/graphs/simulator.ts +++ b/ts/routes/graphs/simulator.ts @@ -31,6 +31,10 @@ export interface Point { label: number; } +export type WorkloadPoint = Point & { + learnSpan: number; +}; + export enum SimulateSubgraph { time, count, @@ -47,7 +51,7 @@ export enum SimulateWorkloadSubgraph { export function renderWorkloadChart( svgElem: SVGElement, bounds: GraphBounds, - data: Point[], + data: WorkloadPoint[], subgraph: SimulateWorkloadSubgraph, ) { const xMin = 70; @@ -59,8 +63,8 @@ export function renderWorkloadChart( const subgraph_data = ({ [SimulateWorkloadSubgraph.ratio]: data.map(d => ({ ...d, y: d.timeCost / d.memorized })), - [SimulateWorkloadSubgraph.time]: data.map(d => ({ ...d, y: d.timeCost })), - [SimulateWorkloadSubgraph.count]: data.map(d => ({ ...d, y: d.count })), + [SimulateWorkloadSubgraph.time]: data.map(d => ({ ...d, y: d.timeCost / d.learnSpan })), + [SimulateWorkloadSubgraph.count]: data.map(d => ({ ...d, y: d.count / d.learnSpan })), [SimulateWorkloadSubgraph.memorized]: data.map(d => ({ ...d, y: d.memorized })), })[subgraph]; @@ -73,8 +77,9 @@ export function renderWorkloadChart( const formatY: (value: number) => string = ({ [SimulateWorkloadSubgraph.ratio]: (value: number) => tr.deckConfigFsrsSimulatorRatioTooltip({ time: timeSpan(value) }), - [SimulateWorkloadSubgraph.time]: timeSpan, - [SimulateWorkloadSubgraph.count]: (value: number) => tr.statisticsReviews({ reviews: Math.round(value) }), + [SimulateWorkloadSubgraph.time]: (value: number) => + tr.statisticsMinutesPerDay({ count: parseFloat((value / 60).toPrecision(2)) }), + [SimulateWorkloadSubgraph.count]: (value: number) => tr.statisticsReviewsPerDay({ count: Math.round(value) }), [SimulateWorkloadSubgraph.memorized]: (value: number) => tr.statisticsMemorized({ memorized: Math.round(value).toFixed(0) }), })[subgraph];