Your IP : 216.73.216.145


Current Path : /home/users/unlimited/www/learnoid.codeskitter.site/app/Http/Controllers/
Upload File :
Current File : /home/users/unlimited/www/learnoid.codeskitter.site/app/Http/Controllers/QuizController.php

<?php

namespace App\Http\Controllers;

use App\Http\Requests\QuizSubmitRequest;
use App\Http\Resources\QuestionResource;
use App\Http\Resources\QuizSessionResource;
use App\Models\Quiz;
use App\Models\QuizSession;
use App\Repositories\AnswerRepository;
use App\Repositories\QuestionRepository;
use App\Repositories\QuizSessionRepository;
use Carbon\Carbon;

class QuizController extends Controller
{
    public function start(Quiz $quiz)
    {
        /** @var User */
        $loggedInUser = auth()->user();

        $isEnrolled = $quiz->course->enrollments->contains('user_id', $loggedInUser->id);

        if (!$isEnrolled) {
            return $this->json('Cannot start quiz without course enrollment', null, 403);
        }

        // $quizSessionExists = QuizSessionRepository::query()
        //     ->where('quiz_id', $quiz->id)
        //     ->where('course_id', $quiz->course_id)
        //     ->where('user_id', $loggedInUser->id)
        //     ->exists();

        // if ($quizSessionExists) {
        //     return $this->json('Quiz session already submitted', null, 400);
        // }

        $questions = QuestionRepository::query()->where('quiz_id', '=', $quiz->id)->get();
        $question = $questions->first();

        // Start the quiz session
        $quizSession = QuizSessionRepository::create([
            'course_id' => $quiz->course->id,
            'quiz_id' => $quiz->id,
            'user_id' => $loggedInUser->id,
            'seen_question_ids' => json_encode([$question->id]),
            'last_answered_at' => now(),
            'obtained_mark' => 0
        ]);

        return $this->json('Quiz started successfully', [
            'quiz_session' => QuizSessionResource::make($quizSession),
            'previous_was_correct' => null,
            'question' => QuestionResource::make($question),
            'question_count' => $questions->count()
        ], 201);
    }

    public function submit(QuizSession $quizSession, QuizSubmitRequest $request)
    {
        /** @var User */
        $loggedInUser = auth()->user();

        if ($quizSession->user_id !== $loggedInUser->id) {
            return $this->json('Cannot submit quiz answer', null, 403);
        }

        $quiz = $quizSession->quiz;
        $answer = $request->answer;

        $seenQuestionIds = json_decode($quizSession->seen_question_ids) ?? [];
        $answeredQuestionIds = json_decode($quizSession->answered_question_ids) ?? [];
        $question = QuestionRepository::query()
            ->where('id', '=', $answer['question_id'])
            ->where('quiz_id', '=', $quiz->id)
            ->first();


        if (
            !$question
            || in_array($question->id, $answeredQuestionIds)
            || !in_array($question->id, $seenQuestionIds)
        ) {
            return $this->json('Invalid question', null, 404);
        }

        $responseMessage = 'Answer submitted successfully';
        $isCorrect = false;

        if (now() > Carbon::parse($quizSession->last_answered_at)->addSeconds($quiz->duration_per_question)) {
            $answer['skip'] = true;
            $responseMessage = 'Answer skipped due to timeout';
        } else {
            $isCorrect = AnswerRepository::storeAndEvaluate($question, $answer);
        }

        // Get the next question
        $questions = QuestionRepository::query()->where('quiz_id', '=', $quiz->id)->get();
        $nextQuestion = $questions->whereNotIn('id', $seenQuestionIds)->isNotEmpty() ? $questions->whereNotIn('id', $seenQuestionIds)->random(1)->first() : null;

        // Update the quiz session state
        QuizSessionRepository::update($quizSession, [
            'seen_question_ids' => $nextQuestion ? json_encode(array_merge($seenQuestionIds, [$nextQuestion?->id])) : json_encode($seenQuestionIds),
            'answered_question_ids' => json_encode(array_merge($answeredQuestionIds, [$question->id])),
            'obtained_mark' => !$answer['skip'] && $isCorrect ? $quizSession->obtained_mark + $quiz->mark_per_question : $quizSession->obtained_mark,
            'right_answer_count' => !$answer['skip'] && $isCorrect ? $quizSession->right_answer_count + 1 : $quizSession->right_answer_count,
            'wrong_answer_count' => !$answer['skip'] && !$isCorrect ? $quizSession->wrong_answer_count + 1 : $quizSession->wrong_answer_count,
            'skipped_answer_count' => $answer['skip'] ? $quizSession->skipped_answer_count + 1 : $quizSession->skipped_answer_count,
            'last_answered_at' => now(),
        ]);

        return $this->json($responseMessage, [
            'quiz_session' => QuizSessionResource::make($quizSession),
            'previous_was_correct' => $isCorrect,
            'question' => $nextQuestion ? QuestionResource::make($nextQuestion) : null
        ], 201);
    }
}