113 lines
3.2 KiB
PHP
113 lines
3.2 KiB
PHP
<?php
|
||
|
||
namespace App\Services\Scheduling\Data;
|
||
|
||
/**
|
||
* Kontainer utama yang menampung semua data untuk satu run GA.
|
||
* Dibuat sekali oleh DatasetLoader di awal, lalu dipass ke GA.
|
||
*/
|
||
class SchedulingDataset
|
||
{
|
||
/**
|
||
* @param array<int, Guru> $guruList Map guru_id → Guru
|
||
* @param array<int, Kelas> $kelasList Map kelas_id → Kelas
|
||
* @param array<int> $ruanganRobotkuIds Daftar id ruangan Robotku
|
||
* (untuk domain pilihan ruang di kelas reguler)
|
||
* @param array<SchedulingSlot> $allSlots Semua slot valid (6 hari × 5 sesi = 30 slot)
|
||
*/
|
||
public function __construct(
|
||
public readonly array $guruList,
|
||
public readonly array $kelasList,
|
||
public readonly array $ruanganRobotkuIds,
|
||
public readonly array $allSlots,
|
||
) {
|
||
}
|
||
|
||
/**
|
||
* Ambil guru berdasarkan ID. Throw exception jika tidak ditemukan.
|
||
*/
|
||
public function getGuru(int $id): Guru
|
||
{
|
||
if (!isset($this->guruList[$id])) {
|
||
throw new \OutOfBoundsException("Guru dengan id={$id} tidak ada di dataset.");
|
||
}
|
||
return $this->guruList[$id];
|
||
}
|
||
|
||
/**
|
||
* Ambil kelas berdasarkan ID.
|
||
*/
|
||
public function getKelas(int $id): Kelas
|
||
{
|
||
if (!isset($this->kelasList[$id])) {
|
||
throw new \OutOfBoundsException("Kelas dengan id={$id} tidak ada di dataset.");
|
||
}
|
||
return $this->kelasList[$id];
|
||
}
|
||
|
||
/**
|
||
* Semua kelas reguler (kandidat untuk dioptimasi penuh oleh GA).
|
||
*
|
||
* @return array<Kelas>
|
||
*/
|
||
public function kelasReguler(): array
|
||
{
|
||
return array_values(array_filter(
|
||
$this->kelasList,
|
||
fn(Kelas $k) => !$k->isEkstrakurikuler
|
||
));
|
||
}
|
||
|
||
/**
|
||
* Semua kelas ekstrakurikuler (jadwal fix, hanya guru yang dioptimasi).
|
||
*
|
||
* @return array<Kelas>
|
||
*/
|
||
public function kelasEkstrakurikuler(): array
|
||
{
|
||
return array_values(array_filter(
|
||
$this->kelasList,
|
||
fn(Kelas $k) => $k->isEkstrakurikuler
|
||
));
|
||
}
|
||
|
||
/**
|
||
* Guru yang mampu mengajar level tertentu (berjenjang).
|
||
*
|
||
* @return array<Guru>
|
||
*/
|
||
public function guruMampuLevel(int $level): array
|
||
{
|
||
return array_values(array_filter(
|
||
$this->guruList,
|
||
fn(Guru $g) => $g->mampuMengajarLevel($level)
|
||
));
|
||
}
|
||
|
||
/**
|
||
* Total pertemuan per minggu yang harus dijadwalkan (= panjang kromosom N).
|
||
*/
|
||
public function totalPertemuan(): int
|
||
{
|
||
return array_sum(array_map(
|
||
fn(Kelas $k) => $k->frekuensiPerMinggu,
|
||
$this->kelasList
|
||
));
|
||
}
|
||
|
||
/**
|
||
* Statistik ringkas untuk keperluan diagnostik & pelaporan.
|
||
*/
|
||
public function summary(): array
|
||
{
|
||
return [
|
||
'total_guru' => count($this->guruList),
|
||
'total_kelas' => count($this->kelasList),
|
||
'kelas_reguler' => count($this->kelasReguler()),
|
||
'kelas_ekstrakurikuler' => count($this->kelasEkstrakurikuler()),
|
||
'total_ruangan_robotku' => count($this->ruanganRobotkuIds),
|
||
'total_slot' => count($this->allSlots),
|
||
'total_pertemuan_per_minggu' => $this->totalPertemuan(),
|
||
];
|
||
}
|
||
} |