using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; using backend.Data; using backend.DTOs; using backend.Models; namespace backend.Controllers; [ApiController] [Route("api/[controller]")] public class QuizController : ControllerBase { private readonly AppDbContext _db; private readonly AppConfig _appConfig; public QuizController(AppDbContext db, IOptions appConfig) { _db = db; _appConfig = appConfig.Value; } [HttpGet("questions")] public async Task GetQuestions() { var questions = await _db.QuizQuestions .OrderBy(q => q.Id) .Select(q => new QuestionDto { Id = q.Id, QuestionText = q.QuestionText, Options = new List { q.Option1, q.Option2, q.Option3, q.Option4 } }) .ToListAsync(); return Ok(questions); } [HttpPost("submit")] public async Task SubmitQuiz([FromBody] QuizSubmitRequest request) { // Check if user already attempted var existingAttempt = await _db.UserQuizAttempts .AnyAsync(qa => qa.UserId == request.UserId); if (existingAttempt) { return BadRequest(new { message = "شما قبلاً در مسابقه شرکت کرده‌اید." }); } var user = await _db.Users.FindAsync(request.UserId); if (user == null) { return NotFound(new { message = "کاربر یافت نشد." }); } var questions = await _db.QuizQuestions.ToListAsync(); var participationPoints = _appConfig.Quiz.ParticipationPoints; var correctAnswerPoints = _appConfig.Quiz.CorrectAnswerPoints; int correctCount = 0; var answers = new List(); foreach (var answer in request.Answers) { var question = questions.FirstOrDefault(q => q.Id == answer.QuestionId); if (question == null) continue; bool isCorrect = question.CorrectOption == answer.SelectedOption; if (isCorrect) correctCount++; answers.Add(new UserQuizAnswer { QuestionId = answer.QuestionId, SelectedOption = answer.SelectedOption, IsCorrect = isCorrect }); } int totalQuizPoints = participationPoints + (correctCount * correctAnswerPoints); var attempt = new UserQuizAttempt { UserId = request.UserId, ParticipationPoints = participationPoints, CorrectAnswersCount = correctCount, TotalQuizPoints = totalQuizPoints, CompletedAt = DateTime.UtcNow, Answers = answers }; _db.UserQuizAttempts.Add(attempt); // Update total score await RecalculateTotalScore(request.UserId); await _db.SaveChangesAsync(); var totalScore = await _db.UserTotalScores .Where(ts => ts.UserId == request.UserId) .Select(ts => ts.TotalPoints) .FirstOrDefaultAsync(); return Ok(new QuizSubmitResponse { ParticipationPoints = participationPoints, CorrectCount = correctCount, TotalQuizPoints = totalQuizPoints, TotalScore = totalScore }); } [HttpGet("user/{userId}")] public async Task GetUserQuiz(int userId) { var attempt = await _db.UserQuizAttempts .Include(qa => qa.Answers) .ThenInclude(a => a.Question) .FirstOrDefaultAsync(qa => qa.UserId == userId); if (attempt == null) { return NotFound(new { message = "کاربر هنوز در مسابقه شرکت نکرده است." }); } var questions = attempt.Answers.Select(a => new UserQuestionDto { Id = a.Question.Id, QuestionText = a.Question.QuestionText, Options = new List { a.Question.Option1, a.Question.Option2, a.Question.Option3, a.Question.Option4 }, SelectedOption = a.SelectedOption, IsCorrect = a.IsCorrect }).ToList(); return Ok(new UserQuizResponse { Questions = questions, ParticipationPoints = attempt.ParticipationPoints, CorrectCount = attempt.CorrectAnswersCount, TotalQuizPoints = attempt.TotalQuizPoints }); } private async Task RecalculateTotalScore(int userId) { var quizPoints = await _db.UserQuizAttempts .Where(qa => qa.UserId == userId) .Select(qa => (int?)qa.TotalQuizPoints) .FirstOrDefaultAsync() ?? 0; var khatmPoints = await _db.UserKhatmSelections .Where(ks => ks.UserId == userId && ks.IsSelected) .SumAsync(ks => ks.KhatmItem.Points); int total = quizPoints + khatmPoints; var totalScore = await _db.UserTotalScores .FirstOrDefaultAsync(ts => ts.UserId == userId); if (totalScore != null) { totalScore.TotalPoints = total; } } }