diff --git a/Penilaian Literasi/iClOP-V2/app/Http/Controllers/Literacy/LiteracyAssessmentController.php b/Penilaian Literasi/iClOP-V2/app/Http/Controllers/Literacy/LiteracyAssessmentController.php index e245fa3..05df739 100644 --- a/Penilaian Literasi/iClOP-V2/app/Http/Controllers/Literacy/LiteracyAssessmentController.php +++ b/Penilaian Literasi/iClOP-V2/app/Http/Controllers/Literacy/LiteracyAssessmentController.php @@ -5,9 +5,13 @@ use App\Http\Controllers\Controller; use App\Models\Literacy\LiteracyAssessment; use App\Models\Literacy\LiteracyQuestion; +use App\Models\Literacy\LiteracyMaterial; +use App\Models\Literacy\LiteracyOption; use App\Models\Literacy\LiteracyAnswer; +use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Log; class LiteracyAssessmentController extends Controller { @@ -38,11 +42,31 @@ public function index() public function start($id) { $assessment = LiteracyAssessment::where('id', $id) - ->where('user_id', Auth::id()) // Pastikan hanya asesmen milik student tersebut + ->where('user_id', Auth::id()) ->firstOrFail(); + // Ubah status asesmen menjadi in_progress $assessment->update(['status' => 'in_progress']); + // Ambil semua pertanyaan terkait asesmen ini + $questions = LiteracyQuestion::all(); // Sesuaikan jika ada filter + + // Insert jawaban kosong jika belum ada + foreach ($questions as $question) { + LiteracyAnswer::updateOrInsert( + [ + 'assessment_id' => $assessment->id, + 'question_id' => $question->id, + ], + [ + 'option_id' => null, + 'answer_text' => null, + 'created_at' => now(), + 'updated_at' => now(), + ] + ); + } + return redirect()->route('literacy_assessments_show', $id); } @@ -56,7 +80,13 @@ public function show($id) ->firstOrFail(); // Ambil semua pertanyaan, urutkan pilihan ganda dulu baru essay - $questions = LiteracyQuestion::orderByRaw("FIELD(type, 'multiple_choice', 'essay')")->get(); + $questions = LiteracyQuestion::orderByRaw("FIELD(type, 'multiple_choice', 'essay')") + ->with([ + 'answers' => function ($query) use ($id) { + $query->where('assessment_id', $id); + } + ]) + ->get(); return view('literacy.student.assessments.assessment', compact('assessment', 'questions')); } @@ -76,40 +106,178 @@ public function continue($id) /** * Menyimpan jawaban siswa ke database secara otomatis saat memilih atau mengisi jawaban. */ - public function storeAnswer(Request $request, $assessmentId) + public function storeAnswer(Request $request, $assessmentId): JsonResponse { + Log::info('Request Data:', $request->all()); + $request->validate([ 'question_id' => 'required|exists:literacy_questions,id', 'answer' => 'nullable|string', ]); + // Pastikan pengguna memiliki asesmen ini $assessment = LiteracyAssessment::where('id', $assessmentId) ->where('user_id', Auth::id()) - ->firstOrFail(); + ->first(); + + if (!$assessment) { + return response()->json(['error' => 'Asesmen tidak ditemukan'], 404); + } + + $questionId = $request->question_id; + $answerValue = $request->answer; + + $question = LiteracyQuestion::find($questionId); + if (!$question) { + return response()->json(['error' => 'Pertanyaan tidak ditemukan'], 404); + } + + $answerData = ['option_id' => null, 'answer_text' => $answerValue]; + + if ($question->type === 'multiple_choice') { + $option = LiteracyOption::where('id', $answerValue) + ->where('question_id', $questionId) + ->first(); + + if (!$option) { + return response()->json(['error' => 'Jawaban tidak valid'], 400); + } + + $answerData = ['option_id' => $option->id, 'answer_text' => null]; + } - // Simpan atau update jawaban siswa LiteracyAnswer::updateOrCreate( [ 'assessment_id' => $assessment->id, - 'user_id' => Auth::id(), - 'question_id' => $request->question_id, + 'question_id' => $questionId, ], - [ - 'answer' => $request->answer, - ] + $answerData ); - // Cek apakah semua pertanyaan telah dijawab - $totalQuestions = LiteracyQuestion::count(); + // Hitung jumlah pertanyaan dalam asesmen ini + $totalQuestions = $assessment->questions()->count(); + + // Hitung jumlah pertanyaan yang sudah dijawab $answeredQuestions = LiteracyAnswer::where('assessment_id', $assessment->id) - ->whereNotNull('answer') + ->where(function ($query) { + $query->whereNotNull('option_id') + ->orWhere('answer_text', '!=', ''); + }) ->count(); - // Jika semua pertanyaan sudah dijawab, ubah status asesmen menjadi "completed" + Log::info('Answered Questions:', ['answered' => $answeredQuestions, 'total' => $totalQuestions]); + + // Jika semua pertanyaan sudah dijawab, update status ke `completed` if ($answeredQuestions >= $totalQuestions) { $assessment->update(['status' => 'completed']); } return response()->json(['success' => true]); } + + public function submitAssessment($id) + { + try { + $user = Auth::user(); + $assessment = LiteracyAssessment::where('id', $id) + ->where('user_id', $user->id) + ->firstOrFail(); + + if ($assessment->status !== 'in_progress') { + return response()->json(['error' => 'Asesmen tidak sedang berjalan.'], 400); + } + + $answers = LiteracyAnswer::where('assessment_id', $id)->get(); + + $correctWeight = 0; // Total bobot jawaban benar + $totalWeight = 0; // Total bobot semua soal + + foreach ($answers as $answer) { + $question = LiteracyQuestion::find($answer->question_id); + if (!$question) + continue; + + $weight = $question->weight ?? ($question->type === 'essay' ? 5 : 1); + $totalWeight += $weight; // Tambah bobot soal ke total + + if ($question->type === 'multiple_choice') { + // Cek apakah jawaban pilihan ganda benar + if ($answer->option_id && LiteracyOption::where('id', $answer->option_id)->where('is_correct', true)->exists()) { + $correctWeight += $weight; + } + } elseif ($question->type === 'essay') { + // Ambil kunci jawaban esai + $correctAnswer = strtolower(trim($question->essay_answer)); + $userAnswer = strtolower(trim($answer->answer_text)); + + // Jika jawaban sama persis, beri skor penuh + if ($userAnswer === $correctAnswer) { + $correctWeight += $weight; + } + } + } + + // Hitung skor akhir berdasarkan bobot + $score = $totalWeight > 0 ? ($correctWeight / $totalWeight) * 100 : 0; + + // Simpan skor dan ubah status asesmen ke 'completed' + $assessment->update([ + 'score' => round($score, 2), + 'status' => 'completed', + 'assessed_at' => now(), + ]); + + // Buat asesmen baru untuk percobaan berikutnya + LiteracyAssessment::create([ + 'user_id' => $user->id, + 'status' => 'pending', + 'score' => null, + 'feedback' => '', + 'assessed_at' => null, + 'created_at' => now(), + 'updated_at' => now(), + ]); + + return response()->json(['message' => 'Asesmen berhasil diselesaikan.', 'score' => round($score, 2)], 200); + + } catch (\Exception $e) { + return response()->json(['error' => 'Terjadi kesalahan: ' . $e->getMessage()], 500); + } + } + + public function viewResult($id) + { + // Ambil asesmen berdasarkan ID, pastikan asesmen milik user dan statusnya sudah 'completed' + $assessment = LiteracyAssessment::where('id', $id) + ->where('user_id', Auth::id()) + ->where('status', 'completed') + ->firstOrFail(); + + // Ambil semua pertanyaan, beserta jawaban dan opsi untuk asesmen ini + $questions = LiteracyQuestion::with([ + 'answers' => function ($query) use ($id) { + $query->where('assessment_id', $id); + }, + 'options' + ])->get(); + + return view('literacy.student.assessments.result', compact('assessment', 'questions')); + } + + public function result($id) + { + $assessment = LiteracyAssessment::where('id', $id) + ->where('user_id', Auth::id()) + ->where('status', 'completed') + ->firstOrFail(); + + $questions = LiteracyQuestion::with([ + 'answers' => function ($query) use ($id) { + $query->where('assessment_id', $id); + }, + 'options' + ])->get(); + + return view('literacy.student.assessments.result', compact('assessment', 'questions')); + } } diff --git a/Penilaian Literasi/iClOP-V2/resources/views/literacy/student/assessments/assessment.blade.php b/Penilaian Literasi/iClOP-V2/resources/views/literacy/student/assessments/assessment.blade.php index e0e6a9f..77e8844 100644 --- a/Penilaian Literasi/iClOP-V2/resources/views/literacy/student/assessments/assessment.blade.php +++ b/Penilaian Literasi/iClOP-V2/resources/views/literacy/student/assessments/assessment.blade.php @@ -182,6 +182,7 @@ }; + @@ -231,7 +232,7 @@
-
- + - + - +
@@ -386,20 +449,93 @@ + + + + + diff --git a/Penilaian Literasi/iClOP-V2/resources/views/literacy/student/assessments/index.blade.php b/Penilaian Literasi/iClOP-V2/resources/views/literacy/student/assessments/index.blade.php index e0a637c..2ec610e 100644 --- a/Penilaian Literasi/iClOP-V2/resources/views/literacy/student/assessments/index.blade.php +++ b/Penilaian Literasi/iClOP-V2/resources/views/literacy/student/assessments/index.blade.php @@ -255,7 +255,7 @@ style="margin-top: 12px; margin-left: 15px; color: #676767;">
- Materials
@@ -317,9 +317,15 @@ - {{ ucfirst($assessment->status) }} + @if ($assessment->status == 'completed') + Selesai + @elseif ($assessment->status == 'in_progress') + Dalam Pengerjaan + @else + Belum Dikerjakan + @endif {{ $assessment->score ?? 'Belum Dinilai' }} @@ -327,12 +333,12 @@ @if ($assessment->status == 'pending')
@csrf - +
@elseif ($assessment->status == 'in_progress') - Lanjutkan + Lanjutkan @else - + Lihat Hasil @endif @@ -341,7 +347,7 @@ Belum ada asesmen @endforelse - +