198 lines
7.5 KiB
PHP
198 lines
7.5 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Admin;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\Siswa;
|
|
use App\Models\PaketMapel;
|
|
use App\Models\AngketSiswa;
|
|
use App\Models\NilaiTotalMapel;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
class HasilAngketController extends Controller
|
|
{
|
|
public function index()
|
|
{
|
|
$siswas = Siswa::with([
|
|
'kelas',
|
|
'angket.paketPertama',
|
|
'angket.paketKedua',
|
|
'angket.paketKetiga',
|
|
'angket.paketFinal'
|
|
])->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.');
|
|
}
|
|
}
|