Add variable question distractor pools

This commit is contained in:
hz
2026-07-13 10:15:05 -05:00
parent f2c59388eb
commit 93154d5925
24 changed files with 1040 additions and 247 deletions
+50 -20
View File
@@ -12,6 +12,7 @@ public class QuestionResponse
public Dictionary<string, string> ChoiceExplanations { get; set; } = [];
public Dictionary<string, WrongAnswerFollowup> WrongAnswerFollowups { get; set; } = [];
public Dictionary<string, int> ChoiceSelectionPercentages { get; set; } = [];
public string ChoiceSelectionRateBasis { get; set; } = "presented";
public string Discipline { get; set; } = "";
public string System { get; set; } = "";
public string PerformanceCategory { get; set; } = "";
@@ -24,27 +25,56 @@ public class QuestionResponse
public static QuestionResponse FromModel(
Question question,
Dictionary<string, int>? liveChoiceSelectionPercentages = null,
int questionElo = 1000) => new()
int questionElo = 1000,
bool includeChoicePool = true)
{
Id = question.Id ?? "",
ExternalId = question.ExternalId,
Stem = question.Stem,
LeadIn = question.LeadIn,
Choices = question.Choices,
CorrectChoiceId = question.CorrectChoiceId,
Explanation = question.Explanation,
ChoiceExplanations = question.ChoiceExplanations,
WrongAnswerFollowups = question.WrongAnswerFollowups,
ChoiceSelectionPercentages = BuildChoiceSelectionPercentages(question, liveChoiceSelectionPercentages),
Discipline = question.Discipline,
System = question.System,
PerformanceCategory = RatingCategory.Normalize(question.PerformanceCategory, question.System, question.Discipline),
Difficulty = question.Difficulty,
QuestionElo = questionElo,
Labs = question.Labs,
Media = question.Media,
Tags = question.Tags
};
var choices = includeChoicePool ? question.Choices : SelectLegacyChoices(question);
var choiceIds = choices.Select(choice => choice.Id).ToHashSet(StringComparer.Ordinal);
var percentages = BuildChoiceSelectionPercentages(question, liveChoiceSelectionPercentages);
return new QuestionResponse
{
Id = question.Id ?? "",
ExternalId = question.ExternalId,
Stem = question.Stem,
LeadIn = question.LeadIn,
Choices = choices,
CorrectChoiceId = question.CorrectChoiceId,
Explanation = question.Explanation,
ChoiceExplanations = question.ChoiceExplanations
.Where(entry => choiceIds.Contains(entry.Key))
.ToDictionary(),
WrongAnswerFollowups = question.WrongAnswerFollowups
.Where(entry => choiceIds.Contains(entry.Key))
.ToDictionary(),
ChoiceSelectionPercentages = percentages
.Where(entry => choiceIds.Contains(entry.Key))
.ToDictionary(),
Discipline = question.Discipline,
System = question.System,
PerformanceCategory = RatingCategory.Normalize(question.PerformanceCategory, question.System, question.Discipline),
Difficulty = question.Difficulty,
QuestionElo = questionElo,
Labs = question.Labs,
Media = question.Media,
Tags = question.Tags
};
}
private static List<QuestionChoice> SelectLegacyChoices(Question question)
{
if (question.Choices.Count <= 5)
return question.Choices;
var correct = question.Choices.First(choice => choice.Id == question.CorrectChoiceId);
var distractors = question.Choices
.Where(choice => choice.Id != question.CorrectChoiceId)
.OrderBy(_ => Random.Shared.Next())
.Take(4)
.Append(correct)
.OrderBy(_ => Random.Shared.Next())
.ToList();
return distractors;
}
public static Dictionary<string, int> BuildChoiceSelectionPercentages(Question question, Dictionary<string, int>? liveChoiceSelectionPercentages)
{