namespace GermanApp.Domain.Entities;
///
/// Represents a quiz question for a quiz.
/// Each question has a type (multiple choice, true/false, fill-in-the-blank, etc.)
/// and is associated with a specific quiz.
///
public class QuizQuestion
{
public int Id { get; private set; }
public int QuizId { get; private set; }
public string QuestionText { get; private set; } = string.Empty;
public QuestionType Type { get; private set; }
public string? CorrectAnswer { get; private set; }
public int Points { get; private set; } = 1; // Points for this question
public int Difficulty { get; private set; } // 1-5 scale
public int Order { get; private set; }
public bool IsActive { get; private set; } = true;
public DateTime CreatedAt { get; private set; }
public DateTime? UpdatedAt { get; private set; }
// Navigation property
public virtual Quiz? Quiz { get; private set; }
public virtual ICollection Options { get; private set; } = new List();
///
/// Constructor for EF Core deserialization.
///
private QuizQuestion() { }
///
/// Factory method to create a new quiz question.
///
/// ID of the parent quiz
/// The question text
/// The question type
/// The correct answer
/// Points for this question (default 1)
/// Difficulty level (1-5, default 3)
/// Sort order within the quiz
public static QuizQuestion Create(
int quizId,
string questionText,
QuestionType type,
string correctAnswer,
int points = 1,
int difficulty = 3,
int order = 1)
{
if (difficulty < 1 || difficulty > 5)
throw new ArgumentOutOfRangeException(nameof(difficulty), "Difficulty must be between 1 and 5");
if (points < 0)
throw new ArgumentOutOfRangeException(nameof(points), "Points must be positive");
if (string.IsNullOrWhiteSpace(questionText))
throw new ArgumentException("Question text cannot be empty", nameof(questionText));
return new QuizQuestion
{
QuizId = quizId,
QuestionText = questionText,
Type = type,
CorrectAnswer = correctAnswer,
Points = points,
Difficulty = difficulty,
Order = order,
CreatedAt = DateTime.UtcNow
};
}
///
/// Updates the question text.
///
public void UpdateQuestionText(string newQuestionText)
{
if (string.IsNullOrWhiteSpace(newQuestionText))
throw new ArgumentException("Question text cannot be empty", nameof(newQuestionText));
QuestionText = newQuestionText;
UpdatedAt = DateTime.UtcNow;
}
///
/// Updates the correct answer.
///
public void UpdateCorrectAnswer(string newCorrectAnswer)
{
CorrectAnswer = newCorrectAnswer;
UpdatedAt = DateTime.UtcNow;
}
///
/// Updates the points for this question.
///
public void UpdatePoints(int newPoints)
{
if (newPoints < 0)
throw new ArgumentOutOfRangeException(nameof(newPoints), "Points must be positive");
Points = newPoints;
UpdatedAt = DateTime.UtcNow;
}
///
/// Updates the difficulty level.
///
public void UpdateDifficulty(int newDifficulty)
{
if (newDifficulty < 1 || newDifficulty > 5)
throw new ArgumentOutOfRangeException(nameof(newDifficulty), "Difficulty must be between 1 and 5");
Difficulty = newDifficulty;
UpdatedAt = DateTime.UtcNow;
}
///
/// Updates the sort order.
///
public void UpdateOrder(int newOrder)
{
Order = newOrder;
UpdatedAt = DateTime.UtcNow;
}
///
/// Updates the question type.
///
public void UpdateType(QuestionType newType)
{
Type = newType;
UpdatedAt = DateTime.UtcNow;
}
///
/// Updates the associated quiz.
///
public void UpdateQuiz(int newQuizId)
{
QuizId = newQuizId;
UpdatedAt = DateTime.UtcNow;
}
///
/// Activates the quiz question.
///
public void Activate()
{
IsActive = true;
UpdatedAt = DateTime.UtcNow;
}
///
/// Deactivates the quiz question.
///
public void Deactivate()
{
IsActive = false;
UpdatedAt = DateTime.UtcNow;
}
///
/// Adds an option to this question.
///
public void AddOption(QuizOption option)
{
Options.Add(option);
}
///
/// Removes an option from this question.
///
public void RemoveOption(QuizOption option)
{
Options.Remove(option);
}
}
///
/// Represents an option for a multiple-choice quiz question.
///
public class QuizOption
{
public int Id { get; private set; }
public int QuizQuestionId { get; private set; }
public string Text { get; private set; } = string.Empty;
public bool IsCorrect { get; private set; }
public int Order { get; private set; }
// Navigation property
public virtual QuizQuestion? QuizQuestion { get; private set; }
///
/// Constructor for EF Core deserialization.
///
private QuizOption() { }
///
/// Factory method to create a new quiz option.
///
/// ID of the parent quiz question
/// The option text
/// Whether this is the correct answer
/// Sort order within the question's options
public static QuizOption Create(
int quizQuestionId,
string text,
bool isCorrect = false,
int order = 1)
{
if (string.IsNullOrWhiteSpace(text))
throw new ArgumentException("Option text cannot be empty", nameof(text));
return new QuizOption
{
QuizQuestionId = quizQuestionId,
Text = text,
IsCorrect = isCorrect,
Order = order
};
}
///
/// Updates the option text.
///
public void UpdateText(string newText)
{
if (string.IsNullOrWhiteSpace(newText))
throw new ArgumentException("Option text cannot be empty", nameof(newText));
Text = newText;
}
///
/// Updates whether this option is correct.
///
public void UpdateIsCorrect(bool newIsCorrect)
{
IsCorrect = newIsCorrect;
}
///
/// Updates the sort order.
///
public void UpdateOrder(int newOrder)
{
Order = newOrder;
}
}
///
/// Enum representing the types of quiz questions.
///
public enum QuestionType
{
///
/// Multiple choice with single correct answer
///
MultipleChoice = 0,
///
/// Multiple choice with multiple correct answers
///
MultipleSelect = 1,
///
/// True or false question
///
TrueFalse = 2,
///
/// Fill-in-the-blank question
///
FillInTheBlank = 3,
///
/// Matching question
///
Matching = 4,
///
/// Short answer question
///
ShortAnswer = 5
}