sm-2 0.2.0

Rust Crate for SM-2 Spaced Repetition
Documentation

SM-2

Rust crate for the classic SM-2 algorithm for spaced repetition scheduling.

Table of Contents

Installation

You can install the sm-2 crate from crates.io [link] using cargo:

cargo add sm-2

Quickstart

use sm_2::Utc; // chrono
use sm_2::{Card, Scheduler};

fn main() {
    // NOTE: cards created with Card::default() are due immediately upon creation
    let card = Card::default();

    // Choose a rating and review the card with the scheduler
    // 5 - perfect response
    // 4 - correct response after a hesitation
    // 3 - correct response recalled with serious difficulty
    // 2 - incorrect response; where the correct one seemed easy to recall
    // 1 - incorrect response; the correct one remembered
    // 0 - complete blackout.
    let rating = 5;

    let (card, review_log) = Scheduler::review_card(&card, rating, None, None).unwrap();

    println!("Card rated {} at {}", rating, review_log.review_datetime);
    // > Card rated 5 at 2025-08-18 00:28:59.756451 UTC

    // how much time between when the card is due and now
    let time_delta = card.due - Utc::now();

    const SECONDS_PER_HOUR: f32 = 60.0 * 60.0;
    let time_delta_hours = (time_delta.as_seconds_f32() / SECONDS_PER_HOUR).round() as i32;

    println!("Card due in {time_delta_hours} hours");
    // > Card due in 24 hours
}

Serialization

Card and ReviewLog variables are json-serializable for easy database storage and network requests

use sm_2::{Card, ReviewLog};

// ...

// serialize before storage / request
let card_json: String = card.to_json().unwrap();
let review_log_json: String = review_log.to_json().unwrap();

println!("{card_json}");
// > {"card_id":1755476939756,"n":1,"ef":2.6,"i":1,"due":"2025-08-19T00:28:59.756421Z","needs_extra_review":false}
println!("{review_log_json}");
// > {"card_id":1755476939756,"rating":5,"review_datetime":"2025-08-18T00:28:59.756451Z","review_duration":null}

// deserialize after storage / request
let new_card: Card = Card::from_json(&card_json).unwrap();
let new_review_log: ReviewLog = ReviewLog::from_json(&review_log_json).unwrap();

Versioning

This package is currently unstable and adheres to the following versioning scheme:

  • Minor version will increase when a backward-incompatible change is introduced.
  • Patch version will increase when a bug is fixed or a new feature is added.

Once this package is considered stable, the Major version will be bumped to 1.0.0 and will follow semver.