mirror of
https://github.com/ankitects/anki.git
synced 2025-09-19 06:22:22 -04:00
Limit study time to hours in reviews graph (#4086)
* Add maxUnit argument to naturalUnit * Limit study time to hours in reviews graph Relevant discussions: - https://forums.ankiweb.net/t/reviews-graph-units-of-total-time-studied-suggestion/61237 - https://forums.ankiweb.net/t/why-does-anki-display-study-time-in-months/37722 - https://forums.ankiweb.net/t/poll-use-hours-in-total-time-stats/62076 - https://github.com/ankitects/anki/pull/3901#issuecomment-2973161601 * Use the new approach for native stability in Card Info * Use a simpler approach
This commit is contained in:
parent
4040a3c1f9
commit
44f3bbbbc9
3 changed files with 19 additions and 9 deletions
|
@ -7,8 +7,8 @@ export const SECOND = 1.0;
|
||||||
export const MINUTE = 60.0 * SECOND;
|
export const MINUTE = 60.0 * SECOND;
|
||||||
export const HOUR = 60.0 * MINUTE;
|
export const HOUR = 60.0 * MINUTE;
|
||||||
export const DAY = 24.0 * HOUR;
|
export const DAY = 24.0 * HOUR;
|
||||||
export const MONTH = 30.417 * DAY; // 365/12 ≈ 30.417
|
|
||||||
export const YEAR = 365.0 * DAY;
|
export const YEAR = 365.0 * DAY;
|
||||||
|
export const MONTH = YEAR / 12;
|
||||||
|
|
||||||
export enum TimespanUnit {
|
export enum TimespanUnit {
|
||||||
Seconds,
|
Seconds,
|
||||||
|
@ -146,8 +146,13 @@ function i18nFuncForUnit(
|
||||||
If precise is true, show to two decimal places, eg
|
If precise is true, show to two decimal places, eg
|
||||||
eg 70 seconds -> "1.17 minutes"
|
eg 70 seconds -> "1.17 minutes"
|
||||||
If false, seconds and days are shown without decimals. */
|
If false, seconds and days are shown without decimals. */
|
||||||
export function timeSpan(seconds: number, short = false, precise = true): string {
|
export function timeSpan(
|
||||||
const unit = naturalUnit(seconds);
|
seconds: number,
|
||||||
|
short = false,
|
||||||
|
precise = true,
|
||||||
|
maxUnit: TimespanUnit = TimespanUnit.Years,
|
||||||
|
): string {
|
||||||
|
const unit = Math.min(naturalUnit(seconds), maxUnit);
|
||||||
let amount = unitAmount(unit, seconds);
|
let amount = unitAmount(unit, seconds);
|
||||||
if (!precise && unit < TimespanUnit.Months) {
|
if (!precise && unit < TimespanUnit.Months) {
|
||||||
amount = Math.round(amount);
|
amount = Math.round(amount);
|
||||||
|
|
|
@ -5,7 +5,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { CardStatsResponse } from "@generated/anki/stats_pb";
|
import type { CardStatsResponse } from "@generated/anki/stats_pb";
|
||||||
import * as tr2 from "@generated/ftl";
|
import * as tr2 from "@generated/ftl";
|
||||||
import { DAY, timeSpan, Timestamp } from "@tslib/time";
|
import { DAY, timeSpan, TimespanUnit, Timestamp } from "@tslib/time";
|
||||||
|
|
||||||
export let stats: CardStatsResponse;
|
export let stats: CardStatsResponse;
|
||||||
|
|
||||||
|
@ -58,7 +58,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
if (stats.memoryState) {
|
if (stats.memoryState) {
|
||||||
let stability = timeSpan(stats.memoryState.stability * 86400, false, false);
|
let stability = timeSpan(stats.memoryState.stability * 86400, false, false);
|
||||||
if (stats.memoryState.stability > 31) {
|
if (stats.memoryState.stability > 31) {
|
||||||
const nativeStability = stats.memoryState.stability.toFixed(0);
|
const nativeStability = timeSpan(
|
||||||
|
stats.memoryState.stability * 86400,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
TimespanUnit.Days,
|
||||||
|
);
|
||||||
stability += ` (${nativeStability})`;
|
stability += ` (${nativeStability})`;
|
||||||
}
|
}
|
||||||
statsRows.push({
|
statsRows.push({
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
import type { GraphsResponse } from "@generated/anki/stats_pb";
|
import type { GraphsResponse } from "@generated/anki/stats_pb";
|
||||||
import * as tr from "@generated/ftl";
|
import * as tr from "@generated/ftl";
|
||||||
import { localizedNumber } from "@tslib/i18n";
|
import { localizedNumber } from "@tslib/i18n";
|
||||||
import { dayLabel, timeSpan } from "@tslib/time";
|
import { dayLabel, timeSpan, TimespanUnit } from "@tslib/time";
|
||||||
import type { Bin, ScaleSequential } from "d3";
|
import type { Bin, ScaleSequential } from "d3";
|
||||||
import {
|
import {
|
||||||
area,
|
area,
|
||||||
|
@ -141,7 +141,7 @@ export function renderReviews(
|
||||||
|
|
||||||
const yTickFormat = (n: number): string => {
|
const yTickFormat = (n: number): string => {
|
||||||
if (showTime) {
|
if (showTime) {
|
||||||
return timeSpan(n / 1000, true);
|
return timeSpan(n / 1000, true, false, TimespanUnit.Hours);
|
||||||
} else {
|
} else {
|
||||||
if (Math.round(n) != n) {
|
if (Math.round(n) != n) {
|
||||||
return "";
|
return "";
|
||||||
|
@ -205,7 +205,7 @@ export function renderReviews(
|
||||||
|
|
||||||
function valueLabel(n: number): string {
|
function valueLabel(n: number): string {
|
||||||
if (showTime) {
|
if (showTime) {
|
||||||
return timeSpan(n / 1000);
|
return timeSpan(n / 1000, false, true, TimespanUnit.Hours);
|
||||||
} else {
|
} else {
|
||||||
return tr.statisticsReviews({ reviews: n });
|
return tr.statisticsReviews({ reviews: n });
|
||||||
}
|
}
|
||||||
|
@ -340,7 +340,7 @@ export function renderReviews(
|
||||||
averageAnswerTime: string,
|
averageAnswerTime: string,
|
||||||
averageAnswerTimeLabel: string;
|
averageAnswerTimeLabel: string;
|
||||||
if (showTime) {
|
if (showTime) {
|
||||||
totalString = timeSpan(total / 1000, false);
|
totalString = timeSpan(total / 1000, false, true, TimespanUnit.Hours);
|
||||||
averageForDaysStudied = tr.statisticsMinutesPerDay({
|
averageForDaysStudied = tr.statisticsMinutesPerDay({
|
||||||
count: Math.round(studiedAvg / 1000 / 60),
|
count: Math.round(studiedAvg / 1000 / 60),
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue