gastrosaw/app/Http/Controllers/UserProsesSawController.php

445 lines
14 KiB
PHP

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Makanan;
use App\Models\RekomendasiUser;
class UserProsesSawController extends Controller
{
public function index()
{
return view('user.proses_saw.index');
}
public function proses(Request $request)
{
$request->validate([
'nama' => 'required',
'umur' => 'required|numeric',
'jenis_kelamin' => 'required',
'berat_badan' => 'required|numeric',
'tinggi_badan' => 'required|numeric',
'gejala' => 'required',
'aktivitas_harian' => 'required'
]);
$pasien = (object)[
'nama' => $request->nama,
'umur' => $request->umur,
'jenis_kelamin' => $request->jenis_kelamin,
'berat_badan' => $request->berat_badan,
'tinggi_badan' => $request->tinggi_badan,
'gejala' => implode(',', $request->gejala),
'aktivitas_harian' => $request->aktivitas_harian,
];
$gejalaList = explode(',', strtolower($pasien->gejala ?? ''));
$gejalaList = array_map('trim', $gejalaList);
if (empty($gejalaList) || in_array('tidak ada keluhan', $gejalaList)) {
return redirect()->back()
->with('error', 'Pasien tidak memiliki gejala gastritis.');
}
$kalori_harian = $this->hitungKaloriHarian($pasien);
$makanans = Makanan::query();
if (in_array('nyeri lambung', $gejalaList)) {
$makanans = $makanans->where('kandungan_lemak', '<=', 7);
}
if (in_array('mual', $gejalaList)) {
$makanans = $makanans
->where('kandungan_serat', '<=', 4)
->whereIn('tekstur', ['lunak', 'sedang']);
} else {
$makanans = $makanans
->whereIn('tekstur', ['lunak', 'sedang']);
}
$makanans = $makanans->get();
if ($makanans->isEmpty()) {
return redirect()->back()
->with('error', 'Tidak ada makanan yang sesuai.');
}
$hasil = $this->hitungSAW(
$makanans,
$gejalaList,
$pasien->aktivitas_harian,
$kalori_harian,
$pasien->jenis_kelamin
);
if (empty($hasil)) {
return redirect()->back()
->with('error', 'Perhitungan SAW gagal.');
}
usort($hasil, fn($a, $b) => $b['skor'] <=> $a['skor']);
$terbaik = $hasil[0];
$hasil = array_slice($hasil, 0, 10);
$jumlah_porsi = 1;
if ($pasien->berat_badan >= 70 || $pasien->aktivitas_harian == 'Berat') {
$ukuran_porsi = 'Mangkuk Sedang';
} else {
$ukuran_porsi = 'Mangkuk Kecil';
}
if ($pasien->aktivitas_harian == 'Berat') {
$frekuensi_makan = '3x makan utama + 3x snack';
} elseif ($pasien->aktivitas_harian == 'Sedang') {
$frekuensi_makan = '3x makan utama + 2-3x snack';
} else {
$frekuensi_makan = '3x makan utama + 2x snack';
}
$hasil_json = array_map(function ($item) use ($jumlah_porsi, $ukuran_porsi, $frekuensi_makan) {
return [
'id' => $item['makanan']->id ?? null,
'nama_makanan' => $item['nama_makanan'] ?? '-',
'tekstur' => $item['tekstur'] ?? '-',
'porsi_saji' => $item['porsi_saji'] ?? '-',
'jumlah_porsi' => $jumlah_porsi,
'ukuran_porsi' => $ukuran_porsi,
'frekuensi_makan' => $frekuensi_makan,
'cara_pengolahan' => $item['cara_pengolahan'] ?? '-',
'alternatif_serupa' => $item['alternatif_serupa'] ?? '-',
'komposisi_makanan' => $item['komposisi_makanan'] ?? '-',
'karbohidrat' => $item['karbohidrat'] ?? 0,
'lemak' => $item['lemak'] ?? 0,
'serat' => $item['serat'] ?? 0,
'kalori' => $item['kalori'] ?? 0,
'protein' => $item['protein'] ?? 0,
'skor' => round($item['skor'], 4)
];
}, $hasil);
RekomendasiUser::create([
'user_id' => auth()->id(),
'nama' => $pasien->nama,
'umur' => $pasien->umur,
'jenis_kelamin' => $pasien->jenis_kelamin,
'berat_badan' => $pasien->berat_badan,
'tinggi_badan' => $pasien->tinggi_badan,
'gejala' => $pasien->gejala,
'aktivitas_harian' => $pasien->aktivitas_harian,
'makanan_rekomendasi' => $terbaik['makanan']->nama_makanan,
'nilai_saw' => round($terbaik['skor'], 4),
'kebutuhan_kalori' => round($kalori_harian),
'hasil_json' => json_encode($hasil_json)
]);
return redirect()
->route('user.laporan.index')
->with('success', 'Rekomendasi berhasil');
}
private function hitungKaloriHarian($pasien)
{
if ($pasien->jenis_kelamin == 'Laki-laki') {
$bmr =
66 +
(13.7 * $pasien->berat_badan) +
(5 * $pasien->tinggi_badan) -
(6.8 * $pasien->umur);
} else {
$bmr =
655 +
(9.6 * $pasien->berat_badan) +
(1.8 * $pasien->tinggi_badan) -
(4.7 * $pasien->umur);
}
$faktor = [
'Ringan' => 1.2,
'Sedang' => 1.55,
'Berat' => 1.9
];
return $bmr * ($faktor[$pasien->aktivitas_harian] ?? 1.2);
}
private function hitungSAW($makanans, $gejalaList, $aktivitas, $kalori_harian, $jenis_kelamin)
{
$bobot = $this->tentukanBobot($gejalaList, $aktivitas);
$max_protein = max($makanans->max('protein'), 1);
$max_karbo = max($makanans->max('karbohidrat'), 1);
$hasil = [];
foreach ($makanans as $makanan) {
$n_protein = ($makanan->protein / $max_protein) * 0.85;
$n_karbo = ($makanan->karbohidrat / $max_karbo) * 0.85;
if ($aktivitas == 'Berat') {
$ideal_kalori = $kalori_harian * 0.12;
} elseif ($aktivitas == 'Sedang') {
$ideal_kalori = $kalori_harian * 0.09;
} else {
$ideal_kalori = $kalori_harian * 0.06;
}
if (in_array('mual', $gejalaList)) {
$ideal_kalori *= 0.90;
}
$ideal_kalori = max($ideal_kalori, 1);
$selisih = abs($makanan->kalori - $ideal_kalori);
$n_kalori = 1 / (1 + ($selisih / $ideal_kalori));
$n_kalori *= 0.80;
// =========================
// PENYESUAIAN ENERGI BERDASARKAN JENIS KELAMIN
// =========================
if ($jenis_kelamin == 'Laki-laki') {
if ($makanan->kalori >= ($ideal_kalori * 0.60)) {
$n_kalori *= 1.10;
}
if ($makanan->protein >= 5) {
$n_protein *= 1.08;
}
if ($makanan->karbohidrat >= 30) {
$n_karbo *= 1.05;
}
} else {
if ($makanan->kalori > ($ideal_kalori * 0.95)) {
$n_kalori *= 0.96;
}
}
if ($aktivitas == 'Ringan') {
if ($makanan->kalori > ($ideal_kalori * 1.80)) {
$n_kalori *= 0.35;
$n_karbo *= 0.75;
} elseif ($makanan->kalori > ($ideal_kalori * 1.35)) {
$n_kalori *= 0.55;
$n_karbo *= 0.85;
}
}
if ($aktivitas == 'Sedang') {
if ($makanan->kalori > ($ideal_kalori * 1.90)) {
$n_kalori *= 0.60;
$n_karbo *= 0.85;
}
}
if ($aktivitas == 'Berat') {
if ($makanan->kalori >= ($ideal_kalori * 0.80)) {
$n_kalori *= 1.12;
}
if ($makanan->protein >= 5) {
$n_protein *= 1.12;
}
if ($makanan->karbohidrat >= 30) {
$n_karbo *= 1.08;
}
}
$n_protein = min($n_protein, 1);
$n_karbo = min($n_karbo, 1);
$n_kalori = min($n_kalori, 1);
if ($makanan->kandungan_lemak <= 2) {
$n_lemak = 0.90;
} elseif ($makanan->kandungan_lemak <= 4) {
$n_lemak = 0.78;
} elseif ($makanan->kandungan_lemak <= 6) {
$n_lemak = 0.60;
} else {
$n_lemak = 0.40;
}
if ($jenis_kelamin != 'Laki-laki' && $makanan->kandungan_lemak > 4) {
$n_lemak *= 0.92;
}
if ($makanan->kandungan_serat <= 1) {
$n_serat = 0.90;
} elseif ($makanan->kandungan_serat <= 2) {
$n_serat = 0.78;
} elseif ($makanan->kandungan_serat <= 4) {
$n_serat = 0.60;
} else {
$n_serat = 0.40;
}
$n_tekstur = match (strtolower($makanan->tekstur)) {
'lunak' => 0.90,
'sedang' => 0.70,
default => 0.40
};
if (in_array('mual', $gejalaList)) {
if ($makanan->kandungan_lemak > 5) {
$n_lemak *= 0.70;
}
if ($makanan->kandungan_serat > 2) {
$n_serat *= 0.75;
}
if (strtolower($makanan->tekstur) != 'lunak') {
$n_tekstur *= 0.85;
}
}
if (in_array('nyeri lambung', $gejalaList)) {
if ($makanan->kandungan_serat > 3) {
$n_serat *= 0.60;
}
if ($makanan->kandungan_lemak > 5) {
$n_lemak *= 0.75;
}
}
$skor =
($n_protein * $bobot['protein']) +
($n_lemak * $bobot['lemak']) +
($n_karbo * $bobot['karbohidrat']) +
($n_serat * $bobot['serat']) +
($n_kalori * $bobot['kalori']) +
($n_tekstur * $bobot['tekstur']);
$faktorAktivitasSkor = match ($aktivitas) {
'Ringan' => 0.92,
'Sedang' => 1.00,
'Berat' => 1.10,
default => 1.00
};
$skor = $skor * $faktorAktivitasSkor;
// =========================
// PENYESUAIAN SKOR AKHIR BERDASARKAN KEBUTUHAN ENERGI
// =========================
if ($jenis_kelamin == 'Laki-laki') {
$skor *= match ($aktivitas) {
'Ringan' => 1.02,
'Sedang' => 1.03,
'Berat' => 1.04,
default => 1.02
};
} else {
$skor *= 0.98;
}
$skor = min($skor, 1);
$hasil[] = [
'makanan' => $makanan,
'nama_makanan' => $makanan->nama_makanan,
'protein' => $makanan->protein,
'lemak' => $makanan->kandungan_lemak,
'karbohidrat' => $makanan->karbohidrat,
'serat' => $makanan->kandungan_serat,
'kalori' => $makanan->kalori,
'tekstur' => $makanan->tekstur,
'porsi_saji' => $makanan->porsi_saji,
'cara_pengolahan' => $makanan->cara_pengolahan,
'alternatif_serupa' => $makanan->alternatif_serupa,
'komposisi_makanan' => $makanan->komposisi_makanan,
'skor' => round($skor, 4)
];
}
return $hasil;
}
private function tentukanBobot($gejalaList, $aktivitas)
{
if (in_array('mual', $gejalaList)) {
if ($aktivitas == 'Berat') {
return [
'tekstur' => 0.18,
'serat' => 0.14,
'lemak' => 0.17,
'karbohidrat' => 0.21,
'protein' => 0.13,
'kalori' => 0.17
];
}
if ($aktivitas == 'Sedang') {
return [
'tekstur' => 0.25,
'serat' => 0.16,
'lemak' => 0.18,
'karbohidrat' => 0.18,
'protein' => 0.10,
'kalori' => 0.13
];
}
return [
'tekstur' => 0.45,
'serat' => 0.22,
'lemak' => 0.18,
'karbohidrat' => 0.07,
'protein' => 0.05,
'kalori' => 0.03
];
}
if ($aktivitas == 'Berat') {
return [
'lemak' => 0.20,
'tekstur' => 0.16,
'serat' => 0.10,
'protein' => 0.16,
'karbohidrat' => 0.18,
'kalori' => 0.20
];
}
if ($aktivitas == 'Sedang') {
return [
'lemak' => 0.30,
'tekstur' => 0.24,
'serat' => 0.14,
'protein' => 0.12,
'karbohidrat' => 0.12,
'kalori' => 0.08
];
}
return [
'lemak' => 0.36,
'tekstur' => 0.27,
'serat' => 0.16,
'protein' => 0.09,
'karbohidrat' => 0.07,
'kalori' => 0.05
];
}
}