update: for view and controller assessment add story text
This commit is contained in:
parent
e613c0da96
commit
687592c644
|
|
@ -88,7 +88,9 @@ public function show($id)
|
||||||
->with([
|
->with([
|
||||||
'answers' => function ($query) use ($id) {
|
'answers' => function ($query) use ($id) {
|
||||||
$query->where('assessment_id', $id);
|
$query->where('assessment_id', $id);
|
||||||
}
|
},
|
||||||
|
'options',
|
||||||
|
'material.storyTexts'
|
||||||
])
|
])
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
|
|
@ -179,101 +181,6 @@ public function storeAnswer(Request $request, $assessmentId): JsonResponse
|
||||||
return response()->json(['success' => true]);
|
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;
|
|
||||||
// $totalWeight = 0;
|
|
||||||
// $essayThreshold = 60;
|
|
||||||
|
|
||||||
// $normalizeText = function ($text) {
|
|
||||||
// $text = strtolower($text);
|
|
||||||
// $text = preg_replace('/[^\p{L}\p{N}\s]/u', '', $text);
|
|
||||||
// $text = preg_replace('/\s+/', ' ', $text);
|
|
||||||
// return trim($text);
|
|
||||||
// };
|
|
||||||
|
|
||||||
// $feedback = [];
|
|
||||||
|
|
||||||
// foreach ($answers as $answer) {
|
|
||||||
// $question = LiteracyQuestion::find($answer->question_id);
|
|
||||||
// if (!$question)
|
|
||||||
// continue;
|
|
||||||
|
|
||||||
// $weight = $question->weight ?? ($question->type === 'essay' ? 5 : 1);
|
|
||||||
// $totalWeight += $weight;
|
|
||||||
|
|
||||||
// if ($question->type === 'multiple_choice') {
|
|
||||||
// if (
|
|
||||||
// $answer->option_id &&
|
|
||||||
// LiteracyOption::where('id', $answer->option_id)
|
|
||||||
// ->where('is_correct', true)
|
|
||||||
// ->exists()
|
|
||||||
// ) {
|
|
||||||
// $correctWeight += $weight;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// } elseif ($question->type === 'essay') {
|
|
||||||
// $userAnswer = $normalizeText($answer->answer_text ?? '');
|
|
||||||
// $correctAnswerRaw = $question->essay_answer ?? '';
|
|
||||||
// $correctAnswers = array_map($normalizeText, preg_split('/\r\n|\r|\n/', $correctAnswerRaw));
|
|
||||||
// $maxMatchPercent = 0;
|
|
||||||
|
|
||||||
// foreach ($correctAnswers as $correctAnswer) {
|
|
||||||
// similar_text($userAnswer, $correctAnswer, $percent);
|
|
||||||
// $maxMatchPercent = max($maxMatchPercent, $percent);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if ($maxMatchPercent >= $essayThreshold) {
|
|
||||||
// $correctWeight += $weight;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Hitung skor akhir berdasarkan bobot
|
|
||||||
// $score = $totalWeight > 0 ? ($correctWeight / $totalWeight) * 100 : 0;
|
|
||||||
|
|
||||||
// // Update asesmen yang sedang berjalan jadi completed
|
|
||||||
// $assessment->update([
|
|
||||||
// 'score' => round($score, 2),
|
|
||||||
// 'status' => 'completed',
|
|
||||||
// 'assessed_at' => now(),
|
|
||||||
// 'feedback' => json_encode($feedback), // Menyimpan feedback ke database
|
|
||||||
// ]);
|
|
||||||
|
|
||||||
// // Buat asesmen baru dengan status 'pending' untuk percakapan 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),
|
|
||||||
// 'feedback' => $feedback, // Mengembalikan feedback dalam respons
|
|
||||||
// ], 200);
|
|
||||||
|
|
||||||
// } catch (\Exception $e) {
|
|
||||||
// return response()->json(['error' => 'Terjadi kesalahan: ' . $e->getMessage()], 500);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
public function submitAssessment($id)
|
public function submitAssessment($id)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
|
@ -338,7 +245,7 @@ public function submitAssessment($id)
|
||||||
$correctWeight += $weight;
|
$correctWeight += $weight;
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
$apiResponse = Http::timeout(10)->post('http://127.0.0.1:8001/generate-feedback/', [
|
$apiResponse = Http::timeout(10)->post('http://127.0.0.1:8010/generate-feedback/', [
|
||||||
'user_answer' => $answer->answer_text,
|
'user_answer' => $answer->answer_text,
|
||||||
'expected_answer' => $bestMatch,
|
'expected_answer' => $bestMatch,
|
||||||
]);
|
]);
|
||||||
|
|
|
||||||
|
|
@ -362,35 +362,40 @@
|
||||||
<!-- CONTENT DAN NAVIGASI SOAL -->
|
<!-- CONTENT DAN NAVIGASI SOAL -->
|
||||||
@php
|
@php
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
$multipleChoiceQuestions = $questions->filter(fn($q) => $q->options->isNotEmpty());
|
$questionsByMaterial = $questions->groupBy('material_id');
|
||||||
$essayQuestions = $questions->filter(fn($q) => $q->options->isEmpty());
|
|
||||||
$multipleChoiceNumber = 0;
|
|
||||||
$essayNumber = 0;
|
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
<main class="col-md-8">
|
<main class="col-md-8">
|
||||||
<div class="grid grid-cols-12 gap-6 p-6">
|
<div class="grid grid-cols-12 gap-6 p-6">
|
||||||
<div class="col-span-12 lg:col-span-9 space-y-4">
|
<div class="col-span-12 lg:col-span-9 space-y-4">
|
||||||
<!-- Bagian Pilihan Ganda -->
|
|
||||||
@if ($multipleChoiceQuestions->isNotEmpty())
|
|
||||||
<div class="row mt-4">
|
|
||||||
<div class="col-12 d-flex justify-content-between align-items-center">
|
|
||||||
<h4 class="text-base font-semibold mb-2">Bagian 1: Pilihan Ganda</h4>
|
|
||||||
<button onclick="window.close()" class="btn btn-outline-secondary btn-sm">Kembali</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p class="text-gray-500 text-sm mb-3">Pilih salah satu jawaban yang paling tepat.</p>
|
|
||||||
|
|
||||||
@foreach ($multipleChoiceQuestions as $question)
|
{{-- ===================== PILIHAN GANDA ===================== --}}
|
||||||
|
<h4 class="text-lg font-semibold mb-2">Soal Pilihan Ganda</h4>
|
||||||
|
@php $mcGlobalNumber = 0; @endphp
|
||||||
|
@foreach ($questionsByMaterial as $materialId => $materialQuestions)
|
||||||
@php
|
@php
|
||||||
$multipleChoiceNumber++;
|
$material = $materialQuestions->first()->material;
|
||||||
|
$storyTexts = $material->storyTexts ?? collect();
|
||||||
|
$multipleChoiceQuestions = $materialQuestions->where('type', 'multiple_choice');
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
@if ($multipleChoiceQuestions->isNotEmpty())
|
||||||
|
<div class="mb-4">
|
||||||
|
<h5 class="font-semibold">Teks Bacaan: {{ $material->title }}</h5>
|
||||||
|
@foreach ($storyTexts as $text)
|
||||||
|
<div class="bg-gray-100 p-3 rounded mb-2">{{ $text->story_text }}</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@foreach ($multipleChoiceQuestions as $index => $question)
|
||||||
|
@php
|
||||||
|
$mcGlobalNumber++;
|
||||||
$savedAnswer = optional($question->answers->where('assessment_id', $assessment->id)->first());
|
$savedAnswer = optional($question->answers->where('assessment_id', $assessment->id)->first());
|
||||||
$kutipan = null;
|
$kutipan = null;
|
||||||
$pertanyaanBersih = $question->question_text;
|
$pertanyaanBersih = $question->question_text;
|
||||||
|
|
||||||
// Deteksi apakah soal memuat kutipan atau paragraf
|
|
||||||
if (Str::contains($question->question_text, 'Bacalah')) {
|
if (Str::contains($question->question_text, 'Bacalah')) {
|
||||||
preg_match('/Bacalah (kutipan|paragraf) berikut:\s*"(.*?)"\s*(.*)/s', $question->question_text, $matches);
|
preg_match('/Bacalah (kutipan|paragraf) berikut:\s*\"(.*?)\"\s*(.*)/s', $question->question_text, $matches);
|
||||||
if (count($matches) >= 4) {
|
if (count($matches) >= 4) {
|
||||||
$kutipan = trim($matches[2]);
|
$kutipan = trim($matches[2]);
|
||||||
$pertanyaanBersih = trim($matches[3]);
|
$pertanyaanBersih = trim($matches[3]);
|
||||||
|
|
@ -398,13 +403,11 @@
|
||||||
}
|
}
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
<div class="bg-white shadow-md rounded-lg p-4 border mb-4" id="question-mc-{{ $multipleChoiceNumber }}">
|
<div id="question-mc-{{ $mcGlobalNumber }}" class="bg-white shadow-md rounded-lg p-4 border mb-4">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<!-- Kolom Nomor Soal -->
|
|
||||||
<div class="col-auto d-flex justify-content-start align-items-start pt-2">
|
<div class="col-auto d-flex justify-content-start align-items-start pt-2">
|
||||||
<strong>{{ $multipleChoiceNumber }}.</strong>
|
<strong>{{ $mcGlobalNumber }}.</strong>
|
||||||
</div>
|
</div>
|
||||||
<!-- Kolom Isi Soal -->
|
|
||||||
<div class="col">
|
<div class="col">
|
||||||
@if ($kutipan)
|
@if ($kutipan)
|
||||||
<p class="mb-0 mt-2"><strong>Bacalah kutipan berikut:</strong></p>
|
<p class="mb-0 mt-2"><strong>Bacalah kutipan berikut:</strong></p>
|
||||||
|
|
@ -432,45 +435,42 @@
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
@endforeach
|
||||||
@endif
|
@endif
|
||||||
|
@endforeach
|
||||||
|
|
||||||
<!-- Bagian Isian / Essay -->
|
{{-- ===================== ISIAN / ESSAY ===================== --}}
|
||||||
@if ($essayQuestions->isNotEmpty())
|
<h4 class="text-lg font-semibold mt-6 mb-2">Soal Isian</h4>
|
||||||
<h4 class="text-base font-semibold mt-4">Bagian 2: Isian</h4>
|
@php $essayGlobalNumber = 0; @endphp
|
||||||
<p class="text-gray-500 text-sm mb-3">Jawablah pertanyaan berikut dengan jawaban yang sesuai.</p>
|
@foreach ($questionsByMaterial as $materialId => $materialQuestions)
|
||||||
|
|
||||||
@foreach ($essayQuestions as $question)
|
|
||||||
@php
|
@php
|
||||||
$essayNumber++;
|
$material = $materialQuestions->first()->material;
|
||||||
$savedAnswer = optional($question->answers->where('assessment_id', $assessment->id)->first());
|
$storyTexts = $material->storyTexts ?? collect();
|
||||||
$kutipan = null;
|
$essayQuestions = $materialQuestions->where('type', 'essay');
|
||||||
$pertanyaanBersih = $question->question_text;
|
|
||||||
|
|
||||||
if (Str::contains($question->question_text, 'Bacalah')) {
|
|
||||||
preg_match('/Bacalah (kutipan|paragraf) berikut:\s*"(.*?)"\s*(.*)/s', $question->question_text, $matches);
|
|
||||||
if (count($matches) >= 4) {
|
|
||||||
$kutipan = trim($matches[2]);
|
|
||||||
$pertanyaanBersih = trim($matches[3]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
<div class="bg-white shadow-md rounded-lg p-4 border mb-4" id="question-essay-{{ $essayNumber }}">
|
@if ($essayQuestions->isNotEmpty())
|
||||||
|
<div class="mb-4">
|
||||||
|
<h5 class="font-semibold">Teks Bacaan: {{ $material->title }}</h5>
|
||||||
|
@foreach ($storyTexts as $text)
|
||||||
|
<div class="bg-gray-100 p-3 rounded mb-2">{{ $text->story_text }}</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@foreach ($essayQuestions as $index => $question)
|
||||||
|
@php
|
||||||
|
$essayGlobalNumber++;
|
||||||
|
$savedAnswer = optional($question->answers->where('assessment_id', $assessment->id)->first());
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
<div id="question-essay-{{ $essayGlobalNumber }}" class="bg-white shadow-md rounded-lg p-4 border mb-4">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<!-- Kolom Nomor Soal -->
|
|
||||||
<div class="col-auto d-flex justify-content-start align-items-start pt-2">
|
<div class="col-auto d-flex justify-content-start align-items-start pt-2">
|
||||||
<strong>{{ $essayNumber }}.</strong>
|
<strong>{{ $essayGlobalNumber }}.</strong>
|
||||||
</div>
|
</div>
|
||||||
<!-- Kolom Isi Soal -->
|
|
||||||
<div class="col">
|
<div class="col">
|
||||||
@if ($kutipan)
|
<p class="mt-2 mb-0">{{ $question->question_text }}</p>
|
||||||
<p class="mb-0 mt-2"><strong>Bacalah kutipan berikut:</strong></p>
|
|
||||||
<div class="ps-3 pe-3">
|
|
||||||
<em>"{{ $kutipan }}"</em>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
<p class="mt-2 mb-0">{{ $pertanyaanBersih }}</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-3">
|
<div class="mt-3">
|
||||||
<textarea name="question_{{ $question->id }}"
|
<textarea name="question_{{ $question->id }}"
|
||||||
class="w-100 h-24 p-3 border rounded-lg focus:ring focus:ring-blue-200"
|
class="w-100 h-24 p-3 border rounded-lg focus:ring focus:ring-blue-200"
|
||||||
|
|
@ -480,6 +480,8 @@ class="w-100 h-24 p-3 border rounded-lg focus:ring focus:ring-blue-200"
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
@endforeach
|
||||||
@endif
|
@endif
|
||||||
|
@endforeach
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
@ -654,27 +656,25 @@ class="btn {{ $btnClass }} d-flex justify-content-center align-items-center"
|
||||||
function checkUnansweredQuestions() {
|
function checkUnansweredQuestions() {
|
||||||
let unansweredCount = 0;
|
let unansweredCount = 0;
|
||||||
|
|
||||||
// Cek soal pilihan ganda (radio button)
|
@foreach ($questions as $question)
|
||||||
@foreach ($multipleChoiceQuestions as $question)
|
@if ($question->type === 'multiple_choice')
|
||||||
if (!$("input[name='question_{{ $question->id }}']:checked").val()) {
|
if (!$("input[name='question_{{ $question->id }}']:checked").val()) {
|
||||||
unansweredCount++;
|
unansweredCount++;
|
||||||
}
|
}
|
||||||
@endforeach
|
@elseif ($question->type === 'essay')
|
||||||
|
|
||||||
// Cek soal isian (textarea)
|
|
||||||
@foreach ($essayQuestions as $question)
|
|
||||||
if (!$("textarea[name='question_{{ $question->id }}']").val().trim()) {
|
if (!$("textarea[name='question_{{ $question->id }}']").val().trim()) {
|
||||||
unansweredCount++;
|
unansweredCount++;
|
||||||
}
|
}
|
||||||
|
@endif
|
||||||
@endforeach
|
@endforeach
|
||||||
|
|
||||||
console.log("Soal yang belum dijawab:", unansweredCount); // Debugging
|
console.log("Soal yang belum dijawab:", unansweredCount);
|
||||||
|
|
||||||
if (unansweredCount > 0) {
|
if (unansweredCount > 0) {
|
||||||
$("#unansweredCount").text(unansweredCount);
|
$("#unansweredCount").text(unansweredCount);
|
||||||
$("#unansweredWarningModal").modal("show"); // Tampilkan modal peringatan
|
$("#unansweredWarningModal").modal("show");
|
||||||
} else {
|
} else {
|
||||||
$("#confirmSubmitModal").modal("show"); // Tampilkan modal konfirmasi
|
$("#confirmSubmitModal").modal("show");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -705,15 +705,6 @@ function checkUnansweredQuestions() {
|
||||||
console.error("Gagal menyimpan jawaban:", error);
|
console.error("Gagal menyimpan jawaban:", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// function updateNavigationButton(questionId) {
|
|
||||||
// const navButton = document.querySelector(`button[data-question-id='${questionId}']`);
|
|
||||||
|
|
||||||
// if (navButton) {
|
|
||||||
// navButton.classList.remove("btn-outline-secondary");
|
|
||||||
// navButton.classList.add("btn-primary", "border-white");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user