Adapt dynamic question difficulty to learner Elo
This commit is contained in:
@@ -80,6 +80,71 @@ public sealed class DynamicQuestionTests
|
||||
Assert.Equal(first.Choices.Select(value => value.Id), regenerated.Choices.Select(value => value.Id));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DifficultyPolicy_BlendsThenSpecializes_AndTargetsSixtyPercent()
|
||||
{
|
||||
Assert.Equal(1200, DynamicDifficultyPolicy.EffectiveAbility(1100, 1300, null));
|
||||
var early = new DynamicObjectiveMastery { Elo = 1500, Attempts = 1 };
|
||||
var established = new DynamicObjectiveMastery { Elo = 1500, Attempts = 10 };
|
||||
Assert.Equal(1224, DynamicDifficultyPolicy.EffectiveAbility(1100, 1300, early));
|
||||
Assert.Equal(1440, DynamicDifficultyPolicy.EffectiveAbility(1100, 1300, established));
|
||||
Assert.Equal(1370, DynamicDifficultyPolicy.TargetFamilyElo(1440));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DifficultyPolicy_SelectsClosestNonrecentFamily()
|
||||
{
|
||||
var families = new List<DynamicCaseFamily>
|
||||
{
|
||||
new() { Id = "foundation", DifficultyTier = "foundation", NominalElo = 850 },
|
||||
new() { Id = "standard", DifficultyTier = "standard", NominalElo = 1050 },
|
||||
new() { Id = "advanced-a", DifficultyTier = "advanced", NominalElo = 1250 },
|
||||
new() { Id = "advanced-b", DifficultyTier = "advanced", NominalElo = 1250 },
|
||||
new() { Id = "expert", DifficultyTier = "expert", NominalElo = 1450 }
|
||||
};
|
||||
var selected = DynamicDifficultyPolicy.SelectFamily(
|
||||
families, new Dictionary<string, DynamicFamilyRating>(), 1260,
|
||||
new HashSet<string> { "advanced-a" }, 0);
|
||||
Assert.Equal("advanced-b", selected.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DifficultyPolicy_RatingsMoveInOppositeDirections()
|
||||
{
|
||||
Assert.True(DynamicDifficultyPolicy.LearnerDelta(1000, 1050, true, 0) > 0);
|
||||
Assert.True(DynamicDifficultyPolicy.FamilyDelta(1000, 1050, true, 0) < 0);
|
||||
Assert.True(DynamicDifficultyPolicy.LearnerDelta(1000, 1050, false, 0) < 0);
|
||||
Assert.True(DynamicDifficultyPolicy.FamilyDelta(1000, 1050, false, 0) > 0);
|
||||
Assert.Equal(600, DynamicDifficultyPolicy.Clamp(-100));
|
||||
Assert.Equal(1800, DynamicDifficultyPolicy.Clamp(5000));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AdaptiveContent_ResolvesToFourCompleteTiers()
|
||||
{
|
||||
var options = new System.Text.Json.JsonSerializerOptions(System.Text.Json.JsonSerializerDefaults.Web)
|
||||
{ PropertyNameCaseInsensitive = true };
|
||||
var root = Path.GetFullPath(Path.Combine(
|
||||
AppContext.BaseDirectory, "..", "..", "..", "..", "..", "content", "dynamic_questions"));
|
||||
var source = Directory.EnumerateFiles(root, "*.json")
|
||||
.SelectMany(file => System.Text.Json.JsonSerializer.Deserialize<List<DynamicQuestionBlueprint>>(
|
||||
File.ReadAllText(file), options) ?? [])
|
||||
.ToList();
|
||||
var adaptive = DynamicBlueprintResolver.ResolveAll(source)
|
||||
.Where(value => value.QualityStandardVersion >= 3).ToList();
|
||||
|
||||
Assert.Equal(5, adaptive.Count);
|
||||
Assert.All(adaptive, blueprint =>
|
||||
{
|
||||
Assert.Equal(8, blueprint.CaseFamilies.Count);
|
||||
Assert.All(DynamicDifficultyPolicy.TierElos.Keys, tier =>
|
||||
Assert.Equal(2, blueprint.CaseFamilies.Count(value => value.DifficultyTier == tier)));
|
||||
Assert.All(blueprint.CaseFamilies, family =>
|
||||
Assert.False(family.StemTemplate.EndsWith(family.LeadIn, StringComparison.Ordinal)));
|
||||
Assert.Null(DynamicQuestionGenerator.Validate(blueprint));
|
||||
});
|
||||
}
|
||||
|
||||
private static DynamicQuestionBlueprint Blueprint() => new()
|
||||
{
|
||||
ExternalId = "test",
|
||||
|
||||
Reference in New Issue
Block a user