MIF_E31222307/app/Http/Controllers/RekomendasiController.php

139 lines
4.7 KiB
PHP

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Makanan;
use App\Models\Kriteria;
use App\Models\BobotKriteria;
use App\Models\SkorMakanan;
use App\Models\Rekomendasi;
use App\Models\WaktuMakan;
use App\Models\Komponen;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
class RekomendasiController extends Controller
{
public function hitungDanSimpanOtomatis()
{
$kriterias = Kriteria::all();
$defaultBobots = BobotKriteria::pluck('bobot', 'kriteria_id');
$waktuMakans = WaktuMakan::all();
$komponens = Komponen::all();
SkorMakanan::truncate();
Rekomendasi::where('user_id', Auth::id())->delete();
foreach ($waktuMakans as $waktu) {
// Ambil preferensi bobot kriteria untuk waktu makan ini
$preferensiBobot = \App\Models\PreferensiWaktuKriteria::where('waktu_makan_id', $waktu->id)
->pluck('bobot', 'kriteria_id');
foreach ($komponens as $komponen) {
$makanans = Makanan::whereHas('komponenWaktu', function ($query) use ($komponen, $waktu) {
$query->where('komponen_id', $komponen->id)
->where('waktu_makan_id', $waktu->id);
})->get();
if ($makanans->isEmpty()) continue;
$total = [
'lemak' => $makanans->sum('lemak') ?: 1,
'natrium' => $makanans->sum('natrium') ?: 1,
'energi' => $makanans->sum('energi') ?: 1,
'karbohidrat' => $makanans->sum('karbohidrat') ?: 1,
];
foreach ($makanans as $makanan) {
$skor = 0;
foreach ($kriterias as $kriteria) {
$attr = strtolower($kriteria->nama);
$nilai = $makanan->$attr ?? 0;
// Normalisasi
$normalized = in_array($attr, ['lemak', 'natrium'])
? 1 - ($nilai / $total[$attr])
: $nilai / $total[$attr];
// Gunakan preferensi waktu jika ada, jika tidak fallback
$bobot = $preferensiBobot[$kriteria->id] ?? $defaultBobots[$kriteria->id] ?? 0;
$skor += $normalized * $bobot;
SkorMakanan::updateOrCreate([
'kriteria_id' => $kriteria->id,
'makanan_id' => $makanan->id,
], [
'nilai' => $normalized
]);
}
// Simpan nilai akhir ke rekomendasi
Rekomendasi::updateOrCreate(
[
'user_id' => Auth::id(),
'makanan_id' => $makanan->id,
'komponen_id' => $komponen->id,
'waktu_makan_id' => $waktu->id,
],
[
'nilai_akhir' => $skor,
'tanggal_rekomendasi' => now(),
]
);
}
}
}
return redirect()->route('rekomendasi.hasil')->with('success', 'Rekomendasi berhasil dihitung dengan bobot preferensi waktu.');
}
public function tampilHasil()
{
$rekomendasi = Rekomendasi::with('makanan', 'komponen', 'waktuMakan')
->where('user_id', Auth::id())
// ->whereDate('tanggal_rekomendasi', now())
->get();
// Urutan komponen manual
$urutanKomponen = ['karbohidrat', 'protein', 'sayur', 'buah', 'susu'];
// Hitung total nilai_akhir per waktu & komponen
$totalPerGroup = [];
foreach ($rekomendasi as $r) {
$waktu = strtolower($r->waktuMakan->nama);
$komponen = strtolower($r->komponen->nama);
$totalPerGroup[$waktu][$komponen] = ($totalPerGroup[$waktu][$komponen] ?? 0) + $r->nilai_akhir;
}
// Group dan sort data
$rekomendasiGrouped = $rekomendasi
->groupBy([
fn($item) => strtolower($item->waktuMakan->nama),
fn($item) => strtolower($item->komponen->nama),
]);
foreach ($rekomendasiGrouped as $waktu => $komponens) {
$sorted = collect();
foreach ($urutanKomponen as $target) {
if ($komponens->has($target)) {
// Tambahkan properti persentase ke setiap item
$komponens[$target]->each(function ($item) use ($totalPerGroup, $waktu, $target) {
$total = $totalPerGroup[$waktu][$target] ?: 1;
$item->persentase = ($item->nilai_akhir / $total) * 100;
});
$sorted[$target] = $komponens[$target]->sortByDesc('nilai_akhir');
}
}
$rekomendasiGrouped[$waktu] = $sorted;
}
return view('admin.rekomendasi', ['rekomendasi' => $rekomendasiGrouped]);
}
}