use chrono::{DateTime, Duration, Utc};
use fsrs::{FSRS, MemoryState};
struct Card {
due: DateTime<Utc>,
memory_state: Option<MemoryState>,
scheduled_days: u32,
last_review: Option<DateTime<Utc>>,
}
impl Card {
pub fn new() -> Self {
Self {
due: Utc::now(),
last_review: None,
memory_state: None,
scheduled_days: 0,
}
}
}
fn schedule_new_card() -> Result<(), Box<dyn std::error::Error>> {
let mut card = Card::new();
let desired_retention = 0.9;
let fsrs = FSRS::new(Some(&[]))?;
let next_states = fsrs.next_states(card.memory_state, desired_retention, 0)?;
println!(
"Again interval: {} days",
next_states.again.interval.round().max(1.0)
);
println!(
"Hard interval: {} days",
next_states.hard.interval.round().max(1.0)
);
println!(
"Good interval: {} days",
next_states.good.interval.round().max(1.0)
);
println!(
"Easy interval: {} days",
next_states.easy.interval.round().max(1.0)
);
let next_state = next_states.good;
let interval = next_state.interval.round().max(1.0) as u32;
card.memory_state = Some(next_state.memory);
card.scheduled_days = interval;
card.last_review = Some(Utc::now());
card.due = card.last_review.unwrap() + Duration::days(interval as i64);
println!("Next review due: {}", card.due);
println!("Memory state: {:?}", card.memory_state);
Ok(())
}
fn schedule_existing_card() -> Result<(), Box<dyn std::error::Error>> {
let mut card = Card {
due: Utc::now(), last_review: Some(Utc::now() - Duration::days(7)), memory_state: Some(MemoryState {
stability: 7.0,
difficulty: 5.0,
}),
scheduled_days: 7,
};
let desired_retention = 0.9;
let fsrs = FSRS::new(Some(&[]))?;
let elapsed_days = (Utc::now() - card.last_review.unwrap()).num_days() as u32;
let next_states = fsrs.next_states(card.memory_state, desired_retention, elapsed_days)?;
println!(
"Again interval: {} days",
next_states.again.interval.round().max(1.0)
);
println!(
"Hard interval: {} days",
next_states.hard.interval.round().max(1.0)
);
println!(
"Good interval: {} days",
next_states.good.interval.round().max(1.0)
);
println!(
"Easy interval: {} days",
next_states.easy.interval.round().max(1.0)
);
let next_state = next_states.again;
let interval = next_state.interval.round().max(1.0) as u32;
card.memory_state = Some(next_state.memory);
card.scheduled_days = interval;
card.last_review = Some(Utc::now());
card.due = card.last_review.unwrap() + Duration::days(interval as i64);
println!("Next review due: {}", card.due);
println!("Memory state: {:?}", card.memory_state);
Ok(())
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Scheduling a new card:");
schedule_new_card()?;
println!("\nScheduling an existing card:");
schedule_existing_card()?;
Ok(())
}