139 lines
4.7 KiB
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]);
|
|
}
|
|
|
|
}
|