MIF_E31221105/app/Http/Controllers/ProsesKmeansController.php

201 lines
7.6 KiB
PHP

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use App\Models\DataAlumni;
use App\Models\Jabatan;
use App\Models\TahunAngkatan;
class ProsesKmeansController extends Controller
{
public function index()
{
$angkatan = TahunAngkatan::all();
$jabatanMap = Jabatan::pluck('Kategori_bidang_kerja', 'id_kategori')->toArray();
return view('proses_klasifikasi', compact('angkatan', 'jabatanMap'));
}
public function proses(Request $request)
{
$request->validate([
'id_angkatan' => 'required',
]);
$id_angkatan = $request->id_angkatan;
// Ambil list angkatan untuk dropdown di view
$angkatan = TahunAngkatan::all();
// Ambil data alumni sesuai angkatan
$data = DataAlumni::with(['jabatan', 'kualifikasiBidang', 'tahunAngkatan'])
->where('angkatan', $id_angkatan)
->get();
if ($data->isEmpty()) {
return redirect()->back()->with('error', 'Data alumni untuk angkatan tersebut tidak ditemukan.');
}
// Siapkan dataset numerik untuk K-Means
$dataset = $data->map(function ($item) {
return [
'id' => $item->id_alumni,
'nama' => $item->nama,
'nim' => $item->nim,
'angkatan' => optional($item->tahunAngkatan)->tahun,
'pekerjaan' => $item->pekerjaan,
// 'jabatan' => optional($item->jabatan)->nilai ?? 0,
'jabatan' => is_object($item->jabatan) ? $item->jabatan->nilai : (isset($item->jabatan) ? $item->jabatan : 0),
'kualifikasi' => optional($item->kualifikasiBidang)->nilai ?? 0,
];
})->toArray();
// Inisialisasi centroid awal (manual)
$centroids = [
['jabatan' => 1, 'kualifikasi' => 0], //C0
['jabatan' => 3, 'kualifikasi' => 3], //C1
['jabatan' => 6, 'kualifikasi' => 6], //C2
];
$centroid_awal = json_encode($centroids);
// Define cluster labels
$clusterLabels = [
0 => 'TIDAK SESUAI',
1 => 'KURANG SESUAI',
2 => 'SESUAI'
];
$maxIterasi = 10;
$hasil_iterasi = [];
// Proses iterasi
for ($iterasi = 1; $iterasi <= $maxIterasi; $iterasi++) {
$clusters = [];
// Assign ke cluster terdekat
foreach ($dataset as $item) {
$jarak = array_map(function ($cent) use ($item) {
return sqrt(
pow($item['jabatan'] - $cent['jabatan'], 2) +
pow($item['kualifikasi'] - $cent['kualifikasi'], 2)
);
}, $centroids);
$cluster_id = array_search(min($jarak), $jarak);
$clusters[$cluster_id][] = $item;
}
// Hitung centroid baru
$newCentroids = [];
foreach (range(0, count($centroids) - 1) as $ci) {
if (!empty($clusters[$ci])) {
$avgJabatan = collect($clusters[$ci])->avg('jabatan');
$avgKualifikasi = collect($clusters[$ci])->avg('kualifikasi');
$newCentroids[] = [
'jabatan' => round($avgJabatan, 4),
'kualifikasi' => round($avgKualifikasi, 4),
];
} else {
// Pertahankan centroid lama jika kosong
$newCentroids[] = $centroids[$ci];
}
}
// Kumpulkan data untuk tampilan iterasi ini
$iterData = [];
$timestamp = Carbon::now()->format('d-m-Y H:i');
foreach ($dataset as $item) {
$jarak = array_map(function ($cent) use ($item) {
return sqrt(
pow($item['jabatan'] - $cent['jabatan'], 2) +
pow($item['kualifikasi'] - $cent['kualifikasi'], 2)
);
}, $centroids);
$cluster_id = array_search(min($jarak), $jarak);
$iterData[] = [
'id' => $item['id'],
'nama' => $item['nama'],
'nim' => $item['nim'],
'angkatan' => $item['angkatan'],
'pekerjaan' => $item['pekerjaan'],
'jabatan' => $item['jabatan'],
'kualifikasi' => $item['kualifikasi'],
'cluster' => $cluster_id,
// 'klasifikasi' => 'Cluster ' . ($cluster_id + 1),
'klasifikasi' => 'Cluster ' . ($cluster_id) . ' - ' . $clusterLabels[$cluster_id],
'waktu_proses' => $timestamp,
];
// Simpan data hasil klasifikasi dari iterasi terakhir
if ($iterasi == $maxIterasi || $newCentroids === $centroids) {
$finalData[] = [
'id' => $item['id'],
'cluster' => $cluster_id
];
}
}
$hasil_iterasi[] = [
'iterasi' => $iterasi,
'centroids' => $centroids,
'data' => $iterData,
];
if ($newCentroids === $centroids) {
// Update finalData jika konvergen sebelum iterasi maksimum
$finalData = []; // Reset dulu
foreach ($iterData as $item) {
$finalData[] = [
'id' => $item['id'],
'cluster' => $item['cluster']
];
}
break;
}
$centroids = $newCentroids;
}
// Hasil centroid akhir
$centroid_akhir = $centroids;
// Jumlah iterasi yang dilakukan
$jumlah_iterasi = count($hasil_iterasi);
// Keterangan klasifikasi untuk tampilan
$keterangan_klasifikasi = [
'C0' => 'TIDAK SESUAI',
'C1' => 'KURANG SESUAI',
'C2' => 'SESUAI'
];
// Encode centroid akhir untuk disimpan ke database
// $centroid_akhir_json = json_encode($centroid_akhir);
// return view('proses_klasifikasi', [
// 'angkatan' => $angkatan,
// 'jabatanMap' => Jabatan::pluck('Kategori_bidang_kerja', 'id_kategori')->toArray(),
// 'hasil_iterasi' => $hasil_iterasi,
// 'centroid_awal' => $centroid_awal,
// 'centroid_akhir' => $centroid_akhir,
// 'centroid_akhir_json' => $centroid_akhir_json,
// 'id_angkatan' => $id_angkatan,
// 'keterangan_klasifikasi' => $keterangan_klasifikasi,
// 'jumlah_iterasi' => $jumlah_iterasi,
// 'finalData' => $finalData, // Data yang akan disimpan
$centroid_akhir_json = json_encode($centroid_akhir);
return view('proses_klasifikasi', [
'angkatan' => $angkatan,
'jabatanMap' => Jabatan::pluck('Kategori_bidang_kerja', 'id_kategori')->toArray(),
'hasil_iterasi' => $hasil_iterasi,
'centroid_awal' => $centroid_awal,
'centroid_akhir' => $centroid_akhir,
'centroid_akhir_json' => $centroid_akhir_json,
'id_angkatan' => $id_angkatan,
'keterangan_klasifikasi' => $keterangan_klasifikasi,
'jumlah_iterasi' => $jumlah_iterasi,
'finalData' => $finalData, // Data yang akan disimpan
]);
}
}