namespace GermanApp.Domain.Entities; /// /// Represents a quiz that can be associated with a lesson. /// A quiz contains multiple questions and has a passing score threshold. /// public class Quiz { public int Id { get; private set; } public int LessonId { get; private set; } public string Title { get; private set; } = string.Empty; public string? Description { get; private set; } public int PassingScore { get; private set; } = 80; // Default 80% public int TimeLimitMinutes { get; private set; } = 0; // 0 = no limit public bool IsActive { get; private set; } = true; public bool ShuffleQuestions { get; private set; } = true; public DateTime CreatedAt { get; private set; } public DateTime? UpdatedAt { get; private set; } // Navigation property public virtual Lesson? Lesson { get; private set; } public virtual ICollection Questions { get; private set; } = new List(); /// /// Constructor for EF Core deserialization. /// private Quiz() { } /// /// Factory method to create a new quiz. /// /// ID of the associated lesson /// Title of the quiz /// Optional description /// Passing score percentage (default 80) /// Time limit in minutes (0 for no limit) public static Quiz Create( int lessonId, string title, string? description = null, int passingScore = 80, int timeLimitMinutes = 0) { if (string.IsNullOrWhiteSpace(title)) throw new ArgumentException("Quiz title cannot be empty", nameof(title)); if (passingScore < 0 || passingScore > 100) throw new ArgumentOutOfRangeException(nameof(passingScore), "Passing score must be between 0 and 100"); if (timeLimitMinutes < 0) throw new ArgumentOutOfRangeException(nameof(timeLimitMinutes), "Time limit cannot be negative"); return new Quiz { LessonId = lessonId, Title = title, Description = description, PassingScore = passingScore, TimeLimitMinutes = timeLimitMinutes, CreatedAt = DateTime.UtcNow }; } /// /// Updates the quiz title. /// public void UpdateTitle(string newTitle) { if (string.IsNullOrWhiteSpace(newTitle)) throw new ArgumentException("Quiz title cannot be empty", nameof(newTitle)); Title = newTitle; UpdatedAt = DateTime.UtcNow; } /// /// Updates the quiz description. /// public void UpdateDescription(string? newDescription) { Description = newDescription; UpdatedAt = DateTime.UtcNow; } /// /// Updates the passing score. /// public void UpdatePassingScore(int newPassingScore) { if (newPassingScore < 0 || newPassingScore > 100) throw new ArgumentOutOfRangeException(nameof(newPassingScore), "Passing score must be between 0 and 100"); PassingScore = newPassingScore; UpdatedAt = DateTime.UtcNow; } /// /// Updates the time limit. /// public void UpdateTimeLimit(int newTimeLimitMinutes) { if (newTimeLimitMinutes < 0) throw new ArgumentOutOfRangeException(nameof(newTimeLimitMinutes), "Time limit cannot be negative"); TimeLimitMinutes = newTimeLimitMinutes; UpdatedAt = DateTime.UtcNow; } /// /// Updates the associated lesson. /// public void UpdateLesson(int newLessonId) { LessonId = newLessonId; UpdatedAt = DateTime.UtcNow; } /// /// Updates the shuffle questions setting. /// public void UpdateShuffleQuestions(bool newShuffleQuestions) { ShuffleQuestions = newShuffleQuestions; UpdatedAt = DateTime.UtcNow; } /// /// Activates the quiz. /// public void Activate() { IsActive = true; UpdatedAt = DateTime.UtcNow; } /// /// Deactivates the quiz. /// public void Deactivate() { IsActive = false; UpdatedAt = DateTime.UtcNow; } /// /// Adds a question to this quiz. /// public void AddQuestion(QuizQuestion question) { if (question == null) throw new ArgumentNullException(nameof(question)); Questions.Add(question); } /// /// Removes a question from this quiz. /// public void RemoveQuestion(QuizQuestion question) { if (question == null) throw new ArgumentNullException(nameof(question)); Questions.Remove(question); } /// /// Checks if the quiz is passed based on a score percentage. /// public bool IsPassed(double scorePercentage) => scorePercentage >= PassingScore; /// /// Calculates the score percentage based on correct answers. /// public double CalculateScore(int correctAnswers, int totalQuestions) { if (totalQuestions == 0) return 0; return (double)correctAnswers / totalQuestions * 100; } }