285 lines
10 KiB
PHP
285 lines
10 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\student;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\Enrollment;
|
|
use App\Models\Course;
|
|
use App\Models\Lesson;
|
|
use App\Models\Watch_history;
|
|
use App\Models\Certificate;
|
|
use App\Models\QuizSubmission;
|
|
use App\Models\Question;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Session;
|
|
|
|
class QuizController extends Controller
|
|
{
|
|
public function quiz_submit(Request $request)
|
|
{
|
|
$quiz = Lesson::findOrFail($request->quiz_id);
|
|
|
|
// 1. Cek Retake (Kesempatan mengulang)
|
|
$retake = $quiz->retake;
|
|
$submit_count = QuizSubmission::where('quiz_id', $quiz->id)
|
|
->where('user_id', auth()->user()->id)
|
|
->count();
|
|
|
|
if ($submit_count >= $retake) {
|
|
Session::flash('warning', get_phrase('Attempt has been over.'));
|
|
return redirect()->back();
|
|
}
|
|
|
|
// 2. Rapikan Input Jawaban
|
|
$inputs = $request->except(['_token', 'quiz_id']);
|
|
$submits = [];
|
|
|
|
// Loop input untuk membersihkan format data (terutama jika dari JS frontend)
|
|
foreach ($inputs as $question_id => $answer) {
|
|
if ($answer !== null) {
|
|
// Jika input berupa string JSON (kecuali 'true'/'false'), decode dulu
|
|
if (is_string($answer) && !in_array($answer, ['true', 'false'])) {
|
|
$decoded = json_decode($answer, true);
|
|
if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
|
|
// Ambil value jika strukturnya array of objects
|
|
$submits[$question_id] = array_column($decoded, 'value');
|
|
} else {
|
|
$submits[$question_id] = $answer;
|
|
}
|
|
} else {
|
|
$submits[$question_id] = $answer;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 3. Ambil Soal dari Database
|
|
// Kita ambil soal berdasarkan key dari jawaban yang dikirim
|
|
$question_ids = array_keys($submits);
|
|
$questions = Question::whereIn('id', $question_ids)->get();
|
|
|
|
$right_answers = [];
|
|
$wrong_answers = [];
|
|
|
|
// 4. Proses Koreksi Jawaban
|
|
foreach ($questions as $question) {
|
|
// PENTING: Ambil jawaban user berdasarkan ID Soal, bukan urutan index loop
|
|
if (!isset($submits[$question->id])) {
|
|
continue;
|
|
}
|
|
|
|
$submitted = $submits[$question->id];
|
|
$correct_answer = json_decode($question->answer, true);
|
|
$isCorrect = false;
|
|
|
|
// Logika per tipe soal
|
|
if ($question->type == 'mcq') {
|
|
// Cek array diff (bolak-balik) untuk memastikan isi array sama persis
|
|
$isCorrect = empty(array_diff($correct_answer, $submitted))
|
|
&& empty(array_diff($submitted, $correct_answer));
|
|
|
|
} elseif ($question->type == 'fill_blanks') {
|
|
if (count($correct_answer) === count($submitted)) {
|
|
$isCorrect = true;
|
|
foreach ($correct_answer as $i => $ans) {
|
|
// Trim dan strtolower agar tidak case-sensitive
|
|
if (trim(strtolower($ans)) !== trim(strtolower($submitted[$i]))) {
|
|
$isCorrect = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
} elseif ($question->type == 'true_false') {
|
|
$isCorrect = strtolower(json_encode($correct_answer)) === strtolower($submitted);
|
|
}
|
|
|
|
// Masukkan ke bucket Benar/Salah
|
|
if ($isCorrect) {
|
|
$right_answers[] = $question->id;
|
|
} else {
|
|
$wrong_answers[] = $question->id;
|
|
}
|
|
}
|
|
|
|
// 5. Simpan Hasil Submission
|
|
QuizSubmission::create([
|
|
'quiz_id' => $quiz->id,
|
|
'user_id' => auth()->user()->id,
|
|
'correct_answer' => json_encode($right_answers),
|
|
'wrong_answer' => json_encode($wrong_answers),
|
|
'submits' => json_encode($submits),
|
|
]);
|
|
|
|
// 6. Hitung Nilai
|
|
$total_questions = $questions->count();
|
|
$mark_per_question = $total_questions > 0 ? ($quiz->total_mark / $total_questions) : 0;
|
|
$obtained_mark = count($right_answers) * $mark_per_question;
|
|
|
|
// 7. Cek Kelulusan
|
|
if ($obtained_mark >= $quiz->pass_mark) {
|
|
|
|
// PANGGIL FUNGSI YANG BERADA DI CLASS YANG SAMA
|
|
$this->update_watch_history2(
|
|
$quiz->id,
|
|
$quiz->course_id,
|
|
auth()->user()->id
|
|
);
|
|
|
|
Session::flash('success', get_phrase('Congratulations, you passed the quiz.'));
|
|
} else {
|
|
Session::flash('warning', get_phrase('You did not reach the minimum score.'));
|
|
}
|
|
|
|
return redirect()->back();
|
|
}
|
|
|
|
public function update_watch_history2($lesson_id, $course_id, $student_id)
|
|
{
|
|
// Validasi Course
|
|
$course = Course::where('id', $course_id)->first();
|
|
if (!$course) return false;
|
|
|
|
// Validasi Enrollment
|
|
$enrollment = Enrollment::where('course_id', $course->id)
|
|
->where('user_id', $student_id)
|
|
->exists();
|
|
|
|
// Cek Role
|
|
$currentUserRole = auth()->check() ? auth()->user()->role : 'student';
|
|
if (!$enrollment && ($currentUserRole != 'admin' && !is_course_instructor($course->id))) {
|
|
return false;
|
|
}
|
|
|
|
// Ambil semua lesson ID
|
|
$total_lesson_ids = Lesson::where('course_id', $course_id)
|
|
->orderBy('id', 'asc')
|
|
->pluck('id')
|
|
->toArray();
|
|
|
|
// Ambil data history user
|
|
$watch_history = Watch_history::where('course_id', $course_id)
|
|
->where('student_id', $student_id)
|
|
->first();
|
|
|
|
$completed_lessons = [];
|
|
|
|
// Parse data lama dengan cara yang lebih aman
|
|
if ($watch_history && !empty($watch_history->completed_lesson)) {
|
|
$completed_lesson_data = $watch_history->completed_lesson;
|
|
|
|
// Coba decode JSON
|
|
$decoded = json_decode($completed_lesson_data, true);
|
|
|
|
if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
|
|
$completed_lessons = $decoded;
|
|
} else {
|
|
// Jika bukan JSON valid, coba parsing manual
|
|
$completed_lesson_data = trim($completed_lesson_data, '[]"\' ');
|
|
if (!empty($completed_lesson_data)) {
|
|
$completed_lessons = array_map('intval', explode(',', $completed_lesson_data));
|
|
$completed_lessons = array_unique($completed_lessons); // pastikan unik
|
|
}
|
|
}
|
|
}
|
|
|
|
// HANYA tambahkan lesson saat ini jika belum ada
|
|
$lesson_id_int = (int)$lesson_id;
|
|
if (!in_array($lesson_id_int, $completed_lessons)) {
|
|
$completed_lessons[] = $lesson_id_int;
|
|
}
|
|
|
|
// Sort dan pastikan unique
|
|
sort($completed_lessons);
|
|
$completed_lessons = array_values(array_unique($completed_lessons));
|
|
|
|
// Course selesai jika semua lesson sudah completed
|
|
$all_lessons_completed = true;
|
|
foreach ($total_lesson_ids as $total_lesson_id) {
|
|
if (!in_array($total_lesson_id, $completed_lessons)) {
|
|
$all_lessons_completed = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
$is_completed = $all_lessons_completed;
|
|
|
|
$data = [
|
|
'course_id' => $course_id,
|
|
'student_id' => $student_id,
|
|
'watching_lesson_id' => $lesson_id,
|
|
'completed_lesson' => json_encode($completed_lessons),
|
|
'completed_date' => $is_completed ? now() : null,
|
|
];
|
|
|
|
// Debug final data
|
|
// dd($data);
|
|
|
|
// Simpan ke DB
|
|
if ($watch_history) {
|
|
// Gunakan ini untuk memastikan hanya update yang diperlukan
|
|
$watch_history->update($data);
|
|
} else {
|
|
Watch_history::create($data);
|
|
}
|
|
|
|
// **LOGIKA SERTIFIKAT - dengan progress yang benar**
|
|
$completed_count = count(array_intersect($completed_lessons, $total_lesson_ids));
|
|
$total_count = count($total_lesson_ids);
|
|
|
|
$progress_percentage = 0;
|
|
if ($total_count > 0) {
|
|
$progress_percentage = ($completed_count / $total_count) * 100;
|
|
}
|
|
|
|
if ($progress_percentage >= 100) {
|
|
$certificateExists = Certificate::where('user_id', $student_id)
|
|
->where('course_id', $course_id)
|
|
->exists();
|
|
|
|
if (!$certificateExists) {
|
|
Certificate::create([
|
|
'user_id' => $student_id,
|
|
'course_id' => $course_id,
|
|
'identifier' => $this->generateIdentifier(12),
|
|
]);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private function generateIdentifier($length = 12)
|
|
{
|
|
$characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
$charactersLength = strlen($characters);
|
|
$randomString = '';
|
|
for ($i = 0; $i < $length; $i++) {
|
|
$randomString .= $characters[rand(0, $charactersLength - 1)];
|
|
}
|
|
|
|
return $randomString;
|
|
}
|
|
|
|
public function load_result(Request $request)
|
|
{
|
|
$page_data['quiz'] = Lesson::where('id', $request->quiz_id)->first();
|
|
$page_data['questions'] = Question::where('quiz_id', $request->quiz_id)->get();
|
|
$page_data['result'] = QuizSubmission::where('id', $request->submit_id)
|
|
->where('quiz_id', $request->quiz_id)
|
|
->where('user_id', auth()->user()->id)
|
|
->first();
|
|
return view('course_player.quiz.result', $page_data);
|
|
}
|
|
|
|
public function load_questions(Request $request)
|
|
{
|
|
$page_data['quiz'] = Lesson::where('id', $request->quiz_id)->first();
|
|
$page_data['questions'] = Question::where('quiz_id', $request->quiz_id)->get();
|
|
$page_data['submits'] = QuizSubmission::where('quiz_id', $request->quiz_id)
|
|
->where('user_id', auth()->user()->id)
|
|
->get();
|
|
$page_data['course_details'] = Course::where('id', $page_data['quiz']->course_id)->first();
|
|
return view('course_player.quiz.questions', $page_data);
|
|
}
|
|
}
|