mirror of
https://github.com/ankitects/anki.git
synced 2025-09-24 08:46:37 -04:00
add timeSpan()
This commit is contained in:
parent
93ab3b4164
commit
8e118bbc76
6 changed files with 104 additions and 27 deletions
|
@ -1,10 +1,13 @@
|
|||
<script lang="typescript">
|
||||
import { timeSpan, MONTH, YEAR } from "../time";
|
||||
import { I18n } from "../i18n";
|
||||
import { HistogramData } from "./histogram-graph";
|
||||
import { gatherData, buildHistogram, GraphData, AddedRange } from "./added";
|
||||
import pb from "../backend/proto";
|
||||
import HistogramGraph from "./HistogramGraph.svelte";
|
||||
|
||||
export let sourceData: pb.BackendProto.GraphsOut | null = null;
|
||||
export let i18n: I18n;
|
||||
|
||||
let svg = null as HTMLElement | SVGElement | null;
|
||||
let histogramData = null as HistogramData | null;
|
||||
|
@ -20,6 +23,10 @@
|
|||
console.log("preparing data");
|
||||
histogramData = buildHistogram(addedData, range);
|
||||
}
|
||||
|
||||
const month = timeSpan(i18n, 1 * MONTH);
|
||||
const month3 = timeSpan(i18n, 3 * MONTH);
|
||||
const year = timeSpan(i18n, 1 * YEAR);
|
||||
</script>
|
||||
|
||||
{#if histogramData}
|
||||
|
@ -29,15 +36,15 @@
|
|||
<div class="range-box-inner">
|
||||
<label>
|
||||
<input type="radio" bind:group={range} value={AddedRange.Month} />
|
||||
Month
|
||||
{month}
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" bind:group={range} value={AddedRange.Quarter} />
|
||||
3 months
|
||||
{month3}
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" bind:group={range} value={AddedRange.Year} />
|
||||
Year
|
||||
{year}
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" bind:group={range} value={AddedRange.AllTime} />
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
<script lang="typescript">
|
||||
import { timeSpan, MONTH, YEAR } from "../time";
|
||||
import { I18n } from "../i18n";
|
||||
import { HistogramData } from "./histogram-graph";
|
||||
import { defaultGraphBounds } from "./graphs";
|
||||
import {
|
||||
|
@ -12,6 +14,8 @@
|
|||
import HistogramGraph from "./HistogramGraph.svelte";
|
||||
|
||||
export let sourceData: pb.BackendProto.GraphsOut | null = null;
|
||||
export let i18n: I18n;
|
||||
|
||||
let graphData = null as GraphData | null;
|
||||
let histogramData = null as HistogramData | null;
|
||||
|
||||
|
@ -27,6 +31,10 @@
|
|||
console.log("preparing data");
|
||||
histogramData = buildHistogram(graphData, range);
|
||||
}
|
||||
|
||||
const month = timeSpan(i18n, 1 * MONTH);
|
||||
const month3 = timeSpan(i18n, 3 * MONTH);
|
||||
const year = timeSpan(i18n, 1 * YEAR);
|
||||
</script>
|
||||
|
||||
{#if histogramData}
|
||||
|
@ -37,15 +45,15 @@
|
|||
<div class="range-box-inner">
|
||||
<label>
|
||||
<input type="radio" bind:group={range} value={FutureDueRange.Month} />
|
||||
Month
|
||||
{month}
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" bind:group={range} value={FutureDueRange.Quarter} />
|
||||
3 months
|
||||
{month3}
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" bind:group={range} value={FutureDueRange.Year} />
|
||||
Year
|
||||
{year}
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" bind:group={range} value={FutureDueRange.AllTime} />
|
||||
|
|
|
@ -3,8 +3,9 @@
|
|||
</script>
|
||||
|
||||
<script lang="typescript">
|
||||
import { assertUnreachable } from "../typing";
|
||||
import { timeSpan, MONTH, YEAR } from "../time";
|
||||
import { I18n } from "../i18n";
|
||||
import { assertUnreachable } from "../typing";
|
||||
import pb from "../backend/proto";
|
||||
import { getGraphData, RevlogRange } from "./graphs";
|
||||
import IntervalsGraph from "./IntervalsGraph.svelte";
|
||||
|
@ -81,6 +82,9 @@
|
|||
search = displayedSearch;
|
||||
}
|
||||
};
|
||||
|
||||
const month = timeSpan(i18n, 1 * MONTH);
|
||||
const year = timeSpan(i18n, 1 * YEAR);
|
||||
</script>
|
||||
|
||||
<div class="range-box">
|
||||
|
@ -113,11 +117,11 @@
|
|||
Review history:
|
||||
<label>
|
||||
<input type="radio" bind:group={revlogRange} value={RevlogRange.Month} />
|
||||
Month
|
||||
{month}
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" bind:group={revlogRange} value={RevlogRange.Year} />
|
||||
Year
|
||||
{year}
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" bind:group={revlogRange} value={RevlogRange.All} />
|
||||
|
@ -129,10 +133,10 @@
|
|||
|
||||
<TodayStats {sourceData} {i18n} />
|
||||
<CardCounts {sourceData} {i18n} />
|
||||
<FutureDue {sourceData} />
|
||||
<ReviewsGraph {sourceData} {revlogRange} />
|
||||
<IntervalsGraph {sourceData} />
|
||||
<FutureDue {sourceData} {i18n} />
|
||||
<ReviewsGraph {sourceData} {revlogRange} {i18n} />
|
||||
<IntervalsGraph {sourceData} {i18n} />
|
||||
<EaseGraph {sourceData} />
|
||||
<ButtonsGraph {sourceData} />
|
||||
<HourGraph {sourceData} />
|
||||
<AddedGraph {sourceData} />
|
||||
<AddedGraph {sourceData} {i18n} />
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
<script lang="typescript">
|
||||
import { timeSpan, MONTH, YEAR } from "../time";
|
||||
import { I18n } from "../i18n";
|
||||
import { HistogramData } from "./histogram-graph";
|
||||
import {
|
||||
gatherIntervalData,
|
||||
|
@ -10,13 +12,14 @@
|
|||
import HistogramGraph from "./HistogramGraph.svelte";
|
||||
|
||||
export let sourceData: pb.BackendProto.GraphsOut | null = null;
|
||||
export let i18n: I18n;
|
||||
|
||||
let intervalData: IntervalGraphData | null = null;
|
||||
let histogramData = null as HistogramData | null;
|
||||
|
||||
let svg = null as HTMLElement | SVGElement | null;
|
||||
let range = IntervalRange.Percentile95;
|
||||
|
||||
|
||||
$: if (sourceData) {
|
||||
console.log("gathering data");
|
||||
intervalData = gatherIntervalData(sourceData);
|
||||
|
@ -26,6 +29,8 @@
|
|||
console.log("preparing data");
|
||||
histogramData = prepareIntervalData(intervalData, range);
|
||||
}
|
||||
|
||||
const month = timeSpan(i18n, 1 * MONTH);
|
||||
</script>
|
||||
|
||||
{#if histogramData}
|
||||
|
@ -35,28 +40,28 @@
|
|||
<div class="range-box-inner">
|
||||
<label>
|
||||
<input type="radio" bind:group={range} value={IntervalRange.Month} />
|
||||
Month
|
||||
{month}
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
bind:group={range}
|
||||
value={IntervalRange.Percentile50} />
|
||||
50th percentile
|
||||
50%
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
bind:group={range}
|
||||
value={IntervalRange.Percentile95} />
|
||||
95th percentile
|
||||
95%
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
bind:group={range}
|
||||
value={IntervalRange.Percentile999} />
|
||||
99.9th percentile
|
||||
99.9%
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" bind:group={range} value={IntervalRange.All} />
|
||||
|
|
|
@ -5,9 +5,12 @@
|
|||
import { defaultGraphBounds, RevlogRange } from "./graphs";
|
||||
import { GraphData, gatherData, renderReviews, ReviewRange } from "./reviews";
|
||||
import pb from "../backend/proto";
|
||||
import { timeSpan, MONTH, YEAR } from "../time";
|
||||
import { I18n } from "../i18n";
|
||||
|
||||
export let sourceData: pb.BackendProto.GraphsOut | null = null;
|
||||
export let revlogRange: RevlogRange = RevlogRange.Month;
|
||||
export let i18n: I18n;
|
||||
|
||||
let graphData: GraphData | null = null;
|
||||
|
||||
|
@ -39,6 +42,10 @@
|
|||
$: if (graphData) {
|
||||
renderReviews(svg as SVGElement, bounds, graphData, range, showTime);
|
||||
}
|
||||
|
||||
const month = timeSpan(i18n, 1 * MONTH);
|
||||
const month3 = timeSpan(i18n, 3 * MONTH);
|
||||
const year = timeSpan(i18n, 1 * YEAR);
|
||||
</script>
|
||||
|
||||
<div class="graph">
|
||||
|
@ -53,15 +60,15 @@
|
|||
{#if revlogRange >= RevlogRange.Year}
|
||||
<label>
|
||||
<input type="radio" bind:group={range} value={ReviewRange.Month} />
|
||||
Month
|
||||
{month}
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" bind:group={range} value={ReviewRange.Quarter} />
|
||||
3 months
|
||||
{month3}
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" bind:group={range} value={ReviewRange.Year} />
|
||||
Year
|
||||
{year}
|
||||
</label>
|
||||
{/if}
|
||||
{#if revlogRange === RevlogRange.All}
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
|
||||
import { I18n } from "./i18n";
|
||||
|
||||
const SECOND = 1.0;
|
||||
const MINUTE = 60.0 * SECOND;
|
||||
const HOUR = 60.0 * MINUTE;
|
||||
const DAY = 24.0 * HOUR;
|
||||
const MONTH = 30.0 * DAY;
|
||||
const YEAR = 12.0 * MONTH;
|
||||
export const SECOND = 1.0;
|
||||
export const MINUTE = 60.0 * SECOND;
|
||||
export const HOUR = 60.0 * MINUTE;
|
||||
export const DAY = 24.0 * HOUR;
|
||||
export const MONTH = 30.0 * DAY;
|
||||
export const YEAR = 12.0 * MONTH;
|
||||
|
||||
enum TimespanUnit {
|
||||
Seconds,
|
||||
|
@ -70,6 +70,15 @@ function unitAmount(unit: TimespanUnit, secs: number): number {
|
|||
}
|
||||
}
|
||||
|
||||
function unitAmountRounded(unit: TimespanUnit, secs: number): number {
|
||||
const value = unitAmount(unit, secs);
|
||||
if (unit === TimespanUnit.Seconds || unit === TimespanUnit.Days) {
|
||||
return Math.round(value);
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
export function studiedToday(i18n: I18n, cards: number, secs: number): string {
|
||||
const unit = naturalUnit(secs);
|
||||
const amount = unitAmount(unit, secs);
|
||||
|
@ -86,3 +95,40 @@ export function studiedToday(i18n: I18n, cards: number, secs: number): string {
|
|||
"secs-per-card": secsPer,
|
||||
});
|
||||
}
|
||||
|
||||
/// Describe the given seconds using the largest appropriate unit.
|
||||
/// If precise is true, show to two decimal places, eg
|
||||
/// eg 70 seconds -> "1.17 minutes"
|
||||
/// If false, seconds and days are shown without decimals.
|
||||
export function timeSpan(i18n: I18n, seconds: number, precise = true): string {
|
||||
const unit = naturalUnit(seconds);
|
||||
let amount: number;
|
||||
if (precise) {
|
||||
amount = unitAmount(unit, seconds);
|
||||
} else {
|
||||
amount = unitAmountRounded(unit, seconds);
|
||||
}
|
||||
let key: number;
|
||||
switch (unit) {
|
||||
case TimespanUnit.Seconds:
|
||||
key = i18n.TR.SCHEDULING_TIME_SPAN_SECONDS;
|
||||
break;
|
||||
case TimespanUnit.Minutes:
|
||||
key = i18n.TR.SCHEDULING_TIME_SPAN_MINUTES;
|
||||
break;
|
||||
case TimespanUnit.Hours:
|
||||
key = i18n.TR.SCHEDULING_TIME_SPAN_HOURS;
|
||||
break;
|
||||
case TimespanUnit.Days:
|
||||
key = i18n.TR.SCHEDULING_TIME_SPAN_DAYS;
|
||||
break;
|
||||
case TimespanUnit.Months:
|
||||
key = i18n.TR.SCHEDULING_TIME_SPAN_MONTHS;
|
||||
break;
|
||||
case TimespanUnit.Years:
|
||||
key = i18n.TR.SCHEDULING_TIME_SPAN_YEARS;
|
||||
break;
|
||||
}
|
||||
|
||||
return i18n.tr(key, { amount });
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue