fitts

Crates.iofitts
lib.rsfitts
version0.0.3
created_at2025-03-25 04:11:37.303278+00
updated_at2025-07-24 19:03:51.144439+00
descriptionA Fitts‑based memory model integrated with the Free Spaced Repetition Scheduler (FSRS) for smarter review scheduling.
homepagehttps://github.com/brenogonzaga/fitts
repositoryhttps://github.com/brenogonzaga/fitts
max_upload_size
id1604722
size282,726
Breno Gonzaga (brenogonzaga)

documentation

https://docs.rs/fitts

README

Fitts Memory Scheduler

A sophisticated memory card review scheduler that applies Fitts' Law to optimize spaced repetition learning. This library provides an intelligent card ordering system based on user response patterns and cognitive difficulty prediction.

What is Fitts Memory Scheduler?

This library implements a memory card review scheduler that uses Fitts' Law principles to:

  1. Predict Response Times: Estimates cognitive difficulty based on memory strength and accessibility
  2. Classify Card Difficulty: Automatically categorizes cards from VeryEasy to VeryHard
  3. Optimize Review Order: Prioritizes cards based on user response patterns and revlog data
  4. Track Learning Progress: Maintains detailed analytics for continuous optimization

Fitts' Law Applied to Memory

Traditional Fitts' Law (Motor Tasks):

Movement Time = a + b × log₂(Distance/Target_Width + 1)

Our Memory Adaptation:

Response Time = a + b × log₂(Memory_Distance/Memory_Accessibility + 1)

Where:

  • Memory Distance = function of time since last review and card difficulty
  • Memory Accessibility = function of memory stability and ease factor
  • Response Time = predicted cognitive recall time (crescimento exponencial sem limite superior)

Key Features

  • 🧠 Intelligent Difficulty Classification: Cards automatically classified into 5 difficulty levels
  • ⏱️ Crescimento Exponencial: Response times crescem exponencialmente sem limite superior rígido
  • 📊 Revlog-Driven Ordering: Card order based entirely on user response patterns
  • 🎯 Priority-Based Scheduling: Smart review order based on urgency × difficulty × error rate
  • 📈 Learning Analytics: Detailed performance tracking and optimization recommendations
  • 🔄 FSRS Integration: Seamless integration with state-of-the-art spaced repetition algorithms

Core Components

FittsMemoryScheduler

The main scheduler class that handles:

  • Card Management: Add, track, and organize memory cards across multiple decks
  • Difficulty Classification: Automatically categorize cards based on predicted response times
  • Review Scheduling: Generate optimal review order based on user response history
  • Session Management: Conduct review sessions with real-time adaptation
  • Analytics: Track performance metrics and generate optimization recommendations

Difficulty Levels

Cards are automatically classified based on predicted cognitive response time (exponential growth):

pub enum DifficultyLevel {
    VeryEasy = 1,   // < 2.0 seconds
    Easy = 2,       // 2.0s - 4.0s
    Medium = 3,     // 4.0s - 8.0s
    Hard = 4,       // 8.0s - 20.0s
    VeryHard = 5,   // ≥ 20.0s (sem limite superior)
}
```## Installation

Add this to your `Cargo.toml`:

```toml
[dependencies]
fitts = "0.1.0"

Quick Start

use fitts::scheduler::{FittsMemoryScheduler, SchedulerConfig};
use fitts::{CardState, Rating};

