mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00
filtered decks w/ scheduling disabled in v3 now log reviews
This commit is contained in:
parent
8830d33826
commit
48c121e4f3
18 changed files with 58 additions and 55 deletions
|
@ -83,7 +83,7 @@ statistics-counts-young-cards = Young
|
|||
statistics-counts-mature-cards = Mature
|
||||
statistics-counts-suspended-cards = Suspended
|
||||
statistics-counts-buried-cards = Buried
|
||||
statistics-counts-early-cards = Early
|
||||
statistics-counts-filtered-cards = Filtered
|
||||
statistics-counts-learning-cards = Learning
|
||||
statistics-counts-relearning-cards = Relearning
|
||||
statistics-counts-title = Card Counts
|
||||
|
|
|
@ -49,7 +49,8 @@ message RevlogEntry {
|
|||
LEARNING = 0;
|
||||
REVIEW = 1;
|
||||
RELEARNING = 2;
|
||||
EARLY_REVIEW = 3;
|
||||
// Recent Anki versions only use this when rescheduling disabled
|
||||
FILTERED = 3;
|
||||
MANUAL = 4;
|
||||
}
|
||||
int64 id = 1;
|
||||
|
|
|
@ -63,9 +63,11 @@ pub enum RevlogReviewKind {
|
|||
Learning = 0,
|
||||
Review = 1,
|
||||
Relearning = 2,
|
||||
EarlyReview = 3,
|
||||
/// Old Anki versions called this "Cram" or "Early", and assigned it when
|
||||
/// reviewing cards ahead. It is now only used for filtered decks with
|
||||
/// rescheduling disabled.
|
||||
Filtered = 3,
|
||||
Manual = 4,
|
||||
// Preview = 5,
|
||||
}
|
||||
|
||||
impl Default for RevlogReviewKind {
|
||||
|
|
|
@ -15,19 +15,19 @@ impl CardStateUpdater {
|
|||
&mut self,
|
||||
current: CardState,
|
||||
next: NewState,
|
||||
) -> Option<RevlogEntryPartial> {
|
||||
) -> RevlogEntryPartial {
|
||||
self.card.ctype = CardType::New;
|
||||
self.card.queue = CardQueue::New;
|
||||
self.card.due = next.position as i32;
|
||||
|
||||
RevlogEntryPartial::maybe_new(current, next.into(), 0.0, self.secs_until_rollover())
|
||||
RevlogEntryPartial::new(current, next.into(), 0.0, self.secs_until_rollover())
|
||||
}
|
||||
|
||||
pub(super) fn apply_learning_state(
|
||||
&mut self,
|
||||
current: CardState,
|
||||
next: LearnState,
|
||||
) -> Option<RevlogEntryPartial> {
|
||||
) -> RevlogEntryPartial {
|
||||
self.card.remaining_steps = next.remaining_steps;
|
||||
self.card.ctype = CardType::Learn;
|
||||
|
||||
|
@ -45,7 +45,7 @@ impl CardStateUpdater {
|
|||
}
|
||||
}
|
||||
|
||||
RevlogEntryPartial::maybe_new(current, next.into(), 0.0, self.secs_until_rollover())
|
||||
RevlogEntryPartial::new(current, next.into(), 0.0, self.secs_until_rollover())
|
||||
}
|
||||
|
||||
/// Adds secs + fuzz to current time
|
||||
|
|
|
@ -42,8 +42,6 @@ pub struct CardAnswer {
|
|||
pub milliseconds_taken: u32,
|
||||
}
|
||||
|
||||
// fixme: log preview review
|
||||
|
||||
/// Holds the information required to determine a given card's
|
||||
/// current state, and to apply a state change to it.
|
||||
struct CardStateUpdater {
|
||||
|
@ -103,7 +101,7 @@ impl CardStateUpdater {
|
|||
&mut self,
|
||||
current: CardState,
|
||||
next: CardState,
|
||||
) -> Result<Option<RevlogEntryPartial>> {
|
||||
) -> Result<RevlogEntryPartial> {
|
||||
let revlog = match next {
|
||||
CardState::Normal(normal) => {
|
||||
// transitioning from filtered state?
|
||||
|
@ -141,7 +139,7 @@ impl CardStateUpdater {
|
|||
&mut self,
|
||||
current: CardState,
|
||||
next: NormalState,
|
||||
) -> Option<RevlogEntryPartial> {
|
||||
) -> RevlogEntryPartial {
|
||||
self.card.reps += 1;
|
||||
self.card.original_due = 0;
|
||||
|
||||
|
@ -259,9 +257,9 @@ impl Collection {
|
|||
current_state, answer.current_state,
|
||||
)));
|
||||
}
|
||||
if let Some(revlog_partial) = updater.apply_study_state(current_state, answer.new_state)? {
|
||||
self.add_partial_revlog(revlog_partial, usn, answer)?;
|
||||
}
|
||||
let revlog_partial = updater.apply_study_state(current_state, answer.new_state)?;
|
||||
self.add_partial_revlog(revlog_partial, usn, answer)?;
|
||||
|
||||
self.update_deck_stats_from_answer(usn, answer, &updater, original.queue)?;
|
||||
self.maybe_bury_siblings(&original, &updater.config)?;
|
||||
let timing = updater.timing;
|
||||
|
|
|
@ -9,17 +9,16 @@ use crate::{
|
|||
};
|
||||
|
||||
impl CardStateUpdater {
|
||||
// fixme: check learning card moved into preview
|
||||
// restores correctly in both learn and day-learn case
|
||||
pub(super) fn apply_preview_state(
|
||||
&mut self,
|
||||
current: CardState,
|
||||
next: PreviewState,
|
||||
) -> Option<RevlogEntryPartial> {
|
||||
) -> RevlogEntryPartial {
|
||||
let revlog = RevlogEntryPartial::new(current, next.into(), 0.0, self.secs_until_rollover());
|
||||
if next.finished {
|
||||
self.card
|
||||
.remove_from_filtered_deck_restoring_queue(SchedulerVersion::V2);
|
||||
return None;
|
||||
return revlog;
|
||||
}
|
||||
|
||||
self.card.queue = CardQueue::PreviewRepeat;
|
||||
|
@ -34,7 +33,7 @@ impl CardStateUpdater {
|
|||
}
|
||||
}
|
||||
|
||||
RevlogEntryPartial::maybe_new(current, next.into(), 0.0, self.secs_until_rollover())
|
||||
revlog
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ impl CardStateUpdater {
|
|||
&mut self,
|
||||
current: CardState,
|
||||
next: RelearnState,
|
||||
) -> Option<RevlogEntryPartial> {
|
||||
) -> RevlogEntryPartial {
|
||||
self.card.interval = next.review.scheduled_days;
|
||||
self.card.remaining_steps = next.learning.remaining_steps;
|
||||
self.card.ctype = CardType::Relearn;
|
||||
|
@ -33,7 +33,7 @@ impl CardStateUpdater {
|
|||
}
|
||||
}
|
||||
|
||||
RevlogEntryPartial::maybe_new(
|
||||
RevlogEntryPartial::new(
|
||||
current,
|
||||
next.into(),
|
||||
next.review.ease_factor,
|
||||
|
|
|
@ -12,7 +12,7 @@ impl CardStateUpdater {
|
|||
&mut self,
|
||||
current: CardState,
|
||||
next: ReviewState,
|
||||
) -> Option<RevlogEntryPartial> {
|
||||
) -> RevlogEntryPartial {
|
||||
self.card.queue = CardQueue::Review;
|
||||
self.card.ctype = CardType::Review;
|
||||
self.card.interval = next.scheduled_days;
|
||||
|
@ -21,7 +21,7 @@ impl CardStateUpdater {
|
|||
self.card.lapses = next.lapses;
|
||||
self.card.remaining_steps = 0;
|
||||
|
||||
RevlogEntryPartial::maybe_new(
|
||||
RevlogEntryPartial::new(
|
||||
current,
|
||||
next.into(),
|
||||
next.ease_factor,
|
||||
|
|
|
@ -15,24 +15,21 @@ pub struct RevlogEntryPartial {
|
|||
}
|
||||
|
||||
impl RevlogEntryPartial {
|
||||
/// Returns None in the Preview case, since preview cards do not currently log.
|
||||
pub(super) fn maybe_new(
|
||||
pub(super) fn new(
|
||||
current: CardState,
|
||||
next: CardState,
|
||||
ease_factor: f32,
|
||||
secs_until_rollover: u32,
|
||||
) -> Option<Self> {
|
||||
current.revlog_kind().map(|review_kind| {
|
||||
let next_interval = next.interval_kind().maybe_as_days(secs_until_rollover);
|
||||
let current_interval = current.interval_kind().maybe_as_days(secs_until_rollover);
|
||||
) -> Self {
|
||||
let next_interval = next.interval_kind().maybe_as_days(secs_until_rollover);
|
||||
let current_interval = current.interval_kind().maybe_as_days(secs_until_rollover);
|
||||
|
||||
RevlogEntryPartial {
|
||||
interval: next_interval,
|
||||
last_interval: current_interval,
|
||||
ease_factor,
|
||||
review_kind,
|
||||
}
|
||||
})
|
||||
RevlogEntryPartial {
|
||||
interval: next_interval,
|
||||
last_interval: current_interval,
|
||||
ease_factor,
|
||||
review_kind: current.revlog_kind(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn into_revlog_entry(
|
||||
|
|
|
@ -20,10 +20,10 @@ impl FilteredState {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn revlog_kind(self) -> Option<RevlogReviewKind> {
|
||||
pub(crate) fn revlog_kind(self) -> RevlogReviewKind {
|
||||
match self {
|
||||
FilteredState::Preview(_state) => None,
|
||||
FilteredState::Rescheduling(state) => Some(state.revlog_kind()),
|
||||
FilteredState::Preview(state) => state.revlog_kind(),
|
||||
FilteredState::Rescheduling(state) => state.revlog_kind(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,9 +40,9 @@ impl CardState {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn revlog_kind(self) -> Option<RevlogReviewKind> {
|
||||
pub(crate) fn revlog_kind(self) -> RevlogReviewKind {
|
||||
match self {
|
||||
CardState::Normal(normal) => Some(normal.revlog_kind()),
|
||||
CardState::Normal(normal) => normal.revlog_kind(),
|
||||
CardState::Filtered(filtered) => filtered.revlog_kind(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
use super::{IntervalKind, NextCardStates, StateContext};
|
||||
use crate::revlog::RevlogReviewKind;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct PreviewState {
|
||||
|
@ -14,6 +15,10 @@ impl PreviewState {
|
|||
IntervalKind::InSecs(self.scheduled_secs)
|
||||
}
|
||||
|
||||
pub(crate) fn revlog_kind(self) -> RevlogReviewKind {
|
||||
RevlogReviewKind::Filtered
|
||||
}
|
||||
|
||||
pub(crate) fn next_states(self, ctx: &StateContext) -> NextCardStates {
|
||||
NextCardStates {
|
||||
current: self.into(),
|
||||
|
|
|
@ -46,7 +46,7 @@ impl ReviewState {
|
|||
|
||||
pub(crate) fn revlog_kind(self) -> RevlogReviewKind {
|
||||
if self.days_late() < 0 {
|
||||
RevlogReviewKind::EarlyReview
|
||||
RevlogReviewKind::Filtered
|
||||
} else {
|
||||
RevlogReviewKind::Review
|
||||
}
|
||||
|
|
|
@ -213,14 +213,14 @@ fn revlog_to_text(e: RevlogEntry, tr: &I18n) -> RevlogText {
|
|||
RevlogReviewKind::Learning => tr.card_stats_review_log_type_learn().into(),
|
||||
RevlogReviewKind::Review => tr.card_stats_review_log_type_review().into(),
|
||||
RevlogReviewKind::Relearning => tr.card_stats_review_log_type_relearn().into(),
|
||||
RevlogReviewKind::EarlyReview => tr.card_stats_review_log_type_filtered().into(),
|
||||
RevlogReviewKind::Filtered => tr.card_stats_review_log_type_filtered().into(),
|
||||
RevlogReviewKind::Manual => tr.card_stats_review_log_type_manual().into(),
|
||||
};
|
||||
let kind_class = match e.review_kind {
|
||||
RevlogReviewKind::Learning => String::from("revlog-learn"),
|
||||
RevlogReviewKind::Review => String::from("revlog-review"),
|
||||
RevlogReviewKind::Relearning => String::from("revlog-relearn"),
|
||||
RevlogReviewKind::EarlyReview => String::from("revlog-filtered"),
|
||||
RevlogReviewKind::Filtered => String::from("revlog-filtered"),
|
||||
RevlogReviewKind::Manual => String::from("revlog-manual"),
|
||||
};
|
||||
let rating = e.button_chosen.to_string();
|
||||
|
|
|
@ -65,13 +65,14 @@ export function gatherData(data: Stats.GraphsResponse, range: GraphRange): Graph
|
|||
break;
|
||||
|
||||
case ReviewKind.REVIEW:
|
||||
case ReviewKind.EARLY_REVIEW:
|
||||
if (review.lastInterval < 21) {
|
||||
buttons = young;
|
||||
} else {
|
||||
buttons = mature;
|
||||
}
|
||||
break;
|
||||
case ReviewKind.FILTERED:
|
||||
break;
|
||||
}
|
||||
|
||||
buttons[buttonNum - 1] += 1;
|
||||
|
|
|
@ -51,7 +51,7 @@ function gatherData(data: Stats.GraphsResponse, range: GraphRange): Hour[] {
|
|||
case ReviewKind.REVIEW:
|
||||
case ReviewKind.RELEARNING:
|
||||
break; // from switch
|
||||
case ReviewKind.EARLY_REVIEW:
|
||||
case ReviewKind.FILTERED:
|
||||
case ReviewKind.MANUAL:
|
||||
continue; // next loop iteration
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ interface Reviews {
|
|||
relearn: number;
|
||||
young: number;
|
||||
mature: number;
|
||||
early: number;
|
||||
filtered: number;
|
||||
}
|
||||
|
||||
export interface GraphData {
|
||||
|
@ -56,7 +56,7 @@ type BinType = Bin<Map<number, Reviews[]>, number>;
|
|||
export function gatherData(data: Stats.GraphsResponse): GraphData {
|
||||
const reviewCount = new Map<number, Reviews>();
|
||||
const reviewTime = new Map<number, Reviews>();
|
||||
const empty = { mature: 0, young: 0, learn: 0, relearn: 0, early: 0 };
|
||||
const empty = { mature: 0, young: 0, learn: 0, relearn: 0, filtered: 0 };
|
||||
|
||||
for (const review of data.revlog as Stats.RevlogEntry[]) {
|
||||
if (review.reviewKind == ReviewKind.MANUAL) {
|
||||
|
@ -89,9 +89,9 @@ export function gatherData(data: Stats.GraphsResponse): GraphData {
|
|||
timeEntry.mature += review.takenMillis;
|
||||
}
|
||||
break;
|
||||
case ReviewKind.EARLY_REVIEW:
|
||||
countEntry.early += 1;
|
||||
timeEntry.early += review.takenMillis;
|
||||
case ReviewKind.FILTERED:
|
||||
countEntry.filtered += 1;
|
||||
timeEntry.filtered += review.takenMillis;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ function totalsForBin(bin: BinType): number[] {
|
|||
total[1] += entry[1].relearn;
|
||||
total[2] += entry[1].young;
|
||||
total[3] += entry[1].mature;
|
||||
total[4] += entry[1].early;
|
||||
total[4] += entry[1].filtered;
|
||||
}
|
||||
|
||||
return total;
|
||||
|
@ -246,7 +246,7 @@ export function renderReviews(
|
|||
[reds(1), tr.statisticsCountsRelearningCards(), valueLabel(totals[1])],
|
||||
[lighterGreens(1), tr.statisticsCountsYoungCards(), valueLabel(totals[2])],
|
||||
[darkerGreens(1), tr.statisticsCountsMatureCards(), valueLabel(totals[3])],
|
||||
[purples(1), tr.statisticsCountsEarlyCards(), valueLabel(totals[4])],
|
||||
[purples(1), tr.statisticsCountsFilteredCards(), valueLabel(totals[4])],
|
||||
["transparent", tr.statisticsRunningTotal(), valueLabel(cumulative)],
|
||||
];
|
||||
for (const [colour, label, detail] of lines) {
|
||||
|
|
|
@ -63,7 +63,7 @@ export function gatherData(data: Stats.GraphsResponse): TodayData {
|
|||
case ReviewKind.RELEARNING:
|
||||
relearnCount += 1;
|
||||
break;
|
||||
case ReviewKind.EARLY_REVIEW:
|
||||
case ReviewKind.FILTERED:
|
||||
earlyReviewCount += 1;
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue