diff --git a/app/Http/Controllers/TestDataController.php b/app/Http/Controllers/TestDataController.php index 221e3cd..e430085 100644 --- a/app/Http/Controllers/TestDataController.php +++ b/app/Http/Controllers/TestDataController.php @@ -10,81 +10,68 @@ class TestDataController extends Controller { + + public function showTestData(Request $request) { $trainPercentage = $request->input('train_percentage', 80); // Default 80% $testPercentage = 100 - $trainPercentage; - $totalTrainData = TrainData::count(); + + $totalTrainData = TrainData::count(); // Total data latih $trainLimit = round(($trainPercentage / 100) * $totalTrainData); - $testLimit = round(($testPercentage / 100) * $totalTrainData); - // **Hapus semua data uji sebelum insert baru** - TestData::query()->delete(); - - // **Ambil data latih acak sesuai persentase** - $trainData = TrainData::inRandomOrder()->limit($trainLimit)->get(); - - // **Gunakan array untuk memastikan NIS unik** - $existingNIS = []; - - foreach ($trainData as $data) { - if (!in_array($data->nis, $existingNIS)) { - TestData::create([ - 'nama' => $data->nama, - 'jenis_kelamin' => $data->jenis_kelamin, - 'nis' => $data->nis, - 'asal_daerah' => $data->asal_daerah, - 'tahun_angkatan' => $data->tahun_angkatan, - 'alquran' => $data->alquran, - 'alhadis' => $data->alhadis, - 'status' => $data->status, - 'created_at' => now(), - 'updated_at' => now(), - ]); - $existingNIS[] = $data->nis; - } - } + $testLimit = round(($testPercentage / 100) * $totalTrainData); // Total data uji + + // $totalTrainData = TrainData::count(); + dump($totalTrainData); + // $trainLimit = round(($trainPercentage / 100) * $totalTrainData); + // $testLimit = round(($testPercentage / 100) * $totalTrainData); + dump($testLimit); + // Ambil data latih sesuai dengan persentase yang dikirim + $trainData = TrainData::inRandomOrder()->limit($trainLimit)->get(); // Ambil data latih sesuai persentase + dump($trainData); + // Ambil data uji sesuai dengan sisa data setelah pengambilan data latih + $testData = TestData::inRandomOrder()->limit($testLimit)->get(); // Ambil data uji sesuai limit + // **Jalankan klasifikasi otomatis** - // Ganti pemanggilan classifyData() seperti ini - $this->classifyData($request); - - - $testData = TestData::limit($testLimit)->get(); + $this->classifyData($trainData, $testData); $totalTestData = $testData->count(); + dump($totalTestData); + // Total Test Data + dd($testData); - - // **Hitung Akurasi** + // Akurasi dan Evaluasi $correctPredictions = $testData->filter(function ($item) { return $item->status === $item->predicted_status; })->count(); $accuracy = ($totalTestData > 0) ? ($correctPredictions / max(1, $totalTestData)) * 100 : 0; - // **Hitung True Positive, False Positive, dan False Negative** + // Hitung TP, FP, FN, Precision, Recall, dan Probabilitas $TP = $testData->filter(function ($item) { - return $item->status === 'Tercapai' && $item->predicted_status === 'Tercapai'; - })->count(); + return $item->status === 'Tercapai' && $item->predicted_status === 'Tercapai'; + })->count(); $FP = $testData->filter(function ($item) { - return $item->status === 'Tidak Tercapai' && $item->predicted_status === 'Tercapai'; - })->count(); + return $item->status === 'Tidak Tercapai' && $item->predicted_status === 'Tercapai'; + })->count(); $FN = $testData->filter(function ($item) { - return $item->status === 'Tercapai' && $item->predicted_status === 'Tidak Tercapai'; - })->count(); + return $item->status === 'Tercapai' && $item->predicted_status === 'Tidak Tercapai'; + })->count(); - // **Hitung Precision dan Recall** $precision = ($TP + $FP) > 0 ? ($TP / ($TP + $FP)) * 100 : 0; $recall = ($TP + $FN) > 0 ? ($TP / ($TP + $FN)) * 100 : 0; // **Hitung probabilitas status prediksi** $probStatus = [ - 'Tepat' => $testData->filter(function ($item) { - return $item->predicted_status === 'Tercapai'; - })->count() * 100 / max(1, $totalTestData), - 'Terlambat' => $testData->filter(function ($item) { - return $item->predicted_status === 'Tidak Tercapai'; - })->count() * 100 / max(1, $totalTestData), + 'Tepat' => $testData->where('predicted_status', 'Tercapai')->count() * 100 / max(1, $totalTestData), + 'Terlambat' => $testData->where('predicted_status', 'Tidak Tercapai')->count() * 100 / max(1, $totalTestData), + ]; + + $probRegion = [ + 'Dalam Provinsi' => $probRegion['Dalam Provinsi'] ?? 0, + 'Luar Provinsi' => $probRegion['Luar Provinsi'] ?? 0, ]; // **Probabilitas berdasarkan jenis kelamin** @@ -100,73 +87,7 @@ public function showTestData(Request $request) 'Perempuan' => $probGender['Perempuan'] ?? 0, ]; - - // Hitung total jumlah "Tercapai" dan "Tidak Tercapai" untuk masing-masing kategori - $totalTercapai = $testData->where('status', 'Tercapai')->count(); - $totalTidakTercapai = $testData->where('status', 'Tidak Tercapai')->count(); - - $probKelamin = [ - 'Tercapai' => [ - 'Laki-laki' => [ - 'probability' => $totalTercapai > 0 ? $testData->where('status', 'Tercapai')->where('jenis_kelamin', 'Laki-laki')->count() / $totalTercapai : 0, - 'count' => $testData->where('status', 'Tercapai')->where('jenis_kelamin', 'Laki-laki')->count(), - ], - 'Perempuan' => [ - 'probability' => $totalTercapai > 0 ? $testData->where('status', 'Tercapai')->where('jenis_kelamin', 'Perempuan')->count() / $totalTercapai : 0, - 'count' => $testData->where('status', 'Tercapai')->where('jenis_kelamin', 'Perempuan')->count(), - ], - ], - 'Tidak Tercapai' => [ - 'Laki-laki' => [ - 'probability' => $totalTidakTercapai > 0 ? $testData->where('status', 'Tidak Tercapai')->where('jenis_kelamin', 'Laki-laki')->count() / $totalTidakTercapai : 0, - 'count' => $testData->where('status', 'Tidak Tercapai')->where('jenis_kelamin', 'Laki-laki')->count(), - ], - 'Perempuan' => [ - 'probability' => $totalTidakTercapai > 0 ? $testData->where('status', 'Tidak Tercapai')->where('jenis_kelamin', 'Perempuan')->count() / $totalTidakTercapai : 0, - 'count' => $testData->where('status', 'Tidak Tercapai')->where('jenis_kelamin', 'Perempuan')->count(), - ], - ], - ]; - - - // **Probabilitas berdasarkan asal daerah** - $probRegion = $testData->groupBy('asal_daerah')->map(function ($group) use ($totalTestData) { - return [ - 'probability' => ($group->count() * 100) / max(1, $totalTestData), - 'count' => $group->count() - ]; - })->toArray(); - - - $probRegion = [ - 'Dalam Provinsi' => $probRegion['Dalam Provinsi'] ?? 0, - 'Luar Provinsi' => $probRegion['Luar Provinsi'] ?? 0, - ]; - - $probProvinsi = [ - 'Tercapai' => [ - 'Dalam Provinsi' => [ - 'probability' => $totalTercapai > 0 ? $testData->where('status', 'Tercapai')->where('asal_daerah', 'Dalam Provinsi')->count() / $totalTercapai : 0, - 'count' => $testData->where('status', 'Tercapai')->where('asal_daerah', 'Dalam Provinsi')->count(), - ], - 'Luar Provinsi' => [ - 'probability' => $totalTercapai > 0 ? $testData->where('status', 'Tercapai')->where('asal_daerah', 'Luar Provinsi')->count() / $totalTercapai : 0, - 'count' => $testData->where('status', 'Tercapai')->where('asal_daerah', 'Luar Provinsi')->count(), - ], - ], - 'Tidak Tercapai' => [ - 'Dalam Provinsi' => [ - 'probability' => $totalTidakTercapai > 0 ? $testData->where('status', 'Tidak Tercapai')->where('asal_daerah', 'Dalam Provinsi')->count() / $totalTidakTercapai : 0, - 'count' => $testData->where('status', 'Tidak Tercapai')->where('asal_daerah', 'Dalam Provinsi')->count(), - ], - 'Luar Provinsi' => [ - 'probability' => $totalTidakTercapai > 0 ? $testData->where('status', 'Tidak Tercapai')->where('asal_daerah', 'Luar Provinsi')->count() / $totalTidakTercapai : 0, - 'count' => $testData->where('status', 'Tidak Tercapai')->where('asal_daerah', 'Luar Provinsi')->count(), - ], - ], - ]; - - // **Hitung peluang tepat waktu berdasarkan jenis kelamin** + // **Hitung peluang tepat waktu berdasarkan jenis kelamin** $peluangGender = $testData->groupBy('jenis_kelamin')->map(function ($group) { $total = $group->count(); $tercapai = $group->filter(function ($item) { @@ -192,7 +113,7 @@ public function showTestData(Request $request) ]; })->toArray(); - $probNumerik = [ + $probNumerik = [ 'alquran' => [ 'Tercapai' => $this->calculateMeanStdDev('alquran', 'Tercapai', $testData), 'Tidak Tercapai' => $this->calculateMeanStdDev('alquran', 'Tidak Tercapai', $testData), @@ -207,9 +128,56 @@ public function showTestData(Request $request) ], ]; + $totalTercapai = $testData->where('status', 'Tercapai')->count(); + $totalTidakTercapai = $testData->where('status', 'Tidak Tercapai')->count(); + $probKelamin = [ + 'Tercapai' => [ + 'Laki-laki' => [ + 'probability' => $totalTercapai > 0 ? $testData->where('status', 'Tercapai')->where('jenis_kelamin', 'Laki-laki')->count() / $totalTercapai : 0, + 'count' => $testData->where('status', 'Tercapai')->where('jenis_kelamin', 'Laki-laki')->count(), + ], + 'Perempuan' => [ + 'probability' => $totalTercapai > 0 ? $testData->where('status', 'Tercapai')->where('jenis_kelamin', 'Perempuan')->count() / $totalTercapai : 0, + 'count' => $testData->where('status', 'Tercapai')->where('jenis_kelamin', 'Perempuan')->count(), + ], + ], + 'Tidak Tercapai' => [ + 'Laki-laki' => [ + 'probability' => $totalTidakTercapai > 0 ? $testData->where('status', 'Tidak Tercapai')->where('jenis_kelamin', 'Laki-laki')->count() / $totalTidakTercapai : 0, + 'count' => $testData->where('status', 'Tidak Tercapai')->where('jenis_kelamin', 'Laki-laki')->count(), + ], + 'Perempuan' => [ + 'probability' => $totalTidakTercapai > 0 ? $testData->where('status', 'Tidak Tercapai')->where('jenis_kelamin', 'Perempuan')->count() / $totalTidakTercapai : 0, + 'count' => $testData->where('status', 'Tidak Tercapai')->where('jenis_kelamin', 'Perempuan')->count(), + ], + ], + ]; + $probProvinsi = [ + 'Tercapai' => [ + 'Dalam Provinsi' => [ + 'probability' => $totalTercapai > 0 ? $testData->where('status', 'Tercapai')->where('asal_daerah', 'Dalam Provinsi')->count() / $totalTercapai : 0, + 'count' => $testData->where('status', 'Tercapai')->where('asal_daerah', 'Dalam Provinsi')->count(), + ], + 'Luar Provinsi' => [ + 'probability' => $totalTercapai > 0 ? $testData->where('status', 'Tercapai')->where('asal_daerah', 'Luar Provinsi')->count() / $totalTercapai : 0, + 'count' => $testData->where('status', 'Tercapai')->where('asal_daerah', 'Luar Provinsi')->count(), + ], + ], + 'Tidak Tercapai' => [ + 'Dalam Provinsi' => [ + 'probability' => $totalTidakTercapai > 0 ? $testData->where('status', 'Tidak Tercapai')->where('asal_daerah', 'Dalam Provinsi')->count() / $totalTidakTercapai : 0, + 'count' => $testData->where('status', 'Tidak Tercapai')->where('asal_daerah', 'Dalam Provinsi')->count(), + ], + 'Luar Provinsi' => [ + 'probability' => $totalTidakTercapai > 0 ? $testData->where('status', 'Tidak Tercapai')->where('asal_daerah', 'Luar Provinsi')->count() / $totalTidakTercapai : 0, + 'count' => $testData->where('status', 'Tidak Tercapai')->where('asal_daerah', 'Luar Provinsi')->count(), + ], + ], + ]; + return view('pages.admin.test-data', compact( 'testData', 'totalTestData', @@ -231,7 +199,9 @@ public function showTestData(Request $request) 'probProvinsi', 'testLimit', 'trainLimit', - + 'FP', + 'TP', + 'FN' )); } @@ -241,57 +211,43 @@ public function showClassify() return view('pages.admin.class-result', compact('classifiedData')); } - private function classifyData(Request $request) + + private function classifyData($trainData, $testData) { - $trainPercentage = $request->input('train_percentage', 80); // Default 80% - $testPercentage = 100 - $trainPercentage; - $totalTrainData = TrainData::count(); - $trainLimit = round(($trainPercentage / 100) * $totalTrainData); - $testLimit = round(($testPercentage / 100) * $totalTrainData); - - // Ambil data uji sesuai limit yang dihitung - $testData = TestData::limit($testLimit)->get(); - $totalTestData = $testData->count(); - - if ($totalTestData == 0) { - return; - } - - // Ambil data latih untuk model - $trainSamples = TrainData::limit($trainLimit)->get()->map(function ($item) { + // Ambil data latih dan pisahkan fitur dan label + $trainSamples = $trainData->map(function ($item) { return [$item->alquran, $item->alhadis]; // Fitur })->toArray(); - $trainLabels = TrainData::limit($trainLimit)->pluck('status')->values()->toArray(); + $trainLabels = $trainData->pluck('status')->values()->toArray(); // Label - // Ambil data uji + // Cek jika data latih kosong + if (empty($trainSamples) || empty($trainLabels)) { + session()->flash('error', 'Data Latih 0. Model tidak mempelajari pola apapun'); + return; + } + + // Ambil data uji dan pisahkan fitur $testSamples = $testData->map(function ($item) { return [$item->alquran, $item->alhadis]; // Fitur })->toArray(); - if (count($trainSamples) == 0 || count($testSamples) == 0) { - return; - } - // Jalankan Naive Bayes $classifier = new NaiveBayes(); - $classifier->train($trainSamples, $trainLabels); - $predictedLabels = $classifier->predict($testSamples); + $classifier->train($trainSamples, $trainLabels); // Latih model dengan data latih + $predictedLabels = $classifier->predict($testSamples); // Prediksi data uji - // Simpan hasil prediksi + // Simpan hasil prediksi ke dalam TestData foreach ($testData as $index => $data) { $data->predicted_status = $predictedLabels[$index] ?? 'Belum Diklasifikasi'; $data->save(); } - // ✅ Tambahkan debug log untuk memastikan prediksi disimpan - Log::info("DEBUG: Hasil Prediksi Naive Bayes", [ - "Total Test Data" => count($testSamples), - "Predicted Labels" => $predictedLabels, - ]); + Log::info("DEBUG: Predicted Labels", ["PredictedLabels" => $predictedLabels]); } + public function resetData() { TestData::query()->delete(); diff --git a/resources/views/pages/admin/test-data.blade.php b/resources/views/pages/admin/test-data.blade.php index 60bf81e..809f252 100644 --- a/resources/views/pages/admin/test-data.blade.php +++ b/resources/views/pages/admin/test-data.blade.php @@ -99,7 +99,16 @@ background-color: #fff; } - +@if($errors->any()) + +@endif
@@ -112,43 +121,123 @@ - -
-
-
-
- -
-
Data Latih
-

{{ $trainPercentage }}%

-
+
+
+
+
+ +

{{ $trainPercentage }}%

+
Data Latih
+ + +
+
+ +

{{ $testPercentage }}%

+
Data Uji
+
+
+
-
-
-
- -
-
Data Uji
-

{{ $testPercentage }}%

-
+
+
+
+
+
+

Jumlah Data

+
+
+
+
+ +

{{$totalTestData}}

+ +
Data yang di Uji
+

Diambil dari sejumlah {{ $totalTrainData }} dengan presentase {{ $testPercentage }}% data + latih

+
+
+
+
+
+
+
+

Confusion Matrix

+
+
+
+ +
+
+ +

{{ number_format($accuracy, 2) }}%

+
Akurasi Model
+
+
+ + +
+
+ +

{{ number_format($precision, 2) }}%

+
Precision
+
+
+ + +
+
+ +

{{ number_format($recall, 2) }}%

+
Recall
+
+
+
+ + +
+ +
+
+ +

{{ number_format($TP) }}

+
True Positive (TP)
+
+
+ + +
+
+ +

{{ number_format($FP) }}

+
False Positive (FP)
+
+
+ + +
+
+ +

{{ number_format($FN) }}

+
False Negative (FN)
- - -{{-- + + {{--
@@ -157,10 +246,14 @@
--}} - - -
-
-
-
-

Jumlah Data

-
-
-
-
- -

{{$totalTestData}}

- -
Data yang di Uji
-

Diambil dari sejumlah {{ $totalTrainData }} dengan presentase {{ $testPercentage }}% data latih

-
-
-
-
@@ -239,7 +312,8 @@
{{ number_format($probStatus['Terlambat'] ?? 0, 2) }}%
Terlambat
- Sejumlah {{ $totalTidakTercapai }} dari {{ $totalTestData }} data + Sejumlah {{ $totalTidakTercapai }} dari {{ $totalTestData }} + data
@@ -261,7 +335,7 @@

Probabilitas Atribut Numerik

- +
@@ -276,7 +350,8 @@

Tercapai

-

{{ number_format($probNumerik['alquran']['Tercapai']['mean'], 2) }}

+

{{ number_format($probNumerik['alquran']['Tercapai']['mean'], + 2) }}

Tidak Tercapai

@@ -288,7 +363,8 @@

Tercapai

-

{{ number_format($probNumerik['alquran']['Tercapai']['std_dev'], 2) }}

+

{{ + number_format($probNumerik['alquran']['Tercapai']['std_dev'], 2) }}

Tidak Tercapai

@@ -297,7 +373,7 @@
- +
@@ -311,7 +387,8 @@

Tercapai

-

{{ number_format($probNumerik['alhadis']['Tercapai']['mean'], 2) }}

+

{{ number_format($probNumerik['alhadis']['Tercapai']['mean'], + 2) }}

Tidak Tercapai

@@ -323,7 +400,8 @@

Tercapai

-

{{ number_format($probNumerik['alhadis']['Tercapai']['std_dev'], 2) }}

+

{{ + number_format($probNumerik['alhadis']['Tercapai']['std_dev'], 2) }}

Tidak Tercapai

@@ -332,7 +410,7 @@
- +
@@ -346,11 +424,13 @@

Tercapai

-

{{ number_format($probNumerik['tahun_angkatan']['Tercapai']['mean'], 2) }}

+

{{ + number_format($probNumerik['tahun_angkatan']['Tercapai']['mean'], 2) }}

Tidak Tercapai

-

{{ number_format($probNumerik['tahun_angkatan']['Tidak Tercapai']['mean'], 2) }}

+

{{ + number_format($probNumerik['tahun_angkatan']['Tidak Tercapai']['mean'], 2) }}


@@ -358,20 +438,22 @@

Tercapai

-

{{ number_format($probNumerik['tahun_angkatan']['Tercapai']['std_dev'], 2) }}

+

{{ + number_format($probNumerik['tahun_angkatan']['Tercapai']['std_dev'], 2) }}

Tidak Tercapai

-

{{ number_format($probNumerik['tahun_angkatan']['Tidak Tercapai']['std_dev'], 2) }}

+

{{ + number_format($probNumerik['tahun_angkatan']['Tidak Tercapai']['std_dev'], 2) }}

- - - + + +
@@ -384,9 +466,9 @@
Jenis - Kelamin -
+ class="bx bx-universal-access me-2"> Jenis + Kelamin +
@@ -400,28 +482,36 @@ class="bx bx-universal-access me-2"> Jenis - - - + + + - - + +
Tercapai{{ number_format($probKelamin['Tercapai']['Laki-laki']['probability'] * 100, 2) }}% ({{ $probKelamin['Tercapai']['Laki-laki']['count'] }}/{{ $totalTercapai }}){{ number_format($probKelamin['Tercapai']['Perempuan']['probability'] * 100, 2) }}% ({{ $probKelamin['Tercapai']['Perempuan']['count'] }}/{{ $totalTercapai }}){{ number_format($probKelamin['Tercapai']['Laki-laki']['probability'] * 100, + 2) }}% ({{ $probKelamin['Tercapai']['Laki-laki']['count'] }}/{{ + $totalTercapai }}){{ number_format($probKelamin['Tercapai']['Perempuan']['probability'] * 100, + 2) }}% ({{ $probKelamin['Tercapai']['Perempuan']['count'] }}/{{ + $totalTercapai }})
Tidak Tercapai{{ number_format($probKelamin['Tidak Tercapai']['Laki-laki']['probability'] * 100, 2) }}% ({{ $probKelamin['Tidak Tercapai']['Laki-laki']['count'] }}/{{ $totalTidakTercapai }}){{ number_format($probKelamin['Tidak Tercapai']['Perempuan']['probability'] * 100, 2) }}% ({{ $probKelamin['Tidak Tercapai']['Perempuan']['count'] }}/{{ $totalTidakTercapai }}){{ number_format($probKelamin['Tidak Tercapai']['Laki-laki']['probability'] + * 100, 2) }}% ({{ $probKelamin['Tidak Tercapai']['Laki-laki']['count'] }}/{{ + $totalTidakTercapai }}){{ number_format($probKelamin['Tidak Tercapai']['Perempuan']['probability'] + * 100, 2) }}% ({{ $probKelamin['Tidak Tercapai']['Perempuan']['count'] }}/{{ + $totalTidakTercapai }})
- +
Asal Daerah -
+ class="bx bx-buildings me-2"> Asal Daerah +
@@ -435,9 +525,13 @@ class="bx bx-buildings me-2"> Asal Daerah - - - + + + @@ -451,7 +545,7 @@ class="bx bx-buildings me-2"> Asal Daerah - +
@@ -479,13 +573,17 @@ class="bx bx-map-pin me-2"> Asal Daerah
- - + + - - + +
Tercapai{{ number_format($probProvinsi['Tercapai']['Dalam Provinsi']['probability'] * 100, 2) }}% ({{ $probProvinsi['Tercapai']['Dalam Provinsi']['count'] }}/{{ $totalTercapai }}){{ number_format($probProvinsi['Tercapai']['Luar Provinsi']['probability'] * 100, 2) }}% ({{ $probProvinsi['Tercapai']['Luar Provinsi']['count'] }}/{{ $totalTercapai }}){{ number_format($probProvinsi['Tercapai']['Dalam Provinsi']['probability'] + * 100, 2) }}% ({{ $probProvinsi['Tercapai']['Dalam Provinsi']['count'] }}/{{ + $totalTercapai }}){{ number_format($probProvinsi['Tercapai']['Luar Provinsi']['probability'] * + 100, 2) }}% ({{ $probProvinsi['Tercapai']['Luar Provinsi']['count'] }}/{{ + $totalTercapai }})
Tidak Tercapai
Dalam Provinsi{{ number_format($probRegion['Dalam Provinsi']['probability'] ?? 0, 2) }}%{{ number_format($peluangRegion['Dalam Provinsi']['peluang'] ?? 0, 2) }}%{{ number_format($probRegion['Dalam Provinsi']['probability'] ?? 0, 2) }}% + {{ number_format($peluangRegion['Dalam Provinsi']['peluang'] ?? 0, 2) }}% +
Luar Provinsi{{ number_format($probRegion['Luar Provinsi']['probability'] ?? 0, 2) }}%{{ number_format($peluangRegion['Luar Provinsi']['peluang'] ?? 0, 2) }}%{{ number_format($probRegion['Luar Provinsi']['probability'] ?? 0, 2) }}% + {{ number_format($peluangRegion['Luar Provinsi']['peluang'] ?? 0, 2) }}% +
@@ -546,8 +644,8 @@ class="bx bxs-user-badge me-2"> Jenis Export Excel
- -
+ +
@@ -593,47 +691,13 @@ class="bx bxs-user-badge me-2"> Jenis
- +
-
-
-
-

Conffusion Matrix

-
-
-
- -
-
- -

{{ number_format($accuracy, 2) }}%

-
Akurasi Model
-
-
- - -
-
- -

{{ number_format($precision, 2) }}%

-
Precision
-
-
- - -
-
- -

{{ number_format($recall, 2) }}%

-
Recall
-
-
-
-
- + +
@@ -648,7 +712,7 @@ class="bx bxs-user-badge me-2"> Jenis - +