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.
37 lines
1.6 KiB
C#
37 lines
1.6 KiB
C#
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 });
|
|
}
|
|
}
|