json([ 'success' => false, 'message' => 'User belum login.' ], 401); } $validated = $request->validate([ 'agama' => 'required|numeric|min:0|max:100', 'pkn' => 'required|numeric|min:0|max:100', 'bahasa_indonesia' => 'required|numeric|min:0|max:100', 'bahasa_inggris' => 'required|numeric|min:0|max:100', 'matematika' => 'required|numeric|min:0|max:100', 'fisika' => 'required|numeric|min:0|max:100', 'kimia' => 'required|numeric|min:0|max:100', 'biologi' => 'required|numeric|min:0|max:100', 'sejarah' => 'required|numeric|min:0|max:100', 'geografi' => 'required|numeric|min:0|max:100', 'ekonomi_mapel' => 'required|numeric|min:0|max:100', 'sosiologi' => 'required|numeric|min:0|max:100', 'seni_budaya' => 'required|numeric|min:0|max:100', 'pjok' => 'required|numeric|min:0|max:100', 'informatika' => 'required|numeric|min:0|max:100', 'riasec_r' => 'required|numeric|min:0|max:100', 'riasec_i' => 'required|numeric|min:0|max:100', 'riasec_a' => 'required|numeric|min:0|max:100', 'riasec_s' => 'required|numeric|min:0|max:100', 'riasec_e' => 'required|numeric|min:0|max:100', 'riasec_c' => 'required|numeric|min:0|max:100', 'gaji_ortu' => 'required|numeric|min:0', ]); $ekonomiOrangTua = self::getLabelEkonomiSingkat($validated['gaji_ortu']); $payload = $validated; $payload['ekonomi_orang_tua'] = $ekonomiOrangTua; try { $response = Http::timeout(15) ->acceptJson() ->post('http://127.0.0.1:5000/predict', $payload); if (!$response->successful()) { return response()->json([ 'success' => false, 'message' => 'ML Engine Error: ' . ($response->json()['message'] ?? $response->body()) ], 500); } $responseData = $response->json(); if (!isset($responseData['success']) || !$responseData['success']) { return response()->json([ 'success' => false, 'message' => 'ML Engine Error: ' . ($responseData['message'] ?? 'Unknown Error') ], 500); } $teksJurusan = $responseData['prediksi_jurusan'] ?? null; if (!$teksJurusan) { return response()->json([ 'success' => false, 'message' => 'Prediksi jurusan tidak ditemukan pada respons Flask.' ], 500); } $riwayat = RiwayatRekomendasi::create([ 'user_id' => $user->id, 'agama' => $validated['agama'], 'pkn' => $validated['pkn'], 'bahasa_indonesia' => $validated['bahasa_indonesia'], 'bahasa_inggris' => $validated['bahasa_inggris'], 'matematika' => $validated['matematika'], 'fisika' => $validated['fisika'], 'kimia' => $validated['kimia'], 'biologi' => $validated['biologi'], 'sejarah' => $validated['sejarah'], 'geografi' => $validated['geografi'], 'ekonomi_mapel' => $validated['ekonomi_mapel'], 'sosiologi' => $validated['sosiologi'], 'seni_budaya' => $validated['seni_budaya'], 'pjok' => $validated['pjok'], 'informatika' => $validated['informatika'], 'riasec_r' => $validated['riasec_r'], 'riasec_i' => $validated['riasec_i'], 'riasec_a' => $validated['riasec_a'], 'riasec_s' => $validated['riasec_s'], 'riasec_e' => $validated['riasec_e'], 'riasec_c' => $validated['riasec_c'], 'gaji_ortu' => $validated['gaji_ortu'], 'hasil_rekomendasi_jurusan' => $teksJurusan, ]); return response()->json([ 'success' => true, 'message' => 'Prediksi berhasil dibuat.', 'redirect_url' => route('student.result', ['id' => $riwayat->id]), 'prediksi_jurusan' => $teksJurusan, 'top_predictions' => $responseData['top_predictions'] ?? null ]); } catch (\Throwable $e) { return response()->json([ 'success' => false, 'message' => 'Koneksi ke API Flask Python gagal: ' . $e->getMessage() ], 500); } } public function getHasilRekomendasi($id) { $riwayat = RiwayatRekomendasi::findOrFail($id); return response()->json([ 'success' => true, 'data' => self::formatHasilData($riwayat) ]); } public static function formatHasilData(RiwayatRekomendasi $riwayat): array { return [ 'id' => $riwayat->id, 'hasil_rekomendasi_jurusan' => $riwayat->hasil_rekomendasi_jurusan, 'label_ekonomi' => self::getLabelEkonomiDetail($riwayat->gaji_ortu), 'minat_utama' => self::getMinatUtamaLabel($riwayat), 'prospek_kerja' => self::getProspekKerjaText($riwayat->hasil_rekomendasi_jurusan), 'gaji_ortu' => $riwayat->gaji_ortu, 'riasec' => [ 'r' => $riwayat->riasec_r, 'i' => $riwayat->riasec_i, 'a' => $riwayat->riasec_a, 's' => $riwayat->riasec_s, 'e' => $riwayat->riasec_e, 'c' => $riwayat->riasec_c, ], ]; } public static function getLabelEkonomiSingkat($gaji): string { $gaji = (float) $gaji; if ($gaji < 2000000) { return 'Kurang Mampu'; } elseif ($gaji <= 5000000) { return 'Menengah'; } return 'Mampu'; } public static function getLabelEkonomiDetail($gaji): string { $gaji = (float) $gaji; if ($gaji < 2000000) { return 'Kurang Mampu (< Rp 2.000.000)'; } elseif ($gaji <= 5000000) { return 'Menengah (Rp 2.000.000 - Rp 5.000.000)'; } return 'Mampu (> Rp 5.000.000)'; } public static function getMinatUtamaLabel(RiwayatRekomendasi $riwayat): string { $riasecScores = [ 'r' => (float) $riwayat->riasec_r, 'i' => (float) $riwayat->riasec_i, 'a' => (float) $riwayat->riasec_a, 's' => (float) $riwayat->riasec_s, 'e' => (float) $riwayat->riasec_e, 'c' => (float) $riwayat->riasec_c, ]; arsort($riasecScores); $topCode = array_key_first($riasecScores); $labels = [ 'r' => 'Teknis & Lapangan', 'i' => 'Sains, Riset & Analitis', 'a' => 'Kreatif & Desain', 's' => 'Sosial & Pelayanan', 'e' => 'Bisnis & Kepemimpinan', 'c' => 'Administratif & Terstruktur', ]; return $labels[$topCode] ?? 'Belum teridentifikasi'; } public static function getProspekKerjaText($jurusan): string { $jurusan = strtolower((string) $jurusan); if (str_contains($jurusan, 'ekonomi') || str_contains($jurusan, 'manajemen') || str_contains($jurusan, 'bisnis')) { return 'Lulusan bidang ini dapat berkarier sebagai manajer bisnis, staf keuangan, analis pasar, konsultan bisnis, wirausahawan, maupun pegawai instansi pemerintah dan BUMN pada sektor ekonomi dan administrasi.'; } if (str_contains($jurusan, 'teknik') || str_contains($jurusan, 'informatika') || str_contains($jurusan, 'komputer')) { return 'Lulusan bidang ini memiliki peluang karier sebagai software developer, analis sistem, teknisi, network engineer, data analyst, maupun profesional teknologi di perusahaan swasta, startup, dan instansi pemerintah.'; } if (str_contains($jurusan, 'kesehatan') || str_contains($jurusan, 'keperawatan') || str_contains($jurusan, 'farmasi')) { return 'Lulusan bidang ini dapat berkarier di rumah sakit, klinik, laboratorium, industri kesehatan, layanan masyarakat, maupun lembaga penelitian kesehatan.'; } if (str_contains($jurusan, 'pendidikan') || str_contains($jurusan, 'guru')) { return 'Lulusan bidang ini memiliki prospek sebagai guru, tenaga pendidik, instruktur pelatihan, pengembang kurikulum, maupun konsultan pendidikan.'; } return 'Prospek karier untuk jurusan ini sangat luas, mulai dari spesialis industri, konsultan ahli, hingga pegawai instansi pemerintah/BUMN di sektor terkait.'; } }