Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,13 @@ print(retrievabilityValue) // 0.9
### Custom Parameters

```swift
let params = PartialFSRSParameters(
let config = FSRSConfiguration(
requestRetention: 0.9,
maximumInterval: 36500,
enableFuzz: true,
enableShortTerm: true
)
let f = fsrs<Flashcard>(params: params)
let f = FSRS<Flashcard>(configuration: config)
```

### Reschedule with History
Expand Down
4 changes: 2 additions & 2 deletions Sources/Examples/Flashcard.swift
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ var card = Flashcard(
)

// Preview all possible scheduling outcomes
let scheduling = try fsrs.repeat(card: card, now: Date())
let scheduling = try fsrs.schedule(card: card, at: Date())

print("If you rate it 'Again':", scheduling[.again]!.card.due)
print("If you rate it 'Hard':", scheduling[.hard]!.card.due)
Expand All @@ -143,4 +143,4 @@ try jsonData.write(to: fileURL)

// Load and continue scheduling
let loaded = try JSONDecoder().decode(Flashcard.self, from: jsonData)
let nextReview = try fsrs.next(card: loaded, now: Date(), rating: .good)
let nextReview = try fsrs.schedule(card: loaded, at: Date(), rating: .good)
12 changes: 6 additions & 6 deletions Sources/Examples/LoggerExample.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func exampleBasicLogging() {
// All operations will now be logged
let card = MyCard()
do {
let result = try fsrs.next(card: card, now: Date(), rating: .good)
let result = try fsrs.schedule(card: card, at: Date(), rating: .good)
print("Next due: \(result.card.due)")
} catch {
print("Error: \(error)")
Expand All @@ -101,7 +101,7 @@ func exampleFilteredLogging() {
// Only warnings and errors will be logged
let card = MyCard()
do {
_ = try fsrs.forget(card: card, now: Date()) // This will log a warning
_ = try fsrs.forget(card: card, at: Date()) // This will log a warning
} catch {
print("Error: \(error)")
}
Expand All @@ -118,7 +118,7 @@ func exampleFileLogging() {
// All logs will be written to file
let card = MyCard()
do {
let recordLog = try fsrs.repeat(card: card, now: Date())
let recordLog = try fsrs.schedule(card: card, at: Date())
print("Logged \(recordLog.count) scenarios to \(logFileURL.path)")
} catch {
print("Error: \(error)")
Expand Down Expand Up @@ -151,7 +151,7 @@ func exampleCompositeLogging() {
// Logs will go to both console and file
let card = MyCard()
do {
_ = try fsrs.next(card: card, now: Date(), rating: .good)
_ = try fsrs.schedule(card: card, at: Date(), rating: .good)
} catch {
print("Error: \(error)")
}
Expand Down Expand Up @@ -216,7 +216,7 @@ func exampleLogAnalysis() {

for rating in ratings {
do {
let result = try fsrs.next(card: card, now: Date(), rating: rating)
let result = try fsrs.schedule(card: card, at: Date(), rating: rating)
card = result.card

// You'll see detailed logs showing:
Expand Down Expand Up @@ -277,7 +277,7 @@ func examplePerformanceMonitoring() {
// Run multiple operations
for _ in 0..<10 {
do {
let result = try fsrs.next(card: card, now: Date(), rating: .good)
let result = try fsrs.schedule(card: card, at: Date(), rating: .good)
card = result.card
} catch {
print("Error: \(error)")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,25 @@
/// Optional logger for debugging and monitoring
public var logger: (any FSRSLogger)?

/// Initialize FSRS algorithm with parameters
/// Initialize FSRS algorithm with configuration
/// - Parameters:
/// - params: Partial FSRS parameters (missing values use defaults)
/// - configuration: FSRS configuration (missing values use defaults)
/// - randomProvider: Random provider (optional, uses system random if not provided)
/// - logger: Optional logger for debugging and monitoring
public init(
params: PartialFSRSParameters = PartialFSRSParameters(),
configuration: FSRSConfiguration = FSRSConfiguration(),
randomProvider: RandomProvider? = nil,
logger: (any FSRSLogger)? = nil
) {
self.randomProvider = randomProvider
self.logger = logger
self.parameters = FSRSParametersGenerator.generate(from: params)
self.parameters = FSRSParametersGenerator.generate(from: configuration)
do {
self.intervalModifier = try FSRSAlgorithm.calculateIntervalModifier(
requestRetention: parameters.requestRetention,
weights: parameters.weights
)
logger?.debug("Algorithm initialized: requestRetention=\(parameters.requestRetention), maximumInterval=\(parameters.maximumInterval), enableFuzz=\(parameters.enableFuzz), enableShortTerm=\(parameters.enableShortTerm)")

Check failure on line 35 in Sources/FSRS/Algorithm/FSRSAlgorithm.swift

View workflow job for this annotation

GitHub Actions / SwiftLint

Line Length Violation: Line should be 200 characters or less; currently it has 230 characters (line_length)
} catch {
// This should never happen with valid parameters, but handle gracefully
logger?.error("Failed to calculate interval modifier: \(error)")
Expand All @@ -46,7 +46,7 @@
/// - stability: Current stability
/// - Returns: Retrievability (probability of recall)
public func forgettingCurve(_ elapsedDays: Double, _ stability: Double) -> Double {
let calculator = StabilityCalculator(parameters: parameters, logger: logger)
let calculator = MemoryStateCalculator(parameters: parameters, logger: logger)
let result = try? calculator.forgettingCurve(
elapsedDays: ElapsedDays(unchecked: elapsedDays),
stability: Stability(unchecked: stability)
Expand All @@ -69,20 +69,14 @@
guard requestRetention > 0 && requestRetention <= 1 else {
throw FSRSError.invalidRequestRetention(requestRetention)
}
let (decay, factor) = StabilityCalculator.computeDecayFactor(weights)
let (decay, factor) = MemoryStateCalculator.computeDecayFactor(weights)
let result = (pow(requestRetention, 1 / decay) - 1) / factor
return roundToFixed(result)
}


// Note: All calculation methods have been extracted to dedicated calculator classes:
// - StabilityCalculator: stability-related formulas
// - DifficultyCalculator: difficulty-related formulas
// Note: All calculation methods live in Algorithm/ directory:
// - MemoryStateCalculator: stability + difficulty formulas (unified)
// - IntervalCalculator: interval calculation and fuzzing
//
// The old nextState(), initStability(), nextDifficulty(), nextRecallStability(),
// nextForgetStability(), nextShortTermStability(), nextInterval(), and applyFuzz()
// methods have been removed as they are now implemented in the calculator classes.
//
// Schedulers now use these calculators directly via BaseScheduler.
// - IntervalConstraintApplier: interval ordering constraints
}
Loading