Anki/ts/routes/graphs/true-retention.ts
Ross Brown 5637390b50
Make the "True Retention" table pretty (#3640)
* Make the True Retention table pretty

* Hide absolute pass/fail table for 'all'

* Run './ninja format'

* Manually run prettier on Svelte 5 components

* Refactor to not use {#snippet}

* Fix lint to pass check:eslint

* Fix lint to pass check:svelte

* Rename t9n -> tr to follow code style

* Replace hard-coded string with a translation string

* Use assertUnreachable(...) for exhaustively matching enum
2024-12-19 00:41:57 +11:00

117 lines
2.7 KiB
TypeScript

// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import * as tr from "@generated/ftl";
import { localizedNumber } from "@tslib/i18n";
import { assertUnreachable } from "@tslib/typing";
import { RevlogRange } from "./graph-helpers";
export interface TrueRetentionData {
youngPassed: number;
youngFailed: number;
maturePassed: number;
matureFailed: number;
}
export interface PeriodTrueRetentionData {
today: TrueRetentionData;
yesterday: TrueRetentionData;
week: TrueRetentionData;
month: TrueRetentionData;
year: TrueRetentionData;
allTime: TrueRetentionData;
}
export enum DisplayMode {
Young,
Mature,
All,
Summary,
}
export enum Scope {
Young,
Mature,
All,
}
export function getPassed(data: TrueRetentionData, scope: Scope): number {
switch (scope) {
case Scope.Young:
return data.youngPassed;
case Scope.Mature:
return data.maturePassed;
case Scope.All:
return data.youngPassed + data.maturePassed;
default:
assertUnreachable(scope);
}
}
export function getFailed(data: TrueRetentionData, scope: Scope): number {
switch (scope) {
case Scope.Young:
return data.youngFailed;
case Scope.Mature:
return data.matureFailed;
case Scope.All:
return data.youngFailed + data.matureFailed;
default:
assertUnreachable(scope);
}
}
export interface RowData {
title: string;
data: TrueRetentionData;
}
export function getRowData(
allData: PeriodTrueRetentionData,
revlogRange: RevlogRange,
): RowData[] {
const rowData: RowData[] = [
{
title: tr.statisticsTrueRetentionToday(),
data: allData.today,
},
{
title: tr.statisticsTrueRetentionYesterday(),
data: allData.yesterday,
},
{
title: tr.statisticsTrueRetentionWeek(),
data: allData.week,
},
{
title: tr.statisticsTrueRetentionMonth(),
data: allData.month,
},
{
title: tr.statisticsTrueRetentionYear(),
data: allData.year,
},
];
if (revlogRange === RevlogRange.All) {
rowData.push({
title: tr.statisticsTrueRetentionAllTime(),
data: allData.allTime,
});
}
return rowData;
}
export function calculateRetentionPercentageString(
passed: number,
failed: number,
): string {
let percentage = 0;
const total = passed + failed;
if (total !== 0) {
percentage = (passed / total) * 100;
}
return localizedNumber(percentage, 1) + "%";
}