waktu_makan_id; $komponenId = $request->komponen_id; if ($waktuMakanId && $komponenId) { $query = MakananKomponenWaktu::with('makanan') ->where('waktu_makan_id', $waktuMakanId); $makananKomponenWaktu = $query->where('status', true)->get(); if ($makananKomponenWaktu->isEmpty()) { $makananKomponenWaktu = MakananKomponenWaktu::with('makanan') ->where('waktu_makan_id', $waktuMakanId) ->get(); } $filtered = $makananKomponenWaktu->where('komponen_id', $komponenId); $makanans = $filtered->map(function($item) { $makanan = $item->makanan; $makanan->komponen_id = $item->komponen_id; return $makanan; })->values(); } return view('user.simulasi.index', compact('waktuMakans', 'komponens', 'kriterias', 'makanans')); } public function getMakananByKomponen($komponen, $waktuMakan) { // Ambil semua data makanan_komponen_waktu untuk waktu makan tertentu $query = MakananKomponenWaktu::with('makanan') ->where('waktu_makan_id', $waktuMakan); // Coba filter status true dulu $makananKomponenWaktu = $query->where('status', true)->get(); // Jika kosong, ambil semua tanpa filter status if ($makananKomponenWaktu->isEmpty()) { $makananKomponenWaktu = MakananKomponenWaktu::with('makanan') ->where('waktu_makan_id', $waktuMakan) ->get(); } // Filter berdasarkan komponen $filtered = $makananKomponenWaktu->where('komponen_id', $komponen); // Map ke array makanan, tambahkan komponen_id $makanans = $filtered->map(function($item) { $makanan = $item->makanan; $makanan->komponen_id = $item->komponen_id; return $makanan; })->values(); return response()->json($makanans); } public function prosesSimulasi(Request $request) { try { DB::beginTransaction(); // Validasi minimal 4 makanan $selectedMakanans = collect($request->makanan_ids)->filter()->values(); if ($selectedMakanans->count() < 4) { return redirect()->back()->with('error', 'Pilih minimal 4 makanan untuk simulasi'); } $waktuMakanId = $request->waktu_makan_id; $komponenId = $request->komponen_id; $kriterias = Kriteria::all(); // Ambil bobot kriteria berdasarkan waktu makan $bobotKriteria = []; foreach ($kriterias as $kriteria) { $bobot = BobotKriteria::where('kriteria_id', $kriteria->id) ->where('waktu_makan_id', $waktuMakanId) ->first(); $bobotKriteria[$kriteria->id] = $bobot ? $bobot->bobot : 0; } // Normalisasi bobot kriteria $totalBobot = array_sum($bobotKriteria); if ($totalBobot > 0) { foreach ($bobotKriteria as $key => $value) { $bobotKriteria[$key] = $value / $totalBobot; } } // Buat record simulasi baru $simulasi = SimulasiAhp::create([ 'user_id' => Auth::id(), 'judul' => 'Simulasi ' . WaktuMakan::find($waktuMakanId)->nama . ' - ' . Komponen::find($komponenId)->nama, 'pilihan_makanan_ids' => $selectedMakanans->toArray(), 'hasil_rangking' => [] ]); // Proses perbandingan berpasangan untuk setiap kriteria foreach ($kriterias as $kriteria) { $matriksPerbandingan = []; $jumlahKolom = []; // Inisialisasi matriks foreach ($selectedMakanans as $makananId) { $jumlahKolom[$makananId] = 0; foreach ($selectedMakanans as $makananId2) { $matriksPerbandingan[$makananId][$makananId2] = 1; } } // Hitung nilai perbandingan berdasarkan kriteria foreach ($selectedMakanans as $makananId1) { $makanan1 = Makanan::find($makananId1); foreach ($selectedMakanans as $makananId2) { if ($makananId1 != $makananId2) { $makanan2 = Makanan::find($makananId2); $nilai1 = $this->getNilaiKriteria($makanan1, $kriteria); $nilai2 = $this->getNilaiKriteria($makanan2, $kriteria); if ($nilai1 > 0 && $nilai2 > 0) { // Terapkan nilai invers untuk kriteria cost (lemak dan natrium) if (in_array(strtolower($kriteria->nama), ['lemak', 'natrium'])) { $ratio = $nilai2 / $nilai1; // Invers untuk cost } else { $ratio = $nilai1 / $nilai2; } if ($ratio > 9) $ratio = 9; if ($ratio < 1/9) $ratio = 1/9; $matriksPerbandingan[$makananId1][$makananId2] = $ratio; $matriksPerbandingan[$makananId2][$makananId1] = 1 / $ratio; } } } } // Simpan matriks perbandingan berpasangan foreach ($selectedMakanans as $makananId1) { foreach ($selectedMakanans as $makananId2) { if ($makananId1 != $makananId2) { SimulasiAhpPairwise::create([ 'simulasi_ahp_id' => $simulasi->id, 'makanan_1_id' => $makananId1, 'makanan_2_id' => $makananId2, 'nilai' => $matriksPerbandingan[$makananId1][$makananId2] ]); } } } // Hitung jumlah kolom foreach ($selectedMakanans as $makananId2) { foreach ($selectedMakanans as $makananId1) { $jumlahKolom[$makananId2] += $matriksPerbandingan[$makananId1][$makananId2]; } } // Normalisasi matriks dan hitung priority vector $matriksNormal = []; $priorityVector = []; foreach ($selectedMakanans as $makananId1) { $jumlahBaris = 0; foreach ($selectedMakanans as $makananId2) { if ($jumlahKolom[$makananId2] != 0) { $nilai = $matriksPerbandingan[$makananId1][$makananId2] / $jumlahKolom[$makananId2]; $matriksNormal[$makananId1][$makananId2] = $nilai; $jumlahBaris += $nilai; } } $priorityVector[$makananId1] = $jumlahBaris / count($selectedMakanans); } // Simpan hasil normalisasi foreach ($selectedMakanans as $makananId) { SimulasiAhpNormalisasi::create([ 'simulasi_ahp_id' => $simulasi->id, 'makanan_id' => $makananId, 'nilai_normalisasi' => $priorityVector[$makananId], 'bobot_akhir' => $priorityVector[$makananId] * $bobotKriteria[$kriteria->id] ]); } // Hitung Consistency Ratio $n = count($selectedMakanans); if ($n > 1) { $lambdaMax = 0; foreach ($selectedMakanans as $makananId1) { $sum = 0; foreach ($selectedMakanans as $makananId2) { $sum += $matriksPerbandingan[$makananId1][$makananId2] * $priorityVector[$makananId2]; } $lambdaMax += $sum / $priorityVector[$makananId1]; } $lambdaMax /= $n; $CI = ($lambdaMax - $n) / ($n - 1); $RI = [ 1 => 0.00, 2 => 0.00, 3 => 0.58, 4 => 0.90, 5 => 1.12, 6 => 1.24, 7 => 1.32, 8 => 1.41, 9 => 1.45, 10 => 1.49 ]; $CR = $CI / ($RI[$n] ?? end($RI)); // Simpan CR ke database ConsistencyRatioAlternatif::updateOrCreate( [ 'kriteria_id' => $kriteria->id, 'waktu_makan_id' => $waktuMakanId, 'komponen_id' => $komponenId ], [ 'ci' => $CI, 'cr' => $CR, 'is_consistent' => $CR <= 0.1 ] ); } // Simpan skor ke database foreach ($selectedMakanans as $makananId) { SkorMakanan::updateOrCreate( [ 'makanan_id' => $makananId, 'kriteria_id' => $kriteria->id, 'waktu_makan_id' => $waktuMakanId, 'komponen_id' => $komponenId ], ['nilai' => $priorityVector[$makananId]] ); } } // Hitung skor akhir $hasilRekomendasi = []; foreach ($selectedMakanans as $makananId) { $skorAkhir = 0; foreach ($kriterias as $kriteria) { $skor = SkorMakanan::where([ 'makanan_id' => $makananId, 'kriteria_id' => $kriteria->id, 'waktu_makan_id' => $waktuMakanId, 'komponen_id' => $komponenId ])->first(); if ($skor) { $skorAkhir += $skor->nilai * $bobotKriteria[$kriteria->id]; } } $hasilRekomendasi[$makananId] = $skorAkhir; } // Urutkan hasil berdasarkan skor arsort($hasilRekomendasi); // Update hasil ranking di tabel simulasi $simulasi->update(['hasil_rangking' => $hasilRekomendasi]); // Simpan hasil ke session Session::put('hasil_simulasi', [ 'simulasi_id' => $simulasi->id, 'waktu_makan_id' => $waktuMakanId, 'komponen_id' => $komponenId, 'hasil' => $hasilRekomendasi, 'makanan_ids' => $selectedMakanans->toArray(), 'bobot_kriteria' => $bobotKriteria ]); DB::commit(); return redirect()->route('user.simulasi.hasil'); } catch (\Exception $e) { DB::rollback(); return redirect()->back()->with('error', 'Terjadi kesalahan: ' . $e->getMessage()); } } public function hasil() { $hasilSimulasi = Session::get('hasil_simulasi'); if (!$hasilSimulasi) { return redirect()->route('user.simulasi.index'); } $waktuMakan = WaktuMakan::find($hasilSimulasi['waktu_makan_id']); $komponen = Komponen::find($hasilSimulasi['komponen_id']); $makanans = Makanan::whereIn('id', $hasilSimulasi['makanan_ids'])->get(); $kriterias = Kriteria::all(); $crCriteria = \App\Models\ConsistencyRatioCriteria::where('waktu_makan_id', $waktuMakan->id ?? $hasilSimulasi['waktu_makan_id'])->orderByDesc('created_at')->first(); return view('user.simulasi.hasil', compact('hasilSimulasi', 'waktuMakan', 'komponen', 'makanans', 'kriterias', 'crCriteria')); } public function history() { $simulasis = SimulasiAhp::where('user_id', Auth::id()) ->orderBy('created_at', 'desc') ->paginate(10); return view('user.simulasi.history', compact('simulasis')); } public function detailHistory($id) { $simulasi = SimulasiAhp::where('user_id', Auth::id()) ->where('id', $id) ->firstOrFail(); $makanans = Makanan::whereIn('id', $simulasi->pilihan_makanan_ids)->get(); $pairwise = SimulasiAhpPairwise::where('simulasi_ahp_id', $id)->get(); $normalisasi = SimulasiAhpNormalisasi::where('simulasi_ahp_id', $id)->get(); return view('user.simulasi.detail-history', compact('simulasi', 'makanans', 'pairwise', 'normalisasi')); } private function getNilaiKriteria($makanan, $kriteria) { switch (strtolower($kriteria->nama)) { case 'energi': return $makanan->energi; case 'lemak': return $makanan->lemak; case 'karbohidrat': return $makanan->karbohidrat; case 'natrium': return $makanan->natrium; default: return 0; } } }