https://github.com/bootuz/swiftfsrs
A Swift implementation of the Free Spaced Repetition Scheduler (FSRS-6) algorithm.
https://github.com/bootuz/swiftfsrs
Last synced: about 1 month ago
JSON representation
A Swift implementation of the Free Spaced Repetition Scheduler (FSRS-6) algorithm.
- Host: GitHub
- URL: https://github.com/bootuz/swiftfsrs
- Owner: bootuz
- Created: 2025-11-14T13:59:12.000Z (8 months ago)
- Default Branch: main
- Last Pushed: 2025-11-14T15:47:23.000Z (8 months ago)
- Last Synced: 2025-11-14T16:10:41.632Z (8 months ago)
- Language: Swift
- Homepage:
- Size: 90.8 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Swift FSRS
[](https://github.com/bootuz/SwiftFSRS/actions/workflows/swift.yml)


[](https://github.com/bootuz/SwiftFSRS/blob/main/LICENSE)
[](https://swift.org/package-manager/)
A Swift implementation of the Free Spaced Repetition Scheduler (FSRS-6) algorithm.
## Overview
Swift FSRS is a native Swift package that implements the FSRS-6 spaced repetition scheduler algorithm for flashcard applications. It provides a clean, type-safe API following Swift best practices.
## Features
- ✅ Complete FSRS-6 algorithm implementation
- ✅ Protocol-oriented design - works with your own card types
- ✅ Concurrency support
- ✅ Card scheduling with learning steps support (BasicScheduler)
- ✅ Long-term scheduling without learning steps (LongTermScheduler)
- ✅ Reschedule functionality for replaying review history
- ✅ Rollback capability to undo reviews
- ✅ Forget functionality to reset cards
- ✅ Retrievability calculation (formatted and numeric)
- ✅ Customizable strategies (seed, learning steps)
- ✅ Parameter migration support (FSRS-4/5/6 compatibility)
- ✅ Logging support with FSRSLogger protocol
## Installation
### Swift Package Manager
Add the following to your `Package.swift`:
```swift
dependencies: [
.package(url: "https://github.com/yourusername/swift-fsrs.git", from: "1.0.0")
]
```
Or add it via Xcode:
1. File → Add Packages...
2. Enter the repository URL
3. Select version and add to your target
## Usage
### Implementing FSRSCard Protocol
First, create a card type that conforms to the `FSRSCard` protocol:
```swift
import FSRS
struct Flashcard: FSRSCard {
// Your custom properties
let id: UUID
var question: String
var answer: String
// FSRS required properties
var due: Date
var state: State
var lastReview: Date?
var stability: Double
var difficulty: Double
var scheduledDays: Int
var learningSteps: Int
var reps: Int
var lapses: Int
init(question: String, answer: String) {
self.id = UUID()
self.question = question
self.answer = answer
// Initialize FSRS properties for new card
self.due = Date()
self.state = .new
self.lastReview = nil
self.stability = 0
self.difficulty = 0
self.scheduledDays = 0
self.learningSteps = 0
self.reps = 0
self.lapses = 0
}
}
```
### Basic Example
```swift
import FSRS
// Create FSRS instance with default parameters (specify your card type)
let f = fsrs()
// Create a new card
let card = Flashcard(question: "What is the capital of France?", answer: "Paris")
let now = Date()
// Preview all rating scenarios
let recordLog = try f.repeat(card: card, now: now)
// Get card for a specific rating
let goodCard = recordLog[.good]!.card
let goodLog = recordLog[.good]!.log
// Review with a specific rating
let result = try f.next(card: card, now: now, rating: .good)
let nextCard = result.card
// Get retrievability as formatted string
let retrievability = f.getRetrievability(card: card, now: now)
print(retrievability) // "90.00%"
// Get retrievability as numeric value
let retrievabilityValue = f.getRetrievabilityValue(card: card, now: now)
print(retrievabilityValue) // 0.9
```
### Custom Parameters
```swift
let config = FSRSConfiguration(
requestRetention: 0.9,
maximumInterval: 36500,
enableFuzz: true,
enableShortTerm: true
)
let f = FSRS(configuration: config)
```
### Reschedule with History
Replay a card's review history to recalculate its state:
```swift
let now = Date()
let reviews: [FSRSHistory] = [
FSRSHistory(rating: .good, review: now),
FSRSHistory(rating: .good, review: now.addingTimeInterval(86400)),
FSRSHistory(rating: .again, review: now.addingTimeInterval(172800))
]
let options = RescheduleOptions(
updateMemoryState: true,
now: Date()
)
let result = try f.reschedule(
currentCard: card,
reviews: reviews,
options: options
)
print(result.collections.count) // Number of replayed reviews
if let rescheduleItem = result.rescheduleItem {
let updatedCard = rescheduleItem.card
}
```
### Rollback
Undo a review and restore the card to its previous state:
```swift
// After reviewing a card, you get a RecordLogItem
let result = try f.next(card: card, now: Date(), rating: .good)
let currentCard = result.card
let reviewLog = result.log
// Rollback to previous state
let previousCard = try f.rollback(card: currentCard, log: reviewLog)
```
### Forget Card
Reset a card back to the new state:
```swift
let forgottenResult = f.forget(card: card, now: Date(), resetCount: false)
let newCard = forgottenResult.card
// Card is now in .new state with reset stability and difficulty
```
## Architecture
The package is organized into the following modules:
### Core Components
- **Models**: Core data structures (ReviewLog, Parameters, Enums, ValueObjects)
- **Protocols**: Protocol definitions (FSRSCard, AlgorithmProtocols, SchedulerProtocol)
- **Core**: Main algorithm (FSRSAlgorithm, FSRS, Factory) and parameter management
- **Schedulers**: Scheduling logic (BasicScheduler, LongTermScheduler, BaseScheduler)
- **Calculators**: Separate calculators for stability, difficulty, and intervals
### Features
- **Strategies**: Extensible strategy system (seed, learning steps)
- **Features**: Advanced features (Reschedule, RetrievabilityService, CardStateService)
- **Utilities**: Helper functions (DateHelpers, MathHelpers, Alea PRNG, FSRSLogger)
### Design Patterns
- **Protocol-Oriented**: Use `FSRSCard` protocol to work with your own card types
- **Generic Types**: FSRS is generic over any card type conforming to FSRSCard
- **Value Objects**: Type-safe wrappers for domain values (Stability, Difficulty, etc.)
- **Service Layer**: Separate services for retrievability, card state, and rescheduling
## Swift Version
Requires Swift 5.9+
## Testing
- **State Transition Tests**: Verify correct state machine behavior for all card states
- **Parameter Tests**: Test parameter validation, migration, and clipping
- **Integration Tests**: End-to-end testing of complete workflows
- **API Tests**: Verify all public API methods work correctly
How to run tests:
```bash
swift test
```
Run specific test suites:
```bash
swift test --filter StateTransitionTests
swift test --filter IntegrationTests
```
## Status
This is a complete, production-ready implementation of FSRS-6 for Swift. All core functionality has been implemented and tested:
- ✅ Complete FSRS-6 algorithm with all formulas
- ✅ Short-term and long-term scheduling modes
- ✅ Protocol-based generic design for flexibility
- ✅ Comprehensive test suite with 125+ tests
## Contributing
Contributions are welcome! Please ensure:
- All changes are made through forked repository
- Code follows Swift style guidelines
- Tests are added for new features
- All tests pass: `swift test`
- Documentation is updated