Add flashcards feature with spaced repetition scheduling
Adds a full flashcards system: FSRS-based scheduling, cloze/basic card types, CSV import/export, media storage, and study UI, wired into navigation and the dashboard alongside existing question flows.
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
using MongoDB.Driver;
|
||||
using QuestionsApi.Models;
|
||||
|
||||
namespace QuestionsApi.Services.Flashcards;
|
||||
|
||||
public sealed class FlashcardSettingsStore
|
||||
{
|
||||
private readonly IMongoCollection<FlashcardSettings> _settings;
|
||||
|
||||
public FlashcardSettingsStore(MongoDatabaseProvider mongo)
|
||||
{
|
||||
_settings = mongo.Database.GetCollection<FlashcardSettings>("FlashcardSettings");
|
||||
_settings.Indexes.CreateOne(new CreateIndexModel<FlashcardSettings>(
|
||||
Builders<FlashcardSettings>.IndexKeys.Ascending(v => v.UserId),
|
||||
new CreateIndexOptions { Unique = true, Name = "flashcard_settings_unique_user" }));
|
||||
}
|
||||
|
||||
public async Task<FlashcardSettings> GetAsync(string userId) =>
|
||||
await _settings.Find(v => v.UserId == userId).FirstOrDefaultAsync()
|
||||
?? new FlashcardSettings { UserId = userId };
|
||||
|
||||
public async Task<FlashcardSettings> UpdateAsync(string userId, UpdateFlashcardSettingsRequest request)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
return await _settings.FindOneAndUpdateAsync(
|
||||
v => v.UserId == userId,
|
||||
Builders<FlashcardSettings>.Update
|
||||
.Set(v => v.NewCardsPerDay, Math.Clamp(request.NewCardsPerDay, 0, 2000))
|
||||
.Set(v => v.ReviewsPerDay, Math.Clamp(request.ReviewsPerDay, 0, 5000))
|
||||
.Set(v => v.DesiredRetention, FsrsFlashcardScheduler.DesiredRetention)
|
||||
.Set(v => v.UpdatedUtc, now)
|
||||
.Inc(v => v.Revision, 1)
|
||||
.SetOnInsert(v => v.UserId, userId),
|
||||
new FindOneAndUpdateOptions<FlashcardSettings> { IsUpsert = true, ReturnDocument = ReturnDocument.After });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user