mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 22:12:21 -04:00
Add gatherByQueue and gatherByCtype methods
This commit is contained in:
parent
47551df2f9
commit
ecbb08e4c5
4 changed files with 82 additions and 21 deletions
|
@ -1,13 +1,15 @@
|
||||||
<script lang="typescript">
|
<script lang="typescript">
|
||||||
import { defaultGraphBounds } from "./graph-helpers";
|
import { CardCountMethod, defaultGraphBounds } from "./graph-helpers";
|
||||||
import { gatherData, renderCards } from "./card-counts";
|
import { gatherData, renderCards } from "./card-counts";
|
||||||
import type { GraphData, TableDatum } from "./card-counts";
|
import type { GraphData, TableDatum } from "./card-counts";
|
||||||
import type pb from "anki/backend_proto";
|
import type pb from "anki/backend_proto";
|
||||||
import type { I18n } from "anki/i18n";
|
import type { I18n } from "anki/i18n";
|
||||||
|
import CountMethodRadios from './CountMethodRadios.svelte';
|
||||||
|
|
||||||
export let sourceData: pb.BackendProto.GraphsOut;
|
export let sourceData: pb.BackendProto.GraphsOut;
|
||||||
export let i18n: I18n;
|
export let i18n: I18n;
|
||||||
|
|
||||||
|
let cardCountMethod = CardCountMethod.ByType;
|
||||||
let svg = null as HTMLElement | SVGElement | null;
|
let svg = null as HTMLElement | SVGElement | null;
|
||||||
|
|
||||||
let bounds = defaultGraphBounds();
|
let bounds = defaultGraphBounds();
|
||||||
|
@ -16,8 +18,9 @@
|
||||||
|
|
||||||
let graphData = (null as unknown) as GraphData;
|
let graphData = (null as unknown) as GraphData;
|
||||||
let tableData = (null as unknown) as TableDatum[];
|
let tableData = (null as unknown) as TableDatum[];
|
||||||
|
|
||||||
$: {
|
$: {
|
||||||
graphData = gatherData(sourceData, i18n);
|
graphData = gatherData(sourceData, cardCountMethod, i18n);
|
||||||
tableData = renderCards(svg as any, bounds, graphData);
|
tableData = renderCards(svg as any, bounds, graphData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,6 +55,10 @@
|
||||||
<div class="graph" id="graph-card-counts">
|
<div class="graph" id="graph-card-counts">
|
||||||
<h1>{graphData.title}</h1>
|
<h1>{graphData.title}</h1>
|
||||||
|
|
||||||
|
<div class="range-box-inner">
|
||||||
|
<CountMethodRadios bind:cardCountMethod {i18n} />
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="counts-outer">
|
<div class="counts-outer">
|
||||||
<svg
|
<svg
|
||||||
bind:this={svg}
|
bind:this={svg}
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
export let cardCountMethod: CardCountMethod;
|
export let cardCountMethod: CardCountMethod;
|
||||||
|
|
||||||
const byType = "By card type";
|
const byType = "By card type";
|
||||||
const byQueue = "By scheduling Queue";
|
const byQueue = "By scheduling queue";
|
||||||
|
const all = i18n.tr(i18n.TR.STATISTICS_RANGE_ALL_TIME);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<label>
|
<label>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
@typescript-eslint/no-explicit-any: "off",
|
@typescript-eslint/no-explicit-any: "off",
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { CardQueue } from "anki/cards";
|
import { CardQueue, CardType } from "anki/cards";
|
||||||
import type pb from "anki/backend_proto";
|
import type pb from "anki/backend_proto";
|
||||||
import { schemeGreens, schemeBlues } from "d3-scale-chromatic";
|
import { schemeGreens, schemeBlues } from "d3-scale-chromatic";
|
||||||
import "d3-transition";
|
import "d3-transition";
|
||||||
|
@ -15,6 +15,7 @@ import { scaleLinear } from "d3-scale";
|
||||||
import { pie, arc } from "d3-shape";
|
import { pie, arc } from "d3-shape";
|
||||||
import { interpolate } from "d3-interpolate";
|
import { interpolate } from "d3-interpolate";
|
||||||
import type { GraphBounds } from "./graph-helpers";
|
import type { GraphBounds } from "./graph-helpers";
|
||||||
|
import { CardCountMethod } from "./graph-helpers";
|
||||||
import { cumsum } from "d3-array";
|
import { cumsum } from "d3-array";
|
||||||
import type { I18n } from "anki/i18n";
|
import type { I18n } from "anki/i18n";
|
||||||
|
|
||||||
|
@ -25,29 +26,25 @@ export interface GraphData {
|
||||||
totalCards: number;
|
totalCards: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function gatherData(data: pb.BackendProto.GraphsOut, i18n: I18n): GraphData {
|
function gatherByQueue(cards: pb.BackendProto.ICard[], i18n: I18n): Count[] {
|
||||||
const totalCards = data.cards.length;
|
|
||||||
let newCards = 0;
|
let newCards = 0;
|
||||||
let young = 0;
|
let learn = 0;
|
||||||
let mature = 0;
|
let review = 0;
|
||||||
let suspended = 0;
|
let suspended = 0;
|
||||||
let buried = 0;
|
let buried = 0;
|
||||||
|
|
||||||
for (const card of data.cards as pb.BackendProto.Card[]) {
|
for (const card of cards as pb.BackendProto.Card[]) {
|
||||||
switch (card.queue) {
|
switch (card.queue) {
|
||||||
case CardQueue.New:
|
case CardQueue.New:
|
||||||
newCards += 1;
|
newCards += 1;
|
||||||
break;
|
break;
|
||||||
case CardQueue.Review:
|
case CardQueue.Review:
|
||||||
if (card.interval >= 21) {
|
review += 1;
|
||||||
mature += 1;
|
break
|
||||||
break;
|
|
||||||
}
|
|
||||||
// young falls through
|
|
||||||
case CardQueue.Learn:
|
case CardQueue.Learn:
|
||||||
case CardQueue.DayLearn:
|
case CardQueue.DayLearn:
|
||||||
case CardQueue.PreviewRepeat:
|
case CardQueue.PreviewRepeat:
|
||||||
young += 1;
|
learn += 1;
|
||||||
break;
|
break;
|
||||||
case CardQueue.Suspended:
|
case CardQueue.Suspended:
|
||||||
suspended += 1;
|
suspended += 1;
|
||||||
|
@ -59,14 +56,63 @@ export function gatherData(data: pb.BackendProto.GraphsOut, i18n: I18n): GraphDa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const counts = [
|
const counts: Count[] = [
|
||||||
[i18n.tr(i18n.TR.STATISTICS_COUNTS_NEW_CARDS), newCards] as Count,
|
[i18n.tr(i18n.TR.STATISTICS_COUNTS_NEW_CARDS), newCards],
|
||||||
[i18n.tr(i18n.TR.STATISTICS_COUNTS_YOUNG_CARDS), young] as Count,
|
["Learning", learn],
|
||||||
[i18n.tr(i18n.TR.STATISTICS_COUNTS_MATURE_CARDS), mature] as Count,
|
["Review", review],
|
||||||
[i18n.tr(i18n.TR.STATISTICS_COUNTS_SUSPENDED_CARDS), suspended] as Count,
|
[i18n.tr(i18n.TR.STATISTICS_COUNTS_SUSPENDED_CARDS), suspended],
|
||||||
[i18n.tr(i18n.TR.STATISTICS_COUNTS_BURIED_CARDS), buried] as Count,
|
[i18n.tr(i18n.TR.STATISTICS_COUNTS_BURIED_CARDS), buried],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
return counts;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gatherByCtype(cards: pb.BackendProto.ICard[], i18n: I18n): Count[] {
|
||||||
|
let newCards = 0;
|
||||||
|
let learn = 0;
|
||||||
|
let young = 0;
|
||||||
|
let mature = 0;
|
||||||
|
let relearn = 0;
|
||||||
|
|
||||||
|
for (const card of cards as pb.BackendProto.Card[]) {
|
||||||
|
switch (card.ctype) {
|
||||||
|
case CardType.New:
|
||||||
|
newCards += 1;
|
||||||
|
break;
|
||||||
|
case CardType.Learn:
|
||||||
|
learn += 1;
|
||||||
|
break;
|
||||||
|
case CardType.Review:
|
||||||
|
if (card.interval < 21) {
|
||||||
|
young += 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mature += 1;
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case CardType.Relearn:
|
||||||
|
relearn += 1;
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const counts: Count[] = [
|
||||||
|
[i18n.tr(i18n.TR.STATISTICS_COUNTS_NEW_CARDS), newCards],
|
||||||
|
["Learning", learn],
|
||||||
|
[i18n.tr(i18n.TR.STATISTICS_COUNTS_YOUNG_CARDS), young],
|
||||||
|
[i18n.tr(i18n.TR.STATISTICS_COUNTS_MATURE_CARDS), mature],
|
||||||
|
["Relearning", relearn],
|
||||||
|
];
|
||||||
|
|
||||||
|
return counts;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function gatherData(data: pb.BackendProto.GraphsOut, method: CardCountMethod, i18n: I18n): GraphData {
|
||||||
|
const totalCards = data.cards.length;
|
||||||
|
const counts = method === CardCountMethod.ByType
|
||||||
|
? gatherByCtype(data.cards, i18n)
|
||||||
|
: gatherByQueue(data.cards, i18n);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title: i18n.tr(i18n.TR.STATISTICS_COUNTS_TITLE),
|
title: i18n.tr(i18n.TR.STATISTICS_COUNTS_TITLE),
|
||||||
counts,
|
counts,
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
// Copyright: Ankitects Pty Ltd and contributors
|
// Copyright: Ankitects Pty Ltd and contributors
|
||||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
|
export enum CardType {
|
||||||
|
New = 0,
|
||||||
|
Learn = 1,
|
||||||
|
Review = 2,
|
||||||
|
Relearn = 3,
|
||||||
|
}
|
||||||
|
|
||||||
export enum CardQueue {
|
export enum CardQueue {
|
||||||
/// due is the order cards are shown in
|
/// due is the order cards are shown in
|
||||||
New = 0,
|
New = 0,
|
||||||
|
|
Loading…
Reference in a new issue