445 lines
14 KiB
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
|
|
];
|
|
}
|
|
} |