Archives
Trending
Support
Login
clear text
XML
Django
JavaScript
MATLAB
C
C++
C#
Python
SQL
Shell
Bash
Markdown
YAML
JSON
HTML
CSS
PHP
Java
Ruby
Go
Rust
Swift
Kotlin
Arduino
TypeScript
Perl
Autohotkey
Lua
SQF
R
Scala
Haskell
Groovy
Dart
Clojure
VB.NET
Objective-C
PowerShell
Bash
CoffeeScript
Verilog
is_restart ? true : false; $progressId = $request->progress_id ?? null; $practiceProgress = null; $lastPracticeProgress = $test->lastUserProgress($progressId); if (!$isRestart && $lastPracticeProgress) { $alreadyTakenTime = $lastPracticeProgress->taken_time ?? 0; $lastPracticeProgress->setRelation('practice', $test); if ($this->examService->hasPracticeTimeExpired( $lastPracticeProgress, $alreadyTakenTime )) { throw new \Exception('Practice time has expired', 403); } if ($lastPracticeProgress->status !== CourseProgress::COMPLETED) { $practiceProgress = $lastPracticeProgress; } else { throw new \Exception('Practice Already Completed', 403); } } else { $practiceProgress = $this->examService->createPracticeProgress($test, $request->exam_time_type); } $modules = $test->modules; $module = $modules->first(); $moduleProgress = $this->examService->getOrCreateModuleProgress($module, $practiceProgress); $totalQuestions = $modules->sum(fn ($m) => $m->settings['totalQuestions']); $data = [ 'test' => [ 'name' => $test->name, 'description' => $test->description, 'max_attempts' => $test->max_attempts ], 'module' => [ 'progress_id' => $moduleProgress->id, 'name' => $module->name, 'directions' => $module->directions, 'isCalculatorEnable' => $module->is_calculator == 1 ], 'progress_id' => $practiceProgress->id, 'taken_time' => $practiceProgress->taken_time, 'totalNumberOfQuestions' => $totalQuestions, 'allowed_time' => (optional($test->markingAndTimeAllocation)->value['total_exam_time'] ?? 0), ]; // dd($module->settings['readingComprehension']); if ($module->subject->slug == 'ela') { $readingCompSection = $module->settings['readingComprehension']; $moduleProgress->update(['get_module' => 'readingComprehension']); $passage = $readingCompSection['passages'][0]; if ($passage['type'] == 'passage') { $quiz = QuestionBank::find($module->settings['selectedBankId']) ->quizzes() ->with(['quizzes' => function ($query) use ($passage) { $query->with(['options'])->limit($passage['numQuestion']); }]) ->where('quizzes.is_grouped_question', 1) ->whereNull('quizzes.parent_id') ->where('quizzes.type', $passage['format']) ->where('quizzes.difficulty', 'medium') ->first(); if($quiz && $quiz->quizzes) { $this->examService->getOrCreateGivenAnswer($quiz->quizzes, $moduleProgress); $quiz->quizzes->each(function ($q, $i) use ($quiz) { $q->no = $i + 1; $q->setRelation('parent', (new Quiz())->forceFill([ 'description' => $quiz->description ])); }); $data['module']['question'] = QuizResource::collection($quiz->quizzes); } else { $data['module']['question'] = []; } } else { $quiz = QuestionBank::find($module->settings['selectedBankId']) ->quizzes() ->with('options') // ->where('quizzes.is_grouped_question', 1) ->whereNull('quizzes.parent_id') ->where('quizzes.type', $passage['format']) ->where('quizzes.difficulty', 'medium') ->first(); if($quiz) { $this->examService->getOrCreateGivenAnswer($quiz, $moduleProgress); $quiz->no = 1; $data['module']['question'] = QuizResource::make($quiz); } else { $data['module']['question'] = []; } } } else { $questionFormat = $module->settings['questionFormats'][0]['key']; $quiz = QuestionBank::find($module->settings['selectedBankId']) ->quizzes() ->with(['options', 'parent.quizzes.options']) ->where('quizzes.is_grouped_question', 0) ->whereNull('quizzes.parent_id') ->where('quizzes.type', $questionFormat) ->where('quizzes.difficulty', 'easy') ->inRandomOrder() ->first(); $this->examService->getOrCreateGivenAnswer($quiz, $moduleProgress); $data['module']['question'] = $quiz->parent ? QuizResource::collection($quiz->parent->quizzes) : QuizResource::make($quiz); } /* $data = [ 'test' => [ 'name' => $test->name, 'description' => $test->description, 'max_attempts' => $test->max_attempts ], 'module' => [ 'progress_id' => $moduleProgress->id, 'name' => $module->name, 'directions' => $module->directions, 'question' => $quiz->parent ? QuizResource::collection($quiz->parent->quizzes) : QuizResource::make($quiz), ], 'progress_id' => $practiceProgress->id, 'taken_time' => $practiceProgress->taken_time, 'totalNumberOfQuestions' => $totalQuestions, 'allowed_time' => (optional($test->markingAndTimeAllocation)->value['total_exam_time'] ?? 0), ]; */ return $data; } /** * SUBMIT ANSWER */ public function submitAnswer($practice_progress, $currentModuleProgress, $givenAnswer, $takenTime, $answer) { $timeType = $practice_progress->time_type; $isTimeEnd = $this->examService->checkHasExamTimeEnd($takenTime, $timeType, $practice_progress->adaptivetest); if ($isTimeEnd) { throw new \Exception('Module exam time limit exceeded', 403); } $quiz = $givenAnswer->quiz; $isCorrect = $this->matcher->checkAnswer($quiz->type, $quiz, $answer); $givenAnswer->update([ 'selected_option' => request('selected_option') ?? null, 'answer' => request('answer') ?? null, 'is_watched' => true, 'is_correct' => $isCorrect, 'score' => $isCorrect ? $quiz->credit : 0 ]); $practice_progress->update(['taken_time' => $takenTime]); return $this->nextQuestion($practice_progress, $currentModuleProgress, $quiz, $isCorrect); } /** * NEXT QUESTION LOGIC */ public function nextQuestion($practice_progress, $moduleProgress, $currentQuiz, $isCorrect) { // Handle grouped quiz if ( $currentQuiz->parent && $moduleProgress->givenAnswers() ->whereIn('quiz_id', $currentQuiz->parent->quizzes->pluck('id')) ->where('is_watched', false) ->exists() ) { return []; } $answeredQuizIds = $moduleProgress->givenAnswers()->pluck('quiz_id')->toArray(); // TODO:: use n1 query for given answers $module = $moduleProgress->adaptiveModule; $moduleIds = $practice_progress ->adaptiveModuleProgresses ->pluck('adaptive_module_id') ->toArray(); $isNewModule = false; // Module completion check if (count($answeredQuizIds) >= $module->settings['totalQuestions']) { $isNewModule = true; $answeredQuizIds = []; $module = $practice_progress->adaptivetest->modules() ->with('subject:id,slug') ->whereNotIn('id', $moduleIds) ->first(); if (!$module) return []; $moduleIds[] = $module->id; $moduleProgress = $this->examService->getOrCreateModuleProgress($module, $practice_progress); } $data = [ 'progress_id' => $moduleProgress->id, 'name' => $module->name, 'directions' => $module->directions, 'isCalculatorEnable' => $module->is_calculator == 1, 'isNewModule' => $isNewModule ]; if ($module->subject->slug == 'ela') { // Difficulty logic $levels = ['easy', 'medium', 'hard']; //get current section $getModuleSection = $moduleProgress->get_module; if($getModuleSection == 'readingComprehension') { $currentSection = $module->settings[$moduleProgress->get_module]; } else { [$secName, $secPart] = explode('-', $getModuleSection); $currentSection = $module->settings[$secName][$secPart]; } if ($currentQuiz->parent) { $qIds = $currentQuiz->parent->quizzes->pluck('id'); //siblings quiz ids $totalCorrectAnswer = $moduleProgress->givenAnswers()->whereIn('quiz_id', $qIds->toArray())->where('is_correct', true)->count(); $correctAnsParcentage = ($totalCorrectAnswer / $qIds->count()) * 100; //checking current section total question //get given passages ids $passageIds = $moduleProgress->givenAnswers()->with('quiz:id,parent_id')->get()->pluck('quiz.parent_id')->unique(); // get current answer passage $currentPassage = collect($currentSection['passages']) ->where('type', 'passage')->where('format', $currentQuiz->parent->type) ->first(); // get given passages $usedType = Quiz::whereIn('id', $passageIds)->pluck('type'); //get current difficulty $diffIndex = array_search($currentQuiz->parent->difficulty, $levels); //get next difficulty if ($correctAnsParcentage >= 50 && $isCorrect) { $diffIndex = min($diffIndex + 1, 2); } else { $diffIndex = max($diffIndex - 1, 0); } $nextDifficulty = $levels[$diffIndex]; //checking next hard question available if ($nextDifficulty == 'hard') { // checking hardness parcentage $totalHardQuestionGiven = Quiz::whereIn('id', $passageIds->toArray())->where('difficulty', 'hard')->count(); // dd($counthard, $currentSection['totalQuestions'], $module->settings['hardnessPercentage']); $hardParcentageGiven = intval(($totalHardQuestionGiven / $currentSection['totalQuestions']) * 100); //is available to give hard type question $isAvailableToGiveHard = $hardParcentageGiven < $module->settings['hardnessPercentage']; if (!$isAvailableToGiveHard) { $nextDifficulty = $levels[$diffIndex - 1]; } } //count current type passage $currentGivenPassageCount = $usedType->filter(fn ($item) => $item === $currentPassage['format'])->count(); //check given passage greater than current passage // dd($currentGivenPassageCount); if ($currentGivenPassageCount < $currentPassage['numPassage']) { $quiz = QuestionBank::find($module->settings['selectedBankId']) ->quizzes() ->with(['quizzes' => function ($query) use ($currentPassage) { $query->with(['options'])->limit($currentPassage['numQuestion']); }]) ->whereNotIn('quizzes.id', $passageIds->toArray()) ->where('quizzes.is_grouped_question', 1) ->whereNull('quizzes.parent_id') ->where('quizzes.type', $currentPassage['format']) ->where('quizzes.difficulty', $nextDifficulty) ->first(); if($quiz && $quiz->quizzes) { $this->examService->getOrCreateGivenAnswer($quiz->quizzes, $moduleProgress); $quiz->quizzes->each(function ($q, $i) use ($quiz, $answeredQuizIds) { $q->no = count($answeredQuizIds) + $i + 1; $q->setRelation('parent', (new Quiz())->forceFill([ 'description' => $quiz->description ])); }); $data['question'] = QuizResource::collection($quiz->quizzes); } else { logger("1, not found for" . $currentPassage['format'] . $nextDifficulty); $data['question'] = []; } } else { //next pasage finding for current given passage limit exceed $allFormats = collect($currentSection['passages'])->pluck('format'); $nextPassageIndex = $allFormats->search($currentQuiz->parent->type); if ($allFormats->count() > $nextPassageIndex + 1) { $next = $currentSection['passages'][$nextPassageIndex + 1]; if ($next['type'] == 'passage') { $quiz = QuestionBank::find($module->settings['selectedBankId']) ->quizzes() ->with(['quizzes' => function ($query) use ($next) { $query->with(['options'])->limit($next['numQuestion']); }]) // ->whereNotIn('quizzes.id', $passageIds->toArray()) ->where('quizzes.is_grouped_question', 1) ->whereNull('quizzes.parent_id') ->where('quizzes.type', $next['format']) ->where('quizzes.difficulty', $nextDifficulty) ->first(); if($quiz && $quiz->quizzes) { $this->examService->getOrCreateGivenAnswer($quiz->quizzes, $moduleProgress); $quiz->quizzes->each(function ($q, $i) use ($quiz, $answeredQuizIds) { $q->no = count($answeredQuizIds) + $i + 1; $q->setRelation('parent', (new Quiz())->forceFill([ 'description' => $quiz->description ])); }); $data['question'] = QuizResource::collection($quiz->quizzes); } else { logger("2, not found for" . $next['format'] . $nextDifficulty); $data['question'] = []; } } else { $quiz = QuestionBank::find($module->settings['selectedBankId']) ->quizzes() ->with('options') // ->where('quizzes.is_grouped_question', 1) ->whereNotIn('quizzes.id', $answeredQuizIds) ->whereNull('quizzes.parent_id') ->where('quizzes.type', $next['format']) ->where('quizzes.difficulty', $nextDifficulty) ->first(); if($quiz) { $this->examService->getOrCreateGivenAnswer($quiz, $moduleProgress); $quiz->no = count($answeredQuizIds) + 1; $data['question'] = QuizResource::make($quiz); } else { logger("3, not found for" . $next['format'] . $nextDifficulty); $data['question'] = []; } } } else { //change section if($moduleProgress->get_module == 'readingComprehension') { $next = 'revisionEditing-partA'; $moduleProgress->update(['get_module' => $next]); //call function for next section question } else if($moduleProgress->get_module == 'revisionEditing-partA') { $next = 'revisionEditing-partB'; $moduleProgress->update(['get_module' => $next]); //call function for next section question } else { // end of module return [];// next module load and give question } } } } else { $currentFormat = collect($currentSection['passages']) ->where('type', 'question')->where('format', $currentQuiz->type) ->first(); $diffIndex = array_search($currentQuiz->difficulty, $levels); if ($isCorrect) { $diffIndex = min($diffIndex + 1, 2); } else { $diffIndex = max($diffIndex - 1, 0); } $nextDifficulty = $levels[$diffIndex]; $givenAnsIds = $moduleProgress->givenAnswers()->whereHas('quiz', fn ($q) => $q->whereNull('parent_id'))->pluck('quiz_id'); if ($nextDifficulty == 'hard') { // checking hardness parcentage $totalHardQuestionGiven = Quiz::whereIn('id', $givenAnsIds->toArray())->where('difficulty', 'hard')->count(); // dd($counthard, $currentSection['totalQuestions'], $module->settings['hardnessPercentage']); $hardParcentageGiven = intval(($totalHardQuestionGiven / $currentSection['totalQuestions']) * 100); //is available to give hard type question $isAvailableToGiveHard = $hardParcentageGiven < $module->settings['hardnessPercentage']; if (!$isAvailableToGiveHard) { $nextDifficulty = $levels[$diffIndex - 1]; } } $givenQuestionIds = $moduleProgress->givenAnswers()->where('type', $currentQuiz->type)->pluck('quiz_id'); if ($givenQuestionIds->count() < $currentFormat['numQuestion']) { $quiz = QuestionBank::find($module->settings['selectedBankId']) ->quizzes() ->with('options') ->whereNotIn('quizzes.id', $givenQuestionIds->toArray()) ->whereNull('quizzes.parent_id') ->where('quizzes.type', $currentFormat['format']) ->where('quizzes.difficulty', $nextDifficulty) ->first(); if($quiz) { $this->examService->getOrCreateGivenAnswer($quiz, $moduleProgress); $data['question'] = QuizResource::make($quiz); } else { logger("4, not found for" . $currentFormat['format'] . $nextDifficulty); $data['question'] = []; } } else { $allFormats = collect($currentSection['passages'])->pluck('format'); $nextFormatIndex = $allFormats->search($currentQuiz->type); if ($allFormats->count() > $nextFormatIndex + 1) { $next = $currentSection['passages'][$nextFormatIndex + 1]; if ($next['type'] == 'passage') { $quiz = QuestionBank::find($module->settings['selectedBankId']) ->quizzes() ->with(['quizzes' => function ($query) use ($next) { $query->with(['options'])->limit($next['numQuestion']); }]) ->where('quizzes.is_grouped_question', 1) ->whereNull('quizzes.parent_id') ->where('quizzes.type', $next['format']) ->where('quizzes.difficulty', $nextDifficulty) ->first(); if($quiz && $quiz->quizzes) { $this->examService->getOrCreateGivenAnswer($quiz->quizzes, $moduleProgress); $quiz->quizzes->each(function ($q) use ($quiz) { $q->setRelation('parent', (new Quiz())->forceFill([ 'description' => $quiz->description ])); }); $data['question'] = QuizResource::collection($quiz->quizzes); } else { logger("5, not found for" . $next['format'] . $nextDifficulty); $data['question'] = []; } } else { $quiz = QuestionBank::find($module->settings['selectedBankId']) ->quizzes() ->with('options') // ->where('quizzes.is_grouped_question', 1) ->whereNull('quizzes.parent_id') ->where('quizzes.type', $next['format']) ->where('quizzes.difficulty', $nextDifficulty) ->first(); if($quiz) { $this->examService->getOrCreateGivenAnswer($quiz, $moduleProgress); $data['question'] = QuizResource::make($quiz); } else { logger("6, not found for" . $next['format'] . $nextDifficulty); $data['question'] = []; } } } else { //next section } } } // $nextDifficulty = $levels[$isCorrect ? min($diffIndex + 1, 2) : max($diffIndex - 1, 0)]; } else { $bank = QuestionBank::with('quizzes:id,type,question_type,difficulty,is_grouped_question,parent_id') ->find($module->settings['selectedBankId']); $questionFormats = collect($module->settings['questionFormats']); $questionTypes = collect($module->settings['questionTopics']); // Difficulty logic $levels = ['easy', 'medium', 'hard']; $diffIndex = array_search($currentQuiz->difficulty, $levels); $nextDifficulty = $levels[$isCorrect ? min($diffIndex + 1, 2) : max($diffIndex - 1, 0)]; // Track reached limits $usedTypes = $questionFormats->filter( fn ($f) => $moduleProgress->givenAnswers() ->whereHas('quiz', fn ($q) => $q->where('type', $f['key'])) ->count() >= $f['value'] )->pluck('key')->toArray(); $usedQtypes = $questionTypes->filter( fn ($qt) => $moduleProgress->givenAnswers() ->whereHas('quiz', fn ($q) => $q->where('question_type', $qt['key'])) ->count() >= $qt['value'] )->pluck('key')->toArray(); // Find next quiz within limits $quiz = $bank->quizzes() ->whereNotIn('quizzes.id', $answeredQuizIds) ->whereNotIn('quizzes.type', $usedTypes) ->whereNotIn('quizzes.question_type', $usedQtypes) ->where('quizzes.is_grouped_question', false) ->whereNull('quizzes.parent_id') ->where('quizzes.difficulty', $nextDifficulty) ->inRandomOrder() ->first(); // If not found, move to next module if (!$quiz) { $nextModule = $practice_progress->adaptivetest->modules() ->whereNotIn('id', $moduleIds)->first(); if (!$nextModule) return []; $isNewModule = true; $moduleProgress = $this->examService->getOrCreateModuleProgress($nextModule, $practice_progress); $bank = QuestionBank::with('quizzes')->find($nextModule->settings['selectedBankId']); $quiz = $bank->quizzes() ->where('quizzes.is_grouped_question', false) ->whereNull('parent_id') ->where('difficulty', $nextDifficulty) ->inRandomOrder() ->first(); if (!$quiz) return []; } $this->examService->getOrCreateGivenAnswer($quiz, $moduleProgress); } return $data; } }
Mark as private (unlisted)
for 30 minutes
for 6 hours
for 1 day
for 1 week
for 1 month
for 1 year
everlasting (like CCCP)