paginate(10); return view('admin.angket.hasil.index', compact('siswas'))->with('info', 'Berikut daftar hasil angket siswa.'); } public function edit(Siswa $siswa) { $paketMapels = PaketMapel::all(); $siswa->load('angket'); if (!$siswa->angket) { $siswa->angket = new AngketSiswa([ 'siswa_id' => $siswa->id, 'nama' => $siswa->nama, 'jenis_kelamin' => $siswa->jenis_kelamin, 'kelas_id' => $siswa->kelas_id ]); } return view('admin.angket.hasil.edit', compact('siswa', 'paketMapels'))->with('info', 'Silakan edit hasil pilihan siswa.'); } public function update(Request $request, Siswa $siswa) { $request->validate([ 'paket_pertama_id' => 'required|exists:paket_mapel,id', 'paket_kedua_id' => 'nullable|exists:paket_mapel,id', 'paket_ketiga_id' => 'nullable|exists:paket_mapel,id', 'cita_cita' => 'nullable|string|max:255', 'rencana_setelah_lulus' => 'nullable|string|max:255', 'paket_final_id' => 'nullable|exists:paket_mapel,id', ]); try { DB::beginTransaction(); $angket = AngketSiswa::updateOrCreate( ['siswa_id' => $siswa->id], [ 'nama' => $siswa->nama, 'jenis_kelamin' => $siswa->jenis_kelamin, 'kelas_id' => $siswa->kelas_id, 'paket_pertama_id' => $request->paket_pertama_id, 'paket_kedua_id' => $request->paket_kedua_id, 'paket_ketiga_id' => $request->paket_ketiga_id, 'cita_cita' => $request->cita_cita ?? '-', 'rencana_setelah_lulus' => $request->rencana_setelah_lulus ?? '-', 'paket_final_id' => $request->has('paket_final_id') ? $request->paket_final_id : $siswa->angket->paket_final_id ?? null, ] ); DB::commit(); Log::info('Berhasil memperbarui AngketSiswa:', $angket->toArray()); return redirect()->route('admin.hasil.index')->with('success', 'Hasil pemilihan berhasil diperbarui.'); } catch (\Exception $e) { DB::rollBack(); Log::error('Gagal memperbarui AngketSiswa: ' . $e->getMessage(), [ 'siswa_id' => $siswa->id, 'request_data' => $request->all() ]); return redirect()->back()->withInput()->withErrors('Gagal memperbarui hasil pemilihan: ' . $e->getMessage()); } } public function destroy(Siswa $siswa) { try { AngketSiswa::where('siswa_id', $siswa->id)->delete(); return redirect()->route('admin.hasil.index')->with('success', 'Hasil pemilihan berhasil dihapus.'); } catch (\Exception $e) { Log::error('Gagal menghapus AngketSiswa: ' . $e->getMessage(), ['siswa_id' => $siswa->id]); return redirect()->back()->withErrors('Gagal menghapus hasil pemilihan: ' . $e->getMessage()); } } public function hitung(Request $request) { $paketMapels = PaketMapel::all(); $paketKuota = $paketMapels->pluck('kuota', 'id')->toArray(); $paketIsi = array_fill_keys(array_keys($paketKuota), []); $ranking = NilaiTotalMapel::select('siswa_id', DB::raw('SUM(nilai_total) as total_nilai')) ->groupBy('siswa_id') ->orderByDesc('total_nilai') ->pluck('total_nilai', 'siswa_id') ->toArray(); $angketList = AngketSiswa::with('siswa') ->get() ->sortByDesc(fn($a) => $ranking[$a->siswa_id] ?? 0); $hasilPilihanSiswa = []; $siswaTanpaPaket = []; foreach ($angketList as $angket) { $siswaId = $angket->siswa_id; $rankingSiswa = $ranking[$siswaId] ?? 0; $pilihans = [ $angket->paket_pertama_id, $angket->paket_kedua_id, $angket->paket_ketiga_id, ]; $assigned = false; foreach ($pilihans as $paketId) { if (!$paketId || !array_key_exists($paketId, $paketKuota)) continue; $isiSaatIni = $paketIsi[$paketId]; if (count($isiSaatIni) < $paketKuota[$paketId]) { $paketIsi[$paketId][$siswaId] = $rankingSiswa; $hasilPilihanSiswa[$siswaId] = $paketId; $assigned = true; break; } else { $lowest = collect($isiSaatIni)->sort()->keys()->first(); if ($rankingSiswa > $isiSaatIni[$lowest]) { unset($paketIsi[$paketId][$lowest]); $paketIsi[$paketId][$siswaId] = $rankingSiswa; $hasilPilihanSiswa[$siswaId] = $paketId; $assigned = true; break; } } } if (!$assigned) { $siswaTanpaPaket[] = $siswaId; } } DB::beginTransaction(); try { foreach ($angketList as $angket) { $finalPaketId = $hasilPilihanSiswa[$angket->siswa_id] ?? null; AngketSiswa::where('siswa_id', $angket->siswa_id)->update([ 'paket_final_id' => $finalPaketId, ]); } DB::commit(); Log::info('Pembaruan alokasi paket final ke database berhasil.'); } catch (\Exception $e) { DB::rollBack(); Log::error('Gagal memperbarui alokasi paket final: ' . $e->getMessage()); return redirect()->back()->withErrors('Gagal menyimpan hasil perhitungan: ' . $e->getMessage()); } $finalAssignments = []; foreach ($paketIsi as $paketId => $assigned) { $finalAssignments[$paketId] = [ 'paket' => $paketMapels->firstWhere('id', $paketId), 'siswas' => collect($assigned)->keys()->map(function ($siswaId) use ($angketList, $ranking) { $angket = $angketList->firstWhere('siswa_id', $siswaId); return [ 'siswa' => $angket->siswa, 'ranking' => $ranking[$siswaId] ?? 0, 'cita_cita' => $angket->cita_cita, 'rencana_setelah_lulus' => $angket->rencana_setelah_lulus, ]; })->sortByDesc('ranking')->values()->all() ]; } $unassignedStudents = Siswa::whereIn('id', $siswaTanpaPaket) ->with(['kelas', 'angket.paketPertama', 'angket.paketKedua', 'angket.paketKetiga']) ->get() ->sortByDesc(fn($siswa) => $ranking[$siswa->id] ?? 0); return view('admin.angket.hasil.hitung', compact('finalAssignments', 'unassignedStudents', 'paketMapels')) ->with('success', 'Perhitungan alokasi paket mata pelajaran telah selesai.'); } }