id)->first(); $kurikulums = Kurikulum::all(); // Ambil kriterias untuk kurikulum pertama secara default // Ini akan diganti saat user memilih kurikulum $kriterias = Kriteria::with('subkriterias.opsisubkriterias') ->where('kurikulum_id', $kurikulums->first()->id ?? null) ->get(); // Ambil riwayat perhitungan user $sesikuisquery = SesiKuis::with(['kurikulum', 'hasilsaw.alternatif']) ->where('user_id', $user->id) ->orderBy('created_at', 'desc'); $hasilitems = HasilSaw::with(['alternatif.mapels', 'alternatif.kurikulum']) ->where('sesi_kuis_id', $request->sesi_id) ->orderBy('peringkat') ->get(); // Filter riwayat jika ada if ($request->filled('kurikulum_id')) { $sesikuisquery->where('kurikulum_id', $request->kurikulum_id); } if ($request->filled('tanggal')) { $sesikuisquery->whereDate('created_at', $request->tanggal); } $sesikuis = $sesikuisquery->get(); // Cek apakah user pernah melakukan perhitungan sebelumnya $showHistory = $sesikuis->isNotEmpty(); // Default: tidak ada hasil yang ditampilkan $hasilsaw = null; $hasilitems = collect(); // Jika ada parameter sesi_id, tampilkan hasil perhitungan spesifik if ($request->has('sesi_id')) { $hasilsaw = SesiKuis::with('kurikulum')->findOrFail($request->sesi_id); $hasilitems = HasilSaw::with('alternatif') ->where('sesi_kuis_id', $request->sesi_id) ->orderBy('peringkat') ->get(); } // Cek apakah perhitungan dibuka oleh admin $quizAccessStatus = SystemSetting::isPerhitunganOpen(); return view('dashboard', compact( 'siswa', 'kurikulums', 'kriterias', 'sesikuis', 'hasilsaw', 'hasilitems', 'showHistory', 'quizAccessStatus' )); } /** * Mendapatkan kriteria berdasarkan kurikulum */ public function getKriteriaByKurikulum(Request $request) { $kriterias = Kriteria::with('subkriterias.opsisubkriterias') ->where('kurikulum_id', $request->kurikulum_id) ->get(); return response()->json($kriterias); } /** * Menampilkan hasil spesifik */ public function lihatHasil($sesiId) { // Validasi kepemilikan data $user = Auth::user(); $sesikuis = SesiKuis::where('id', $sesiId) ->where('user_id', $user->id) ->firstOrFail(); // Redirect ke dashboard dengan parameter sesi_id return redirect()->route('dashboard', ['sesi_id' => $sesiId]); } /** * Menghapus riwayat perhitungan */ public function hapusRiwayat($sesiId) { // Validasi kepemilikan data $user = Auth::user(); $sesikuis = SesiKuis::where('id', $sesiId) ->where('user_id', $user->id) ->firstOrFail(); // Hapus data terkait DB::beginTransaction(); try { // Hapus hasil SAW HasilSaw::where('sesi_kuis_id', $sesiId)->delete(); // Hapus jawaban JawabanKuis::where('sesi_kuis_id', $sesiId)->delete(); // Hapus sesi kuis $sesikuis->delete(); DB::commit(); return redirect()->route('dashboard', ['#riwayat'])->with('success', 'Riwayat berhasil dihapus!'); } catch (\Exception $e) { DB::rollBack(); return redirect()->back()->with('error', 'Gagal menghapus data: ' . $e->getMessage()); } } public function submitpenilaian(Request $request) { // 1. Validasi input $request->validate([ 'kurikulum_id' => 'required|exists:kurikulums,id', 'nama' => 'required|string|max:255', 'sekolah' => 'required|string|max:255', 'kelas' => 'required|string|max:50', 'jawaban' => 'required|array' ]); $user = Auth::user(); // 2. Buat sesi kuis baru $sesikuis = SesiKuis::create([ 'user_id' => $user->id, 'kurikulum_id' => $request->kurikulum_id, 'nama' => $request->nama, 'sekolah' => $request->sekolah, 'kelas' => $request->kelas, ]); // 3. Simpan semua jawaban pengguna foreach ($request->jawaban as $subkriteria_id => $opsi_dipilih) { JawabanKuis::create([ 'sesi_kuis_id' => $sesikuis->id, 'subkriteria_id' => $subkriteria_id, 'opsi_dipilih' => $opsi_dipilih ]); } // 4. HITUNG SAW - Bagian ini yang melakukan perhitungan $this->hitungSAW($sesikuis); // 5. Mark session as completed $sesikuis->selesai_pada = now(); $sesikuis->save(); // Cek jika request adalah AJAX if ($request->ajax() || $request->wantsJson()) { // Load relasi yang diperlukan untuk response JSON $sesikuis->load([ 'kurikulum', 'hasilsaw.alternatif', 'hasilsaw' => function($query) { $query->orderBy('peringkat'); } ]); return response()->json([ 'success' => true, 'hasil' => [ 'nama' => $sesikuis->nama, 'sekolah' => $sesikuis->sekolah, 'kelas' => $sesikuis->kelas, 'kurikulum_nama' => $sesikuis->kurikulum->nama, 'tanggal' => $sesikuis->created_at->format('d F Y, H:i'), 'top3' => $sesikuis->hasilsaw->take(3)->map(function($item) { return [ 'peringkat' => $item->peringkat, 'nama' => $item->alternatif->nama, 'skor' => $item->skor_normalisasi, 'deskripsi' => $item->alternatif->deskripsi ?? 'Tidak ada deskripsi', 'total_skor' => $item->total_skor ]; }), 'all' => $sesikuis->hasilsaw->map(function($item) { return [ 'peringkat' => $item->peringkat, 'nama' => $item->alternatif->nama, 'total_skor' => $item->total_skor, 'skor' => $item->skor_normalisasi ]; }) ] ]); } return redirect()->route('dashboard') ->with('success', 'Penilaian berhasil diselesaikan!') ->with('hasil_id', $sesikuis->id); } public function hitungSAW(SesiKuis $sesikuis) { // Ambil data yang diperlukan $alternatifs = Alternatif::where('kurikulum_id', $sesikuis->kurikulum_id)->get(); $jawabankuis = $sesikuis->jawabankuis->keyBy('subkriteria_id'); // Array untuk menyimpan nilai awal dan nilai max/min $nilaiAwal = []; $maxNilaiKriteria = []; $minNilaiKriteria = []; // LANGKAH 1: Hitung nilai rata-rata per kriteria untuk setiap alternatif foreach ($alternatifs as $alternatif) { $nilaiAwal[$alternatif->id] = []; foreach ($sesikuis->kurikulum->kriterias as $kriteria) { $total_nilai_subkriteria = 0; $jumlah_subkriteria_dijawab = 0; // Hitung nilai untuk setiap subkriteria (soal) dalam kriteria ini foreach ($kriteria->subkriterias as $subkriteria) { if (isset($jawabankuis[$subkriteria->id])) { $opsi_dipilih = $jawabankuis[$subkriteria->id]->opsi_dipilih; $opsisubkriteria = OpsiSubkriteria::where('subkriteria_id', $subkriteria->id) ->where('alternatif_id', $alternatif->id) ->where('opsi', $opsi_dipilih) ->with('crips') ->first(); if ($opsisubkriteria && $opsisubkriteria->crips) { $nilai_subkriteria = $opsisubkriteria->crips->nilai; $total_nilai_subkriteria += $nilai_subkriteria; $jumlah_subkriteria_dijawab++; } } } // Hitung rata-rata per kriteria $nilai_kriteria = ($jumlah_subkriteria_dijawab > 0) ? ($total_nilai_subkriteria / $jumlah_subkriteria_dijawab) : 0; // Simpan nilai kriteria untuk alternatif ini $nilaiAwal[$alternatif->id][$kriteria->id] = $nilai_kriteria; // Update nilai max dan min untuk kriteria ini if (!isset($maxNilaiKriteria[$kriteria->id]) || $nilai_kriteria > $maxNilaiKriteria[$kriteria->id]) { $maxNilaiKriteria[$kriteria->id] = $nilai_kriteria; } if (!isset($minNilaiKriteria[$kriteria->id]) || $nilai_kriteria < $minNilaiKriteria[$kriteria->id]) { $minNilaiKriteria[$kriteria->id] = $nilai_kriteria; } } } // LANGKAH 2: Normalisasi dan hitung skor total $skorAlternatif = []; foreach ($alternatifs as $alternatif) { $skorAlternatif[$alternatif->id] = [ 'total_skor' => 0, 'kriteria_normalisasi' => [], 'kriteria_skor' => [] ]; foreach ($sesikuis->kurikulum->kriterias as $kriteria) { $nilai = $nilaiAwal[$alternatif->id][$kriteria->id]; $max = $maxNilaiKriteria[$kriteria->id]; $min = $minNilaiKriteria[$kriteria->id]; // Normalisasi berdasarkan tipe kriteria $jenis_kriteria = strtolower($kriteria->tipe ?? 'benefit'); if ($max == $min) { // Jika semua nilai sama, berikan nilai normalisasi 1.0 $nilai_normalisasi = 1.0; } else { if ($jenis_kriteria === 'benefit') { // Untuk kriteria benefit: Rij = Xij / Max{Xij} $nilai_normalisasi = ($max > 0) ? ($nilai / $max) : 0; } else { // Untuk kriteria cost: Rij = Min{Xij} / Xij $nilai_normalisasi = ($nilai > 0) ? ($min / $nilai) : 0; } } // Kalikan dengan bobot kriteria $bobot = floatval($kriteria->bobot); $skor_dengan_bobot = $nilai_normalisasi * $bobot; // Simpan nilai normalisasi dan skor mentah $skorAlternatif[$alternatif->id]['kriteria_normalisasi'][$kriteria->id] = $nilai_normalisasi; $skorAlternatif[$alternatif->id]['kriteria_skor'][$kriteria->id] = $nilai; // Tambahkan ke skor total $skorAlternatif[$alternatif->id]['total_skor'] += $skor_dengan_bobot; } // Round total skor di akhir $skorAlternatif[$alternatif->id]['total_skor'] = round($skorAlternatif[$alternatif->id]['total_skor'], 6); } // LANGKAH 3: Urutkan berdasarkan skor (ranking) uasort($skorAlternatif, function($a, $b) { return $b['total_skor'] <=> $a['total_skor']; }); // LANGKAH 4: Simpan hasil ke database $ranking = 1; foreach ($skorAlternatif as $alternatif_id => $skorData) { $hasilsaw = HasilSaw::create([ 'sesi_kuis_id' => $sesikuis->id, 'alternatif_id' => $alternatif_id, 'total_skor' => $skorData['total_skor'], 'skor_normalisasi' => $skorData['total_skor'], 'peringkat' => $ranking++ ]); // Simpan detail SAW $this->simpanDetailSAW($hasilsaw, $sesikuis, $skorData['kriteria_skor'], $skorData['kriteria_normalisasi']); } } public function simpanDetailSAW(HasilSaw $hasilsaw, SesiKuis $sesikuis, array $kriteria_skor, array $kriteria_normalisasi) { $jawabankuis = $sesikuis->jawabankuis->keyBy('subkriteria_id'); foreach ($kriteria_skor as $kriteria_id => $skor_rata_rata) { $kriteria = Kriteria::find($kriteria_id); $nilai_normalisasi_kriteria = $kriteria_normalisasi[$kriteria_id]; $skor_akhir_kriteria = $nilai_normalisasi_kriteria * $kriteria->bobot; // Cari subkriteria pertama yang dijawab sebagai representasi $subkriteria_representatif = null; $opsi_subkriteria_representatif = null; foreach ($kriteria->subkriterias as $subkriteria) { if (isset($jawabankuis[$subkriteria->id])) { $opsi_dipilih = $jawabankuis[$subkriteria->id]->opsi_dipilih; $opsisubkriteria = OpsiSubkriteria::where('subkriteria_id', $subkriteria->id) ->where('alternatif_id', $hasilsaw->alternatif_id) ->where('opsi', $opsi_dipilih) ->with('crips') ->first(); if ($opsisubkriteria && $opsisubkriteria->crips) { $subkriteria_representatif = $subkriteria->id; $opsi_subkriteria_representatif = $opsisubkriteria->id; break; } } } // Simpan jika ada subkriteria representatif if ($subkriteria_representatif) { DetailSaw::create([ 'hasil_saw_id' => $hasilsaw->id, 'kriteria_id' => $kriteria_id, 'subkriteria_id' => $subkriteria_representatif, 'opsi_subkriteria_id' => $opsi_subkriteria_representatif, 'nilai_normalisasi' => $nilai_normalisasi_kriteria, 'nilai_bobot' => $kriteria->bobot, 'skor_akhir' => round($skor_akhir_kriteria, 6) ]); } } } }