From a2169a7b06d9ef5423942ee41ceaa02f782fd0fe Mon Sep 17 00:00:00 2001 From: arieeefajar Date: Mon, 31 Mar 2025 19:57:02 +0700 Subject: [PATCH] fix(assessment-form): function certainty factor calculation --- .../Controllers/AssesmentFormController.php | 128 ++++++++++++++---- ...085614_create_evaluation_details_table.php | 2 +- resources/views/assessment/form.blade.php | 26 ++-- 3 files changed, 117 insertions(+), 39 deletions(-) diff --git a/app/Http/Controllers/AssesmentFormController.php b/app/Http/Controllers/AssesmentFormController.php index 48b66b5..20ca5e3 100644 --- a/app/Http/Controllers/AssesmentFormController.php +++ b/app/Http/Controllers/AssesmentFormController.php @@ -7,6 +7,7 @@ use App\Models\Indicator; use App\Models\Land; use App\Models\Rule; +use Dotenv\Parser\Value; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Validator; @@ -18,12 +19,21 @@ public function index() $lands = Land::select('id', 'owner')->whereNotIn('id', function ($query) { $query->select('land_id')->from('evaluation'); })->orderBy('created_at', 'desc')->get(); - $indicators = Indicator::select('id', 'name')->whereIn('id', function ($query) { - $query->select('indicator_id')->from('rule'); - })->get(); + $indicators = Indicator::select('id', 'name')->whereHas('rules')->with('rules')->get(); return view('assessment.form', compact('lands', 'indicators')); } + public function calculateCFc($cf1, $cf2) + { + if ($cf1 >= 0 && $cf2 >= 0) { + return $cf1 + $cf2 * (1 - $cf1); + } elseif ($cf1 < 0 && $cf2 < 0) { + return $cf1 + $cf2 * (1 + $cf1); + } else { + return ($cf1 + $cf2) / (1 - min(abs($cf1), abs($cf2))); + } + } + public function store(Request $request) { $customMessages = [ @@ -40,54 +50,120 @@ public function store(Request $request) return redirect()->back()->withInput(); } - $indicators = $request->except('_token', 'land'); - if (count($indicators) == 0) { + $cf_e = $request->except('_token', 'land'); + if (count($cf_e) == 0) { toast('Harap pilih jawaban untuk nilai indikator', 'error')->position('top-right')->autoclose(3000); return redirect()->back(); } - $rules = Rule::whereIn('indicator_id', array_keys($indicators))->get()->keyBy('indicator_id'); + $cf_h = collect(Rule::whereIn('indicator_id', array_keys($cf_e)) + ->orderByDesc('cf') + ->get() + ->unique('indicator_id') + ->pluck('cf', 'indicator_id') + ->sortKeys()); - $cfValue = []; - foreach ($indicators as $id => $value) { - if (isset($rules[$id])) { - $rule = $rules[$id]; - $cfValue[$id] = $rule->mb * $value; - } else { - toast("Rule untuk indikator ID {$id} tidak ditemukan.", 'error')->position('top-right')->autoclose(3000); - return redirect()->back(); - } + + $cf_he = collect($cf_e)->map(function ($value, $key) use ($cf_h) { + return [ + "cf(h,e)" . $key => (float) $value * (float) ($cf_h[$key] ?? 1) + ]; + })->collapse(); + + $cf_he_array = $cf_he->toArray(); + + $cf_combined = array_shift($cf_he_array); + + foreach ($cf_he_array as $cf) { + $cf_combined = $this->calculateCFc($cf_combined, $cf); } - $cfCombine = array_shift($cfValue); + $cf_pakar = Rule::pluck('cf')->toArray(); - foreach ($cfValue as $cf) { - $cfCombine = $cfCombine + $cf * (1 - $cfCombine); + $mean_cf = collect($cf_pakar)->avg(); + $std_dev_cf = sqrt(collect($cf_pakar)->map(function ($cf) use ($mean_cf) { + return pow($cf - $mean_cf, 2); + })->avg()); + + $threshold_cocok = $mean_cf + $std_dev_cf; + $threshold_cocok_bersyarat = $mean_cf - $std_dev_cf; + + if ($cf_combined > $threshold_cocok) { + $hasil = 'cocok'; + } elseif ($cf_combined > $threshold_cocok_bersyarat) { + $hasil = 'cocok bersyarat'; + } else { + $hasil = 'tidak cocok'; } + $landName = Land::find($request->land)->owner; + // dd($cf_e, $cf_h, $cf_he, $cf_he_array, $cf_combined, $hasil); + DB::beginTransaction(); try { $evaluation = new Evaluation; $evaluation->land_id = $request->land; - $evaluation->cf_value = $cfCombine; + $evaluation->cf_value = $cf_combined; $evaluation->user_id = auth()->user()->id; $evaluation->save(); - foreach ($indicators as $id => $value) { - $evaluationDetail = new EvaluationDetail(); + foreach ($cf_e as $id => $value) { + $evaluationDetail = new EvaluationDetail; $evaluationDetail->evaluation_id = $evaluation->id; $evaluationDetail->indicator_id = $id; - $evaluationDetail->md_value = $value; + $evaluationDetail->cf_e = $value; $evaluationDetail->save(); } DB::commit(); - $presentase = round($cfCombine * 100, 2); - toast('Data berhasil disimpan', 'success')->position('top-right')->autoclose(3000); - return redirect()->back()->with('presentase', $presentase); + $presentase = round($cf_combined * 100, 2); + toast("Data berhasil disimpan.", "success")->position('top-right')->autoclose(3000); + return redirect()->back()->with(['land' => $landName, 'presentase' => $presentase, 'hasil' => $hasil]); } catch (\Throwable $th) { DB::rollBack(); - toast('Terjadi kesalahan', 'error')->position('top-right')->autoclose(3000); + toast($th->getMessage(), 'error')->position('top-right')->autoclose(3000); return redirect()->back(); } + + // $cfValue = []; + // foreach ($cf_e as $id => $value) { + // if (isset($rules[$id])) { + // $rule = $rules[$id]; + // $cfValue[$id] = $rule->mb * $value; + // } else { + // toast("Rule untuk indikator ID {$id} tidak ditemukan.", 'error')->position('top-right')->autoclose(3000); + // return redirect()->back(); + // } + // } + + // $cfCombine = array_shift($cfValue); + + // foreach ($cfValue as $cf) { + // $cfCombine = $cfCombine + $cf * (1 - $cfCombine); + // } + + // DB::beginTransaction(); + // try { + // $evaluation = new Evaluation; + // $evaluation->land_id = $request->land; + // $evaluation->cf_value = $cfCombine; + // $evaluation->user_id = auth()->user()->id; + // $evaluation->save(); + + // foreach ($indicators as $id => $value) { + // $evaluationDetail = new EvaluationDetail(); + // $evaluationDetail->evaluation_id = $evaluation->id; + // $evaluationDetail->indicator_id = $id; + // $evaluationDetail->md_value = $value; + // $evaluationDetail->save(); + // } + // DB::commit(); + // $presentase = round($cfCombine * 100, 2); + // toast('Data berhasil disimpan', 'success')->position('top-right')->autoclose(3000); + // return redirect()->back()->with('presentase', $presentase); + // } catch (\Throwable $th) { + // DB::rollBack(); + // toast('Terjadi kesalahan', 'error')->position('top-right')->autoclose(3000); + // return redirect()->back(); + // } } } diff --git a/database/migrations/2025_02_06_085614_create_evaluation_details_table.php b/database/migrations/2025_02_06_085614_create_evaluation_details_table.php index 417f33c..4505548 100644 --- a/database/migrations/2025_02_06_085614_create_evaluation_details_table.php +++ b/database/migrations/2025_02_06_085614_create_evaluation_details_table.php @@ -15,7 +15,7 @@ public function up(): void $table->id(); $table->unsignedBigInteger('evaluation_id'); $table->unsignedBigInteger('indicator_id'); - $table->float('md_value'); + $table->float('cf_e'); $table->timestamps(); }); diff --git a/resources/views/assessment/form.blade.php b/resources/views/assessment/form.blade.php index 9892c4c..6fc6fcd 100644 --- a/resources/views/assessment/form.blade.php +++ b/resources/views/assessment/form.blade.php @@ -52,15 +52,12 @@
- Pilih Jawaban + Pilih Jawaban {{ $indicator->name }}
@endforeach @@ -79,19 +76,25 @@
@if (session('presentase')) -

0% -

Presentase kelayakan tanah berdasarkan perhitungan Certainty Factor.

+

0% +

+ @endif + @if (session('hasil') && session('land')) +

Hasil perhitungan sistem menetapkan lahan + "{{ session('land') }}" + termasuk + dalam kondisi "{{ session('hasil') }}" +

@endif
- @@ -104,7 +107,6 @@ - @endpush @endsection