Add daily study missions
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
using QuestionsApi.Models;
|
||||
using QuestionsApi.Services;
|
||||
using Xunit;
|
||||
|
||||
namespace QuestionsApi.Tests;
|
||||
|
||||
public sealed class DailyMissionPolicyTests
|
||||
{
|
||||
private static readonly DateTime Now = new(2026, 8, 1, 12, 0, 0, DateTimeKind.Utc);
|
||||
|
||||
[Fact]
|
||||
public void DueReviewsArePrioritizedAndCappedAtTen()
|
||||
{
|
||||
var candidates = DailyMissionStore.BuildCandidates(Dashboard(17), Questions(), Now);
|
||||
Assert.Equal(DailyMissionTypes.DueReviews, candidates[0].Type);
|
||||
Assert.Equal(10, candidates[0].Target);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NoReviewsFallsBackToCoverageGaps()
|
||||
{
|
||||
var candidates = DailyMissionStore.BuildCandidates(Dashboard(0), Questions(), Now);
|
||||
Assert.DoesNotContain(candidates, value => value.Type == DailyMissionTypes.DueReviews);
|
||||
Assert.True(candidates.Count >= 3);
|
||||
Assert.Contains(candidates.Take(3), value => value.Type == DailyMissionTypes.DifficultyFourCorrect);
|
||||
Assert.All(candidates.Where(value => value.Type == DailyMissionTypes.WeakSystemCorrect),
|
||||
value => Assert.Equal(3, value.Target));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HardMissionRequiresThreeEligiblePublishedQuestions()
|
||||
{
|
||||
var questions = Questions();
|
||||
questions.RemoveAll(value => value.Step3System == Step3SystemCatalog.All[1] && value.Difficulty >= 4);
|
||||
var candidates = DailyMissionStore.BuildCandidates(Dashboard(0), questions, Now);
|
||||
Assert.DoesNotContain(candidates, value => value.Type == DailyMissionTypes.DifficultyFourCorrect
|
||||
&& value.Step3System == Step3SystemCatalog.All[1]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void QuestionProgressRequiresCorrectEligibleActivityAfterMissionStart()
|
||||
{
|
||||
var system = Step3SystemCatalog.All[0];
|
||||
var mission = new DailyMission
|
||||
{
|
||||
Type = DailyMissionTypes.DifficultyFourCorrect, Step3System = system, StartsUtc = Now
|
||||
};
|
||||
var question = new Question { Step3System = system, Difficulty = 4 };
|
||||
Assert.True(DailyMissionStore.QualifiesQuestion(mission,
|
||||
new QuestionAttempt { IsCorrect = true, CreatedUtc = Now }, question));
|
||||
Assert.False(DailyMissionStore.QualifiesQuestion(mission,
|
||||
new QuestionAttempt { IsCorrect = false, CreatedUtc = Now }, question));
|
||||
Assert.False(DailyMissionStore.QualifiesQuestion(mission,
|
||||
new QuestionAttempt { IsCorrect = true, IsSkip = true, CreatedUtc = Now }, question));
|
||||
Assert.False(DailyMissionStore.QualifiesQuestion(mission,
|
||||
new QuestionAttempt { IsCorrect = true, CreatedUtc = Now.AddSeconds(-1) }, question));
|
||||
question.Difficulty = 3;
|
||||
Assert.False(DailyMissionStore.QualifiesQuestion(mission,
|
||||
new QuestionAttempt { IsCorrect = true, CreatedUtc = Now }, question));
|
||||
}
|
||||
|
||||
private static DashboardResponse Dashboard(int pending) => new()
|
||||
{
|
||||
MissedQuestionCount = pending,
|
||||
Systems = Step3SystemCatalog.All.Take(4).Select((system, index) => new DashboardSystemPerformance
|
||||
{
|
||||
System = system, MasteryState = index == 0 ? MasteryStates.Unseen : MasteryStates.Learning,
|
||||
MasteryScore = index * 10, DistinctQuestions = index, Difficulty4PlusSuccessful = index
|
||||
}).ToList()
|
||||
};
|
||||
|
||||
private static List<Question> Questions() => Step3SystemCatalog.All.Take(4)
|
||||
.SelectMany(system => Enumerable.Range(0, 6).Select(index => new Question
|
||||
{
|
||||
ExternalId = $"{system}-{index}", Step3System = system, Difficulty = index < 3 ? 4 : 2,
|
||||
IsPublished = true
|
||||
})).ToList();
|
||||
}
|
||||
Reference in New Issue
Block a user