4b467ec136
Includes SwiftData dual-store architecture (local reference + CloudKit user data), JSON-based data seeding, 20 tense guides, 20 grammar notes, SRS review system, course vocabulary, and widget support. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
45 lines
1.4 KiB
Swift
45 lines
1.4 KiB
Swift
import Foundation
|
|
import SharedModels
|
|
import SwiftData
|
|
|
|
struct CourseReviewStore {
|
|
let context: ModelContext
|
|
|
|
@discardableResult
|
|
func fetchOrCreateReviewCard(for card: VocabCard) -> CourseReviewCard {
|
|
let reviewKey = CourseCardStore.reviewKey(for: card)
|
|
let descriptor = FetchDescriptor<CourseReviewCard>(
|
|
predicate: #Predicate<CourseReviewCard> { $0.id == reviewKey }
|
|
)
|
|
|
|
if let existing = (try? context.fetch(descriptor))?.first {
|
|
return existing
|
|
}
|
|
|
|
let reviewCard = CourseReviewCard(
|
|
id: reviewKey,
|
|
deckId: card.deckId,
|
|
front: card.front,
|
|
back: card.back
|
|
)
|
|
context.insert(reviewCard)
|
|
return reviewCard
|
|
}
|
|
|
|
func rate(card: VocabCard, quality: ReviewQuality) {
|
|
let reviewCard = fetchOrCreateReviewCard(for: card)
|
|
let result = SRSEngine.review(
|
|
quality: quality,
|
|
currentEase: reviewCard.easeFactor,
|
|
currentInterval: reviewCard.interval,
|
|
currentReps: reviewCard.repetitions
|
|
)
|
|
reviewCard.easeFactor = result.easeFactor
|
|
reviewCard.interval = result.interval
|
|
reviewCard.repetitions = result.repetitions
|
|
reviewCard.dueDate = SRSEngine.nextDueDate(interval: result.interval)
|
|
reviewCard.lastReviewDate = Date()
|
|
try? context.save()
|
|
}
|
|
}
|