السلام عليكم جمعة مباركة إن شاء الله
مشكلتي في صفحة الاختبارات، عند الانتقال من سؤال لآخر في اختبار الاستماع، يتم تحديث الرابط ولكن الصوت لا يتغير. وأعتقد أن المشكلة تكمن في ذاكرة التخزين المؤقت (Cache). هل يمكنكم المساعدة في حل هذه المشكلة؟
علما أنني أستخدم إطار عمل laravel مع livewire
@elseif($questions[$currentQuestionIndex]->type =='record_voice')<audio id="question-audio" controls><source
src="{{ asset('audio/'.$questions[$currentQuestionIndex]->question_text) }}?v={{ $questions[$currentQuestionIndex]->updated_at->timestamp }}"// src="{{ $audioSource }}"
type="audio/mpeg">Your browser does not support the audio element.</audio>@endif
يتم اختيار سؤال الحالي عن طريق الكورنت اندكس الذي يستخرجه من مصفوفه الاسئله المشكله تكون فقط اذا كان اكثر من سؤال فيه ملف صوتي بحيث بقيه الاسئله تاخذ نفس المقطع الصوتي السابق رغم اني طبعت الرابط ولاحظت ان الرابط يتغير كل مره لكن الملف الصوتي يظل هو هو جربت كم من طريقه لم تفلح معي انتم تعرفون ان الصفحه لا يتم تحديثها في اللايف وير ربما هذه هي المشكله
$questions[$currentQuestionIndex]
يتم تغيير الاندكس الخاص بالسؤال الحالي في متحكم لايف وير في حال إنتقل المستخدم من سؤال لآخر سواء ذهابا أم إيابا و إذا كان آخر سؤال يتم إرسال الأجوبة أو إذا إنتهى الوقت سأرفق لكم الشيفة الخاصة بالمتحكم وصفحة العرض لايفوير
صفحة العرض :
<divclass="page-body dark:bg-black dark:text-white bg-gray-200 mb-12 px-8 border h-full grid grid-cols-4 gap-2 p-20">
{{-- 1 --}}
<imgsrc="{{ asset('storage/online2.png') }}"alt=""class="flex m-auto col-span-1"><divclass="sec-question col-span-3 px-16"><divclass="border-4 border-white dark:border-2 p-4 rounded-lg">
{{-- Step and Exam information --}}
<divclass="space-x-32 relative px-1 m-auto"><!-- Display the current queepion number and the total number of questions --><divclass="total-number text-2xl text-red-400 font-bold absolute left-5">
{{ $currentQuestionIndex + 1 }}/{{ $questions->count() }}</div><!-- Display the name of the exam --><divclass="exam-number font-bold right-5 absolute">{{ $exam->name }}</div></div>
{{-- Divider --}}
<hrclass="w-[94%] h-1 my-10 border-white text-white m-auto flex">
{{-- Question and Time --}}
<divclass="justify-between text-clip flex"><divclass="question-part font-bold px-7 mr-16 text-2xl overflow-wrap-anywhere">
{{ $questions[$currentQuestionIndex]->question }}</div><divclass="time-down font-bold text-lg"><divid="taim"class="taim flex gap-x-2 "><divclass="circle relative w-28 h-28 justify-center flex items-center"><divclass="dots hours absolute w-full h-full rounded-[50%] flex justify-center items-start z-[1000] before:w-3 before:h-3 before:absolute before:top-[02px] before:bg-amber-600 before:rounded-[50%] before:shadow-[0_0_20px_rgb(202_138_4)_,_0_0_60px_rgb(202_138_4)] "></div><svgclass="relative w-28 h-28 rotate-[270deg] "><circleclass="w-full h-full fill-transparent stroke-[8] stroke-stone-900 translate-x-1 translate-y-1"cx="50"cy="50"r="50"></circle><circlestroke-dashoffset="440"stroke-dasharray="440"class=" w-full h-full fill-transparent stroke-[8] stroke-amber-600 translate-x-1 translate-y-1"cx="50"cy="50"r="50"id="hh"></circle></svg><divclass="absolute text-center font-[500] text-[1.5rem] text-gray-800"id="hours">
00<br><spanclass="uppercase text-gray-900 absolute translate-x-[-50%] translate-y-[-10px] text-[0.65rem] font-[500] tracking-[0.1rem]">hours</span></div></div><divclass="circle relative w-28 h-28 justify-center flex items-center "><divclass="dots minutes absolute w-full h-full rounded-[50%] flex justify-center items-start z-[1000] before:w-3 before:h-3 before:absolute before:top-[02px] before:bg-green-600 before:rounded-[50%] before:shadow-[0_0_20px_rgb(22_163_74)_,_0_0_60px_rgb(22_163_74)] "></div><svgclass="relative w-28 h-28 rotate-[270deg] "><circleclass="w-full h-full fill-transparent stroke-[8] stroke-stone-900 translate-x-1 translate-y-1"cx="50"cy="50"r="50"></circle><circlestroke-dashoffset="300"stroke-dasharray="612"class=" w-full h-full fill-transparent stroke-[8] stroke-green-600 translate-x-1 translate-y-1"cx="50"cy="50"r="50"id="mm"></circle></svg><divclass="absolute text-center font-[500] text-[1.5rem] text-gray-800"id="minutes">
00<br><spanclass="uppercase text-gray-900 absolute translate-x-[-50%] translate-y-[-10px] text-[0.65rem] font-[500] tracking-[0.1rem]">minutes</span></div></div><divclass="circle relative w-28 h-28 justify-center flex items-center "><divclass="dots seconds absolute w-full h-full rounded-[50%] flex justify-center items-start z-[1000] before:w-3 before:h-3 before:absolute before:top-[02px] before:bg-purple-500 before:rounded-[50%] before:shadow-[0_0_20px_rgb(168_85_247)_,_0_0_60px_rgb(168_85_247)] "></div><svgclass="relative w-28 h-28 rotate-[270deg] "><circleclass="w-full h-full fill-transparent stroke-[8] stroke-stone-900 translate-x-1 translate-y-1"cx="50"cy="50"r="50"></circle><circlestroke-dashoffset="300"stroke-dasharray="612"class=" w-full h-full fill-transparent stroke-[8] stroke-purple-500 translate-x-1 translate-y-1"cx="50"cy="50"r="50"id="ss"></circle></svg><divclass="absolute text-center font-[500] text-[1.5rem] text-gray-800"id="seconds">00
</div></div></div></div><script>var remainingTime = localStorage.getItem('remainingTime')||{{ $remainingTime }};var initialTime ={{ $remainingTime }};// Define a function to update the remaining timefunction updateRemainingTime(){// Check if the exam time has expiredif(remainingTime <=0){// If so, submit the answers// Livewire.emit('sendAnswersToServer');
console.log('exam finish');@this.call('sendAnswersToServer');
localStorage.removeItem('remainingTime');}else{// Otherwise, decrement the remaining time by 1 second
remainingTime = remainingTime -1;// @this.call('updatePivotTable', remainingTime);// Update the remaining time displayed on the pagevar minutes =Math.floor(remainingTime /60);var seconds = remainingTime %60;
document.getElementById('minutes').innerHTML = minutes +'<br> <span class="uppercase text-gray-900 absolute translate-x-[-50%] translate-y-[-10px] text-[0.65rem] font-[500] tracking-[0.1rem]">menutes</span>';
document.getElementById('seconds').innerHTML =(seconds <10?"0":"")+ seconds +'<br> <span class="uppercase text-gray-900 absolute translate-x-[-50%] translate-y-[-10px] text-[0.65rem] font-[500] tracking-[0.1rem]">seconds</span>';// retrieve the circle element by its idvar myHCircle = document.getElementById('hh');var myMCircle = document.getElementById('mm');var mySCircle = document.getElementById('ss');// set the new stroke-dashoffset value// mySCircle.setAttribute('stroke-dashoffset', 440 - (440 * minutes) / 60);
myMCircle.setAttribute('stroke-dasharray',312+(300* minutes)/(initialTime /60));
mySCircle.setAttribute('stroke-dasharray',312+(300* seconds)/60);// formatTime(remainingTime);// document.getElementById('remainingTime').innerHTML = // Store the remaining time in local storage
localStorage.setItem('remainingTime', remainingTime);// Call the updateRemainingTime function again after 1 second
setTimeout(updateRemainingTime,1000);}}// Use setTimeout to update the remaining time after the exam has started
document.addEventListener('livewire:load',function(){
console.log('Livewire loaded');
setTimeout(updateRemainingTime,1000);});</script></div>
@if ($questions[$currentQuestionIndex]->type == 'fill')
<divclass="mt-8 font-bold px-10">
@php
$listItems = $questions[$currentQuestionIndex]->blanks;
$text = $questions[$currentQuestionIndex]->question_text;
$fillQuestion = '';
for ($i = 1; $i < count($listItems) + 1; $i++) {
if (strpos($text, '[__]')) {
$fillQuestion = '<inputtype="text"class="m-1 text-center space-x-5 bg-inherit shadow border-none h-8 focus:ring-0 p-4 w-fit"placeholder="_ _ _ _ _ _ _ _ _"name="' . $i . '__blank"wire:model.lazy="fill_answers.' . $currentQuestionIndex . '.' . $i . '">';
$text = substr_replace($text, $fillQuestion, strpos($text, '[__]'), 4);
}
}
echo $text;
@endphp
{{-- <buttontype="submit"wire:click="saveInputs">submit</button> --}}
@foreach ($fill_answers as $key => $items)
{{ $key . ':' }}
@foreach ($items as $item)
{{ $item }}
@endforeach
@endforeach
</div>
@elseif($questions[$currentQuestionIndex]->type == 'Multiple_choice')
{{-- Answers --}}
<divclass="answers mt-8"><ulclass="px-8">
{{-- Previous answer --}}
@if (isset($currentAnswers[$questions[$currentQuestionIndex]->id]))
@if (array_key_exists($questions[$currentQuestionIndex]->id, $currentAnswers))
<h1>Your previous answer</h1>
@php
$answer = $all_answers->where('id', $currentAnswers[$questions[$currentQuestionIndex]->id])->first();
@endphp
<liclass="my-2 w-full p-4 font-bold text-lg border rounded-lg dark:text-white/60 dark:font-semibold text-[#523b92] dark:border-white hover:text-white bg-red-400">
{{ $answer->answer }}
</li><hrclass="h-2 bg-slate-400">
@endif
@endif
{{-- Shuffled answers --}}
@php
$shuffledAnswers = collect($all_answers->where('question_id', $questions[$currentQuestionIndex]->id))->shuffle();
@endphp
@foreach ($shuffledAnswers as $key => $item)
<liclass="my-2 cursor-pointer w-full p-4 font-bold text-lg border rounded-lg dark:text-white/60 dark:font-semibold text-[#523b92] dark:border-white border-[#523b92] hover:text-white hover:bg-[#523b92]"wire:click="submitAnswer('{{ $item->id }}')">
{{ $item->answer }}
</li>
@endforeach
</ul></div>
@elseif($questions[$currentQuestionIndex]->type == 'record_voice')
<audioid="question-audio"controls><sourcesrc="{{ $audioSource }}"type="audio/mpeg">
Your browser does not support the audio element.
</audio>
@endif
{{-- Navigation buttons --}}
<divclass="inline-flex justify-around mt-6 w-full"><buttonwire:click="preAnswer()"onclick="stopAudio()"class="bg-orange-500 hover:bg-orange-400 text-white font-bold py-2 px-4 rounded-l"><spanclass="material-symbols-outlined">Undo Prev</span></button>
@if ($questions->count() == $currentQuestionIndex + 1)
<buttonwire:click="submitAnswer()"class="bg-orange-500 hover:bg-orange-400 text-white font-bold py-2 px-4 rounded-r">
Finish Exam
</button>
@else
<buttonwire:click="goToNextQuestionIfPossible()"onclick="stopAudio()"class="bg-orange-500 hover:bg-orange-400 text-white font-bold py-2 px-4 rounded-r"><spanclass="material-symbols-outlined">Redo Next</span></button>
@endif
</div><script>function stopAudio(){var audio = document.getElementById("question-audio");
audio.pause();
audio.currentTime =0;}</script></div></div></div>
المتحكم :
<?php
// In your Questions componentnamespaceApp\Http\Livewire;useApp\Models\Answer;useApp\Models\Exam;useApp\Models\Question;useApp\Models\UserAnswer;useIlluminate\Contracts\Session\Session;useIlluminate\Database\Eloquent\Collection;useLivewire\Component;useIlluminate\Session\SessionManager;useIlluminate\Support\Facades\Auth;classQuestionsextendsComponent{publicExam $exam;publicCollection $questions;publicint $currentQuestionIndex =0;public $all_answers;public $remainingTime;public $fill_answers =[];public $audioSource;// /تحديث الوقت كل ثانية / إحضار جميع الإجاباتpublicfunction mount(){
$this->emit('examStarted');
$this->getAnswers();
$this->getUser();
$this->remainingTime = $this->user->exams->find($this->exam->id)->pivot->time_of_exam *60;}// إحضار جميع الإجاباتpublicfunction getAnswers(){
$this->all_answers =Answer::all();}// المستخد الحالي publicfunction getUser(){
$this->user = auth()->user();}// Define a function to update the remaining timepublicfunction submitAnswer($choiceKey,SessionManager $session){// Get ID for current question
$questionId = $this->questions[$this->currentQuestionIndex]->id;// Get stored answers from session
$storedAnswers = json_decode($session->get('answers','{}'),true);// Check if an answer for this question already existsif(array_key_exists($questionId, $storedAnswers)){// Remove existing answer
unset($storedAnswers[$questionId]);}// Add new answer
$storedAnswers[$questionId]= $choiceKey;// Save updated answers to session
$session->put('answers', json_encode($storedAnswers));if($this->isLastQuestion()){// Send answers to server and redirect to exam result page
$this->sendAnswersToServer();
$session->forget('answers');// exam-result// return redirect()->route('types');}
$this->goToNextQuestionIfPossible();}publicfunction sendAnswersToServer(){// جلب عدد المحاولات المتبقية للامتحان الخاصة بالطالب
$examPivot = $this->user->exams()->where('exam_id', $this->exam->id)->first()->pivot;
$attempts = $examPivot->number_of_submission;if($attempts >0){
$attempts = $attempts -1;}// Save the user's answers
$answers = json_decode(request()->session()->get('answers','{}'),true);
$score =0;
$num_questions = count($answers);// اذا كانت الاجوبة اختيار من متعددif($num_questions >0){foreach($answers as $answerId){// Get the question from the database
$answer =Answer::find($answerId);// Check if the user's answer is correctif($answer->is_correct ==true){
$score++;}}foreach($answers as $question_id => $answer_key){
$answer =newUserAnswer();
$answer->user_id = $this->user->id;
$answer->question_id = $question_id;
$answer->answer_id = $answer_key;
$answer->save();}}// اذا كانت الاجوبة املئ الفراغ if(count($this->fill_answers)){
$questionScore =0;foreach($this->fill_answers as $questionIndex => $fillAnswers){
$question = $this->questions[$questionIndex];foreach($fillAnswers as $index => $answer){// Check if the answer is valid
$answer = strtolower(trim($answer));foreach($question->blanks as $validAnswer){// dd($validAnswer);if(strtolower(trim($validAnswer['text']))=== $answer){// Add score for valid answer
$questionScore +=1/ count($question->blanks);}}}}
$score += $questionScore;}// Update the exam_user pivot table
$examPivot->update(['number_of_submission'=> $attempts,]);
$this->user->exams()->updateExistingPivot($this->exam->id,['score'=> $score,'closed'=>($attempts ==0),]);return redirect()->route('exam.result', $this->exam->id);}publicfunction preAnswer(){
$this->goToPreviousQuestionIfPossible();}publicfunction isLastQuestion():bool{return $this->currentQuestionIndex === $this->questions->count()-1;}publicfunction goToNextQuestionIfPossible(){if($this->canGoToNextQuestion()){
$this->currentQuestionIndex++;
$this->audioSource = asset('audio/'. $this->questions[$this->currentQuestionIndex]->question_text);}}publicfunction goToPreviousQuestionIfPossible(){if($this->canGoToPreviousQuestion()){
$this->currentQuestionIndex--;}}publicfunction canGoToNextQuestion():bool{return $this->currentQuestionIndex < $this->questions->count()-1;}publicfunction canGoToPreviousQuestion():bool{return $this->currentQuestionIndex >0;}// update time every secend publicfunction updatePivotTable($remainingTime){
$this->user->exams()->updateExistingPivot($this->exam->id,['time_of_exam'=> $this->remainingTime]);}publicfunction render(){
$answers = json_decode(request()->session()->get('answers','{}'),true);return view('livewire.questions',['currentAnswers'=> $answers ??null,]);}}
شكرا لكم واتمنى ان تقدموا لي نصائح بشان تحسين الشفره او عن اي اخطاء موجوده فيها او ملاحظات
السؤال
ابراهيم الخليل سماني
السلام عليكم جمعة مباركة إن شاء الله
مشكلتي في صفحة الاختبارات، عند الانتقال من سؤال لآخر في اختبار الاستماع، يتم تحديث الرابط ولكن الصوت لا يتغير. وأعتقد أن المشكلة تكمن في ذاكرة التخزين المؤقت (Cache). هل يمكنكم المساعدة في حل هذه المشكلة؟
علما أنني أستخدم إطار عمل laravel مع livewire
يتم اختيار سؤال الحالي عن طريق الكورنت اندكس الذي يستخرجه من مصفوفه الاسئله المشكله تكون فقط اذا كان اكثر من سؤال فيه ملف صوتي بحيث بقيه الاسئله تاخذ نفس المقطع الصوتي السابق رغم اني طبعت الرابط ولاحظت ان الرابط يتغير كل مره لكن الملف الصوتي يظل هو هو جربت كم من طريقه لم تفلح معي انتم تعرفون ان الصفحه لا يتم تحديثها في اللايف وير ربما هذه هي المشكله
يتم تغيير الاندكس الخاص بالسؤال الحالي في متحكم لايف وير في حال إنتقل المستخدم من سؤال لآخر سواء ذهابا أم إيابا و إذا كان آخر سؤال يتم إرسال الأجوبة أو إذا إنتهى الوقت سأرفق لكم الشيفة الخاصة بالمتحكم وصفحة العرض لايفوير
صفحة العرض :
المتحكم :
شكرا لكم واتمنى ان تقدموا لي نصائح بشان تحسين الشفره او عن اي اخطاء موجوده فيها او ملاحظات
تم التعديل في بواسطة Mustafa Suleimanتنسيق النص
8 أجوبة على هذا السؤال
Recommended Posts
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.