2020-06-26 02:42:10 +02:00
|
|
|
// Copyright: Ankitects Pty Ltd and contributors
|
|
|
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|
|
|
|
2020-11-05 02:01:30 +01:00
|
|
|
import pb from "anki/backend_proto";
|
|
|
|
import { studiedToday } from "anki/time";
|
|
|
|
import type { I18n } from "anki/i18n";
|
2020-06-26 02:42:10 +02:00
|
|
|
|
|
|
|
export interface TodayData {
|
2020-06-27 12:31:33 +02:00
|
|
|
title: string;
|
|
|
|
lines: string[];
|
2020-06-26 02:42:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const ReviewKind = pb.BackendProto.RevlogEntry.ReviewKind;
|
|
|
|
|
2020-06-27 11:24:49 +02:00
|
|
|
export function gatherData(data: pb.BackendProto.GraphsOut, i18n: I18n): TodayData {
|
2020-06-26 02:42:10 +02:00
|
|
|
let answerCount = 0;
|
|
|
|
let answerMillis = 0;
|
|
|
|
let correctCount = 0;
|
|
|
|
let matureCorrect = 0;
|
|
|
|
let matureCount = 0;
|
|
|
|
let learnCount = 0;
|
|
|
|
let reviewCount = 0;
|
|
|
|
let relearnCount = 0;
|
|
|
|
let earlyReviewCount = 0;
|
|
|
|
|
|
|
|
const startOfTodayMillis = (data.nextDayAtSecs - 86400) * 1000;
|
|
|
|
|
|
|
|
for (const review of data.revlog as pb.BackendProto.RevlogEntry[]) {
|
|
|
|
if (review.id < startOfTodayMillis) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-09-02 09:18:29 +02:00
|
|
|
if (review.reviewKind == ReviewKind.MANUAL) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-06-26 02:42:10 +02:00
|
|
|
// total
|
|
|
|
answerCount += 1;
|
|
|
|
answerMillis += review.takenMillis;
|
|
|
|
|
|
|
|
// correct
|
|
|
|
if (review.buttonChosen > 1) {
|
|
|
|
correctCount += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// mature
|
|
|
|
if (review.lastInterval >= 21) {
|
|
|
|
matureCount += 1;
|
|
|
|
if (review.buttonChosen > 1) {
|
|
|
|
matureCorrect += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// type counts
|
|
|
|
switch (review.reviewKind) {
|
|
|
|
case ReviewKind.LEARNING:
|
|
|
|
learnCount += 1;
|
|
|
|
break;
|
|
|
|
case ReviewKind.REVIEW:
|
|
|
|
reviewCount += 1;
|
|
|
|
break;
|
|
|
|
case ReviewKind.RELEARNING:
|
|
|
|
relearnCount += 1;
|
|
|
|
break;
|
|
|
|
case ReviewKind.EARLY_REVIEW:
|
|
|
|
earlyReviewCount += 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-27 12:31:33 +02:00
|
|
|
let lines: string[];
|
|
|
|
if (answerCount) {
|
|
|
|
const studiedTodayText = studiedToday(i18n, answerCount, answerMillis / 1000);
|
|
|
|
const againCount = answerCount - correctCount;
|
2021-03-26 09:17:08 +01:00
|
|
|
let againCountText = i18n.statisticsTodayAgainCount();
|
2020-06-27 12:31:33 +02:00
|
|
|
againCountText += ` ${againCount} (${((againCount / answerCount) * 100).toFixed(
|
|
|
|
2
|
|
|
|
)}%)`;
|
2021-03-26 10:09:50 +01:00
|
|
|
const typeCounts = i18n.statisticsTodayTypeCounts({
|
2020-06-27 12:31:33 +02:00
|
|
|
learnCount,
|
|
|
|
reviewCount,
|
|
|
|
relearnCount,
|
|
|
|
filteredCount: earlyReviewCount,
|
|
|
|
});
|
|
|
|
let matureText: string;
|
|
|
|
if (matureCount) {
|
2021-03-26 10:09:50 +01:00
|
|
|
matureText = i18n.statisticsTodayCorrectMature({
|
2020-06-27 12:31:33 +02:00
|
|
|
correct: matureCorrect,
|
|
|
|
total: matureCount,
|
|
|
|
percent: (matureCorrect / matureCount) * 100,
|
|
|
|
});
|
|
|
|
} else {
|
2021-03-26 09:17:08 +01:00
|
|
|
matureText = i18n.statisticsTodayNoMatureCards();
|
2020-06-27 12:31:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
lines = [studiedTodayText, againCountText, typeCounts, matureText];
|
|
|
|
} else {
|
2021-03-26 09:17:08 +01:00
|
|
|
lines = [i18n.statisticsTodayNoCards()];
|
2020-06-27 12:31:33 +02:00
|
|
|
}
|
2020-06-27 11:24:49 +02:00
|
|
|
|
2020-06-26 02:42:10 +02:00
|
|
|
return {
|
2021-03-26 09:17:08 +01:00
|
|
|
title: i18n.statisticsTodayTitle(),
|
2020-06-27 12:31:33 +02:00
|
|
|
lines,
|
2020-06-26 02:42:10 +02:00
|
|
|
};
|
|
|
|
}
|