fn main() -> Result<(), String> {
    // Create scheduler with optimized configuration
    let mut scheduler = FittsMemoryScheduler::new(SchedulerConfig {
        max_cards_per_session: 15,
        max_session_duration_minutes: 20,
        prioritize_error_prone: true,    // Key: prioritize problem cards
        balance_difficulty_levels: false, // Let user responses drive order
        urgency_multiplier: 1.5,
        new_cards_limit: 8,
    })?;

    // Add a card
    let card_state = CardState {
        memory_state: None,
        review_count: 0,
        lapse_count: 0,
        stability: 1.0,
        ease: 2.5,
        interval_days: 1.0,
        last_review: None,
    };

    scheduler.add_card("my_deck".to_string(), "card_1".to_string(), card_state);

    // Generate review schedule (order based on priority)
    let schedule = scheduler.generate_review_schedule("user_id", "my_deck")?;

    // Process user response (this updates future card ordering)
    let result = scheduler.review_card(
        "user_id".to_string(),
        "my_deck".to_string(),
        "card_1".to_string(),
        Rating::Hard,        // User found it difficult
        8.5                  // Slow response time
    )?;

    // Next time, this card will have higher priority due to poor performance
    let updated_schedule = scheduler.generate_review_schedule("user_id", "my_deck")?;

    Ok(())
}

How It Works: Response-Driven Ordering

The scheduler uses user response patterns to optimize card ordering:

  1. Initial State: All cards start with similar priority
  2. User Reviews Cards: Response time and rating are recorded in revlog
  3. Priority Recalculation: Cards with poor performance get higher priority:
    • Slow response times → Higher priority
    • Poor ratings (Again/Hard) → Higher priority
    • High prediction error → Higher priority
  4. Reordering: Next session prioritizes problem cards first

Example Priority Calculation

Priority = urgency_factor × difficulty_factor × error_factor × frequency_factor

Where:
- urgency_factor = 1.0 + (days_overdue × urgency_multiplier)
- difficulty_factor = difficulty_level.priority_multiplier()
- error_factor = 1.0 + error_rate (if prioritize_error_prone = true)
- frequency_factor = 1.0 / (reviews_since_update + 1.0)

Examples

See the examples/ directory for complete demonstrations:

  • memory_simulation_simple.rs - Basic scheduler usage
  • response_driven_ordering.rs - How user responses affect card ordering
  • comprehensive_scheduler_demo.rs - Full feature demonstration

Advanced Features

Analytics and Optimization

// Get user performance statistics
if let Some(stats) = scheduler.get_user_stats("user_id") {
    println!("Total reviews: {}", stats.total_reviews);
    println!("Average response time: {:.2}s", stats.avg_response_time);
    println!("Accuracy rate: {:.1}%", stats.accuracy_rate * 100.0);
}

// Generate deck optimization recommendations
let optimization = scheduler.generate_deck_optimization("deck_id")?;
println!("Total cards: {}", optimization.total_cards);

Revlog Analysis

// Export complete review history for analysis
let revlog_json = scheduler.export_revlog();

// Each review creates a detailed revlog entry with:
// - Actual vs predicted response time
// - Rating and difficulty classification
// - Prediction error calculation
// - Context and metadata

Configuration Options

pub struct SchedulerConfig {
    pub max_cards_per_session: usize,         // Limit cards per session
    pub max_session_duration_minutes: usize,   // Time limit per session
    pub prioritize_error_prone: bool,          // Boost priority for problem cards
    pub balance_difficulty_levels: bool,       // Balance vs pure response-driven
    pub urgency_multiplier: f64,              // How much to weight overdue cards
    pub new_cards_limit: usize,               // Max new cards per session
}

Performance

The scheduler is optimized for real-time use:

  • Fast Priority Calculation: O(n) complexity for card ordering
  • Efficient Revlog: Minimal memory overhead per review
  • Batch Processing: Optimized for multiple card reviews
  • Response Time Growth: All predictions follow exponential progression without artificial caps

Integration with FSRS

The scheduler seamlessly integrates with FSRS (Free Spaced Repetition Scheduler):

  • Uses FSRS parameters for memory modeling
  • Applies Fitts' Law for cognitive difficulty prediction
  • Combines both systems for optimal review timing
  • Maintains compatibility with FSRS card states

License

This project is licensed under the MIT OR Apache-2.0 license.

Contributing

Contributions are welcome! Please see the examples/ directory for usage patterns and feel free to submit issues or pull requests.

Commit count: 0

cargo fmt