Feat/Neaten dr graph x-axis (#4251)

* Remove "Plotted on x axis"

* Add: X tick format

* fix formatx

* Fix: Regular simualtor x axis
This commit is contained in:
Luc Mcgrady 2025-08-08 11:30:10 +01:00 committed by GitHub
parent d3e8dc6dbf
commit f4266f0142
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 18 additions and 25 deletions

View file

@ -517,7 +517,6 @@ deck-config-smooth-graph = Smooth graph
deck-config-suspend-leeches = Suspend leeches
deck-config-save-options-to-preset = Save Changes to Preset
deck-config-save-options-to-preset-confirm = Overwrite the options in your current preset with the options that are currently set in the simulator?
deck-config-plotted-on-x-axis = (Plotted on the X-axis)
# Radio button in the FSRS simulation diagram (Deck options -> FSRS) selecting
# to show the total number of cards that can be recalled or retrieved on a
# specific date.
@ -545,6 +544,7 @@ deck-config-fsrs-good-fit = Health Check:
## NO NEED TO TRANSLATE. This text is no longer used by Anki, and will be removed in the future.
deck-config-plotted-on-x-axis = (Plotted on the X-axis)
deck-config-a-100-day-interval =
{ $days ->
[one] A 100 day interval will become { $days } day.

View file

@ -44,8 +44,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import Warning from "./Warning.svelte";
import type { ComputeRetentionProgress } from "@generated/anki/collection_pb";
import Modal from "bootstrap/js/dist/modal";
import Row from "$lib/components/Row.svelte";
import Col from "$lib/components/Col.svelte";
export let state: DeckOptionsState;
export let simulateFsrsRequest: SimulateFsrsReviewRequest;
@ -373,23 +371,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
{tr.deckConfigDesiredRetention()}
</SettingTitle>
</SpinBoxFloatRow>
{:else}
<Row --cols={13}>
<Col --col-size={7} breakpoint="xs">
<SettingTitle
on:click={() => openHelpModal("desiredRetention")}
>
{tr.deckConfigDesiredRetention()}
</SettingTitle>
</Col>
<Col --col-size={6} breakpoint="xs">
<input
type="text"
disabled
value={tr.deckConfigPlottedOnXAxis()}
/>
</Col>
</Row>
{/if}
<SpinBoxRow

View file

@ -74,6 +74,13 @@ export function renderWorkloadChart(
: n.toString();
};
const formatter = new Intl.NumberFormat(undefined, {
style: "percent",
minimumFractionDigits: 0,
maximumFractionDigits: 0,
});
const xTickFormat = (n: number) => formatter.format(n / 100);
const formatY: (value: number) => string = ({
[SimulateWorkloadSubgraph.ratio]: (value: number) =>
tr.deckConfigFsrsSimulatorRatioTooltip({ time: timeSpan(value) }),
@ -85,7 +92,7 @@ export function renderWorkloadChart(
})[subgraph];
function formatX(dr: number) {
return `Desired Retention: ${dr}%<br>`;
return `${tr.deckConfigDesiredRetention()}: ${xTickFormat(dr)}<br>`;
}
return _renderSimulationChart(
@ -93,10 +100,11 @@ export function renderWorkloadChart(
bounds,
subgraph_data,
x,
yTickFormat,
formatY,
formatX,
(_e: MouseEvent, _d: number) => undefined,
yTickFormat,
xTickFormat,
);
}
@ -169,10 +177,11 @@ export function renderSimulationChart(
bounds,
subgraph_data,
x,
yTickFormat,
formatY,
formatX,
legendMouseMove,
yTickFormat,
undefined,
);
}
@ -181,10 +190,11 @@ function _renderSimulationChart<T extends { x: any; y: any; label: number }>(
bounds: GraphBounds,
subgraph_data: T[],
x: any,
yTickFormat: (n: number) => string,
formatY: (n: T["y"]) => string,
formatX: (n: T["x"]) => string,
legendMouseMove: (e: MouseEvent, d: number) => void,
yTickFormat?: (n: number) => string,
xTickFormat?: (n: number) => string,
): TableDatum[] {
const svg = select(svgElem);
svg.selectAll(".lines").remove();
@ -198,7 +208,9 @@ function _renderSimulationChart<T extends { x: any; y: any; label: number }>(
const trans = svg.transition().duration(600) as any;
svg.select<SVGGElement>(".x-ticks")
.call((selection) => selection.transition(trans).call(axisBottom(x).ticks(7).tickSizeOuter(0)))
.call((selection) =>
selection.transition(trans).call(axisBottom(x).ticks(7).tickSizeOuter(0).tickFormat(xTickFormat as any))
)
.attr("direction", "ltr");
// y scale