Card States - ghrgriner/anki-stats GitHub Wiki
This page is intended as supplementary reading to the information provided in Anki Statistical Reports. It is not necessary to understand how card state is represented in the database to understand the statistical reports generated by Anki. However, once a reader understands the card type, it is only a bit more work to understand the card state. It is recommended a reader read the Anki Statistical Reports page at least through the 'Card Type' section before reading this page.
The card state is the card-specific information used in the Anki Rust backend when
answering to determine the new type of the card and the due date(time) of the next
review if a given answer button is pushed. It also contains properties (like the
leeched field in ReviewState) that are updated as a result of the review but are
not used to determine the new type or due date.
At the highest level is CardState, which is an enum
that has variants Filtered (for cards in a filtered deck) and
Normal. The Filtered variant is also an enum, and this has variants
Rescheduling and Preview, representing whether or not the filtered
deck has rescheduling enabled. The Rescheduling variant and the
Normal variant of CardState both contain a NormalState enum
with four variants indicating the card type New, Learning,
Review, and Relearning. These final 4 variants no longer
contain any more enums. They each contain a structure with the
card-specific data that will be used to update the card state.
Note that the card queue is not contained anywhere in these data
structures. We also find it interesting to observe that a
RelearnState contains both a LearnState and a ReviewState.
The code below gives the data structures defined in the Rust backend.
In Rust, an enum can have values of different types associated
with the different variants of the enum. The type of the associated
value is in parentheses after the variant name. See the
Rust tutorial
for details.
pub enum CardState {
Normal(NormalState),
Filtered(FilteredState),
}
pub enum FilteredState {
Preview(PreviewState),
Rescheduling(ReschedulingFilterState),
}
pub struct PreviewState {
pub scheduled_secs: u32,
pub finished: bool,
}
pub struct ReschedulingFilterState {
pub original_state: NormalState,
}
pub enum NormalState {
New(NewState),
Learning(LearnState),
Review(ReviewState),
Relearning(RelearnState),
}
pub struct NewState {
pub position: u32,
}
pub struct LearnState {
pub remaining_steps: u32,
pub scheduled_secs: u32,
pub elapsed_secs: u32,
pub memory_state: Option<FsrsMemoryState>,
}
pub struct ReviewState {
pub scheduled_days: u32,
pub elapsed_days: u32,
pub ease_factor: f32,
pub lapses: u32,
pub leeched: bool,
pub memory_state: Option<FsrsMemoryState>,
}
pub struct RelearnState {
pub learning: LearnState,
pub review: ReviewState,
}The non-card specific information (i.e., information defined by
the scheduler) is stored in the StateContext. This is used
with the CardState during state transitions to determine the
next state.
/// Info required during state transitions.
pub(crate) struct StateContext<'a> {
/// In range `0.0..1.0`. Used to pick the final interval from the fuzz
/// range.
pub fuzz_factor: Option<f32>,
pub fsrs_next_states: Option<NextStates>,
pub fsrs_short_term_with_steps_enabled: bool,
pub fsrs_allow_short_term: bool,
// learning
pub steps: LearningSteps<'a>,
pub graduating_interval_good: u32,
pub graduating_interval_easy: u32,
pub initial_ease_factor: f32,
// reviewing
pub hard_multiplier: f32,
pub easy_multiplier: f32,
pub interval_multiplier: f32,
pub maximum_review_interval: u32,
pub leech_threshold: u32,
pub load_balancer: Option<LoadBalancerContext<'a>>,
// relearning
pub relearn_steps: LearningSteps<'a>,
pub lapse_multiplier: f32,
pub minimum_lapse_interval: u32,
// filtered
pub in_filtered_deck: bool,
pub preview_delays: PreviewDelays,
}