rs_fsrs/
models.rs

1use crate::Parameters;
2use chrono::{DateTime, Utc};
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6
7#[derive(Clone, Copy, PartialEq, Debug, Default, Eq)]
8#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9pub enum State {
10    #[default]
11    New = 0,
12    Learning = 1,
13    Review = 2,
14    Relearning = 3,
15}
16
17#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
18#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
19pub enum Rating {
20    Again = 1,
21    Hard = 2,
22    Good = 3,
23    Easy = 4,
24}
25
26impl Rating {
27    pub fn iter() -> std::slice::Iter<'static, Self> {
28        static VARIANTS: [Rating; 4] = [Rating::Again, Rating::Hard, Rating::Good, Rating::Easy];
29        VARIANTS.iter()
30    }
31}
32
33#[derive(Debug, Clone)]
34pub struct SchedulingInfo {
35    pub card: Card,
36    pub review_log: ReviewLog,
37}
38
39pub type RecordLog = HashMap<Rating, SchedulingInfo>;
40
41#[derive(Clone, Debug, PartialEq, Eq)]
42#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
43pub struct ReviewLog {
44    pub rating: Rating,
45    pub elapsed_days: i64,
46    pub scheduled_days: i64,
47    pub state: State,
48    pub reviewed_date: DateTime<Utc>,
49}
50
51#[derive(Clone, Debug, Default, PartialEq)]
52#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
53pub struct Card {
54    pub due: DateTime<Utc>,
55    pub stability: f64,
56    pub difficulty: f64,
57    pub elapsed_days: i64,
58    pub scheduled_days: i64,
59    pub reps: i32,
60    pub lapses: i32,
61    pub state: State,
62    pub last_review: DateTime<Utc>,
63}
64
65impl Card {
66    pub fn new() -> Self {
67        Self {
68            due: Utc::now(),
69            last_review: Utc::now(),
70            ..Default::default()
71        }
72    }
73
74    pub fn get_retrievability(&self, now: DateTime<Utc>) -> f64 {
75        match self.state {
76            State::New => 0.0,
77            _ => {
78                let elapsed_days = now.signed_duration_since(self.last_review).num_days();
79                Parameters::forgetting_curve(elapsed_days as f64, self.stability)
80            }
81        }
82    }
83}