166 lines
5.1 KiB
C#
166 lines
5.1 KiB
C#
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> appConfig)
|
|
{
|
|
_db = db;
|
|
_appConfig = appConfig.Value;
|
|
}
|
|
|
|
[HttpGet("questions")]
|
|
public async Task<IActionResult> GetQuestions()
|
|
{
|
|
var questions = await _db.QuizQuestions
|
|
.OrderBy(q => q.Id)
|
|
.Select(q => new QuestionDto
|
|
{
|
|
Id = q.Id,
|
|
QuestionText = q.QuestionText,
|
|
Options = new List<string> { q.Option1, q.Option2, q.Option3, q.Option4 }
|
|
})
|
|
.ToListAsync();
|
|
|
|
return Ok(questions);
|
|
}
|
|
|
|
[HttpPost("submit")]
|
|
public async Task<IActionResult> 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<UserQuizAnswer>();
|
|
|
|
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<IActionResult> 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<string> { 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;
|
|
}
|
|
}
|
|
}
|