From 7ec1dcb5c152dc9d632c4b40a9ad2fbd0e6668d1 Mon Sep 17 00:00:00 2001 From: Zhaqian Rouf Alfauzi Date: Sun, 9 Feb 2025 03:56:09 +0700 Subject: [PATCH] [add] TestData Done --- app/Http/Controllers/AuthController.php | 2 +- app/Http/Controllers/SantriController.php | 2 +- app/Http/Controllers/TestDataController.php | 139 +++++++ app/Models/TestData.php | 27 ++ composer.json | 3 +- composer.lock | 55 ++- .../2014_10_12_000000_create_users_table.php | 2 +- ...25_02_08_192739_create_test_data_table.php | 29 ++ database/seeders/UserSeeder.php | 2 +- .../views/pages/admin/class-result.blade.php | 307 +++++++++++++++ .../views/pages/admin/dashboard.blade.php | 4 +- .../views/pages/admin/exam-data.blade.php | 371 ++++++++++++++++++ resources/views/pages/auth/register.blade.php | 4 +- resources/views/pages/santri/profil.blade.php | 8 +- .../views/partial/sidebar-admin.blade.php | 2 +- routes/web.php | 6 +- 16 files changed, 947 insertions(+), 16 deletions(-) create mode 100644 app/Http/Controllers/TestDataController.php create mode 100644 app/Models/TestData.php create mode 100644 database/migrations/2025_02_08_192739_create_test_data_table.php diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php index 19355e9..9853588 100644 --- a/app/Http/Controllers/AuthController.php +++ b/app/Http/Controllers/AuthController.php @@ -83,7 +83,7 @@ public function register(Request $request) 'email' => 'required|email|unique:users,email', 'password' => 'required|min:6', 'jenis_kelamin' => 'required|in:Laki-laki,Perempuan', - 'asal_daerah' => 'required|in:Jawa,luarJawa', + 'asal_daerah' => 'required|in:dalamProvinsi,luarProvinsi', ]); // Buat user baru dengan role "santri" diff --git a/app/Http/Controllers/SantriController.php b/app/Http/Controllers/SantriController.php index a97b095..fafb01c 100644 --- a/app/Http/Controllers/SantriController.php +++ b/app/Http/Controllers/SantriController.php @@ -59,7 +59,7 @@ public function updateProfile(Request $request) $request->validate([ 'name' => 'required|string|max:255', 'email' => 'required|email|unique:users,email,' . $user->id, - 'asal_daerah' => 'required|in:Jawa,luarJawa', + 'asal_daerah' => 'required|in:dalamProvinsi,luarProvinsi', 'password' => 'nullable|min:6|same:password_confirmation', ], [ 'password.same' => 'Konfirmasi password tidak cocok.', diff --git a/app/Http/Controllers/TestDataController.php b/app/Http/Controllers/TestDataController.php new file mode 100644 index 0000000..8ea8557 --- /dev/null +++ b/app/Http/Controllers/TestDataController.php @@ -0,0 +1,139 @@ +input('percentage', 100); + $totalTrainData = TrainData::count(); + $limit = round(($percentage / 100) * $totalTrainData); + + // **Hapus semua data di TestData secara aman** + TestData::query()->delete(); + + // **Ambil data latih sesuai persentase** + $trainData = TrainData::inRandomOrder()->limit($limit)->get(); + + // **Gunakan array untuk menyimpan NIS unik** + $existingNIS = []; + + foreach ($trainData as $data) { + if (!in_array($data->nis, $existingNIS)) { // Cek jika NIS belum ada + 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; // Tambahkan ke array + } + } + + // **Jalankan klasifikasi otomatis setelah data dipilih** + $this->classifyData(); + + // **Ambil kembali data uji** + $testData = TestData::all(); + $totalTestData = $testData->count(); + + // **Hitung akurasi berdasarkan prediksi** + $correctPredictions = TestData::whereColumn('status', 'predicted_status')->count(); + $accuracy = ($totalTestData > 0) ? ($correctPredictions / $totalTestData) * 100 : 0; + + // **Hitung probabilitas berdasarkan status prediksi** + $probStatus = [ + 'Tepat' => TestData::where('predicted_status', 'Tercapai')->count() * 100 / max(1, $totalTestData), + 'Terlambat' => TestData::where('predicted_status', 'Tidak Tercapai')->count() * 100 / max(1, $totalTestData), + ]; + + // **Hitung probabilitas berdasarkan jenis kelamin** + $probGender = TestData::groupBy('jenis_kelamin') + ->selectRaw("jenis_kelamin, COUNT(*) * 100 / $totalTestData as probability") + ->pluck('probability', 'jenis_kelamin') + ->toArray(); + + $probGender = [ + 'Laki-laki' => $probGender['Laki-laki'] ?? 0, + 'Perempuan' => $probGender['Perempuan'] ?? 0, + ]; + + // **Hitung probabilitas berdasarkan asal daerah** + $probRegion = TestData::groupBy('asal_daerah') + ->selectRaw("asal_daerah, COUNT(*) * 100 / $totalTestData as probability") + ->pluck('probability', 'asal_daerah') + ->toArray(); + + $probRegion = [ + 'Dalam Provinsi' => $probRegion['Dalam Provinsi'] ?? 0, + 'Luar Provinsi' => $probRegion['Luar Provinsi'] ?? 0, + ]; + + return view('pages.admin.exam-data', compact( + 'testData', + 'totalTestData', + 'accuracy', + 'probStatus', + 'probGender', + 'probRegion' + )); + } + + + + + + private function classifyData() + { + if (TestData::count() == 0) { + return; + } + + // Ambil data latih untuk model + $trainSamples = TrainData::all()->map(function ($item) { + return [$item->alquran, $item->alhadis]; // Fitur + })->toArray(); + + $trainLabels = TrainData::pluck('status')->values()->toArray(); + + // Ambil data uji + $testSamples = TestData::all()->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); + + // Simpan hasil prediksi + $testData = TestData::all(); + 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, + ]); + } +} diff --git a/app/Models/TestData.php b/app/Models/TestData.php new file mode 100644 index 0000000..41eab30 --- /dev/null +++ b/app/Models/TestData.php @@ -0,0 +1,27 @@ +string('password'); $table->enum('role', ['admin', 'santri'])->default('santri'); $table->enum('jenis_kelamin', ['Laki-laki', 'Perempuan'])->nullable(); - $table->enum('asal_daerah', ['Jawa', 'luarJawa'])->nullable(); + $table->enum('asal_daerah', ['dalamProvinsi', 'luarProvinsi'])->nullable(); $table->timestamps(); }); } diff --git a/database/migrations/2025_02_08_192739_create_test_data_table.php b/database/migrations/2025_02_08_192739_create_test_data_table.php new file mode 100644 index 0000000..7bdffa6 --- /dev/null +++ b/database/migrations/2025_02_08_192739_create_test_data_table.php @@ -0,0 +1,29 @@ +id(); + $table->string('nama'); + $table->string('jenis_kelamin'); + $table->string('nis')->unique(); + $table->string('asal_daerah'); + $table->string('tahun_angkatan'); + $table->integer('alquran'); + $table->integer('alhadis'); + $table->string('status'); + $table->string('predicted_status')->nullable(); + $table->timestamps(); + }); + } + + public function down() + { + Schema::dropIfExists('test_data'); + } +}; diff --git a/database/seeders/UserSeeder.php b/database/seeders/UserSeeder.php index 6ec0fd8..9468d61 100644 --- a/database/seeders/UserSeeder.php +++ b/database/seeders/UserSeeder.php @@ -27,7 +27,7 @@ public function run() 'password' => Hash::make('123456'), // password: 123456 'role' => 'santri', 'jenis_kelamin' => 'Laki-laki', - 'asal_daerah' => 'Jawa', + 'asal_daerah' => 'dalamProvinsi', ]); } } diff --git a/resources/views/pages/admin/class-result.blade.php b/resources/views/pages/admin/class-result.blade.php index e69de29..966b01d 100644 --- a/resources/views/pages/admin/class-result.blade.php +++ b/resources/views/pages/admin/class-result.blade.php @@ -0,0 +1,307 @@ +@extends('layouts.app-admin') +Data Uji | SR Klasifikasi + +@section('content') + +
+
+
+

Data Uji

+
+ + +
+
+
+
+
+
Jumlah Data
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+ +
+
+
+
+ +

94%

+
Akurasi Data
+

Total data yang di Uji: 31

+
+
+ +
+
+ +

32

+
Data yang di Uji
+

Diambil dari 10% data

+
+
+
+
+ +
+
+
+
+
+
Hasil Klasifikasi
+
+ +
+
+

Probabilitas Status

+
+
+ +
+ +
+
+
+
+ +
+
70%
+
Tepat
+
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
70%
+
Terlambat
+
+
+
+
+
+
+
+
+
+
+ +
+
+ +
+
+
+
Asal + Daerah +
+
+
+ + + + + + + + + + + + + + + + + + + + +
KategoriJumlahPeluang
Dalam Provinsixxxx
Luar Provinsixxxx
+
+
+
+ + +
+
+
+
Jenis + Kelamin +
+
+
+ + + + + + + + + + + + + + + + + + + + +
KategoriJumlahPeluang
Laki Lakixxxx
Perempuanxxxx
+
+
+
+
+
+
+
+
+
+
+
+ + + + + + + + +@endsection \ No newline at end of file diff --git a/resources/views/pages/admin/dashboard.blade.php b/resources/views/pages/admin/dashboard.blade.php index 6dfa85e..c6309f3 100644 --- a/resources/views/pages/admin/dashboard.blade.php +++ b/resources/views/pages/admin/dashboard.blade.php @@ -182,10 +182,10 @@ class="card-icon rounded-circle d-flex align-items-center justify-content-center { new ApexCharts(document.querySelector("#asalDaerah"), { series: [{ - name: 'Luar Jawa', + name: 'Dalam Provinsi', data: [21,22,23,24,25], }, { - name: 'Jawa', + name: 'Luar Provinsi', data: [11, 32, 45,32, 41] }], chart: { diff --git a/resources/views/pages/admin/exam-data.blade.php b/resources/views/pages/admin/exam-data.blade.php index e69de29..574a02c 100644 --- a/resources/views/pages/admin/exam-data.blade.php +++ b/resources/views/pages/admin/exam-data.blade.php @@ -0,0 +1,371 @@ +@extends('layouts.app-admin') +Data Uji | SR Klasifikasi + +@section('content') + + +
+
+
+

Data Uji

+
+ + + + +
+
+
+
Jumlah Data
+
+
+ +
+ +
+
+
+
+ + +
+
+
+
+ +

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

+
Akurasi Model
+

Total data diuji: {{ $totalTestData }}

+
+
+ +
+
+ +

{{ $totalTestData }}

+
Data yang di Uji
+

Diambil dari {{ request('percentage', 100) }}% data latih

+
+
+
+
+ +
+ +
+
+

Probabilitas Status

+
+
+ +
+ +
+
+
+
+ +
+
{{ number_format($probStatus['Tepat'] ?? 0, 2) }}%
+
Tepat
+
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
{{ number_format($probStatus['Terlambat'] ?? 0, 2) }}%
+
Terlambat
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+
+ +
+
+
+
Asal + Daerah +
+
+
+ + + + + + + + + + + + + + + + + + + + +
KategoriJumlah
Dalam Provinsi{{ number_format($probRegion['Dalam Provinsi'] ?? 0, 2) }}%
Luar Provinsi{{ number_format($probRegion['Luar Provinsi'] ?? 0, 2) }}%
+
+
+
+ +
+
+
+
Jenis + Kelamin +
+
+
+ + + + + + + + + + + + + + + + + + + + +
KategoriJumlah
Laki Laki{{ number_format($probGender['Laki-laki'] ?? 0, 2) }}%
Perempuan{{ number_format($probGender['Perempuan'] ?? 0, 2) }}%
+
+
+
+
+
+ + +
+
+
+
Hasil Klasifikasi
+
+ + + + + + + + + + + + + + + + @foreach ($testData as $item) + + + + + + + + + + + + @endforeach + +
NamaJenis KelaminNISAsal DaerahTahun AngkatanCapaian HadisCapaian Al Qur'anStatus AktualStatus Prediksi
{{ $item->nama }}{{ $item->jenis_kelamin }}{{ $item->nis }}{{ $item->asal_daerah }}{{ $item->tahun_angkatan }}{{ $item->alhadis }}{{ $item->alquran }}{{ $item->status }}{{ $item->predicted_status ?? 'Belum Diklasifikasi' }}
+
+
+
+
+
+
+ + + + + + + + + + +@endsection \ No newline at end of file diff --git a/resources/views/pages/auth/register.blade.php b/resources/views/pages/auth/register.blade.php index 0d42abe..9f969e6 100644 --- a/resources/views/pages/auth/register.blade.php +++ b/resources/views/pages/auth/register.blade.php @@ -77,8 +77,8 @@
Pilih Asal Daerah Anda
diff --git a/resources/views/pages/santri/profil.blade.php b/resources/views/pages/santri/profil.blade.php index cf4e703..40d4e98 100644 --- a/resources/views/pages/santri/profil.blade.php +++ b/resources/views/pages/santri/profil.blade.php @@ -64,9 +64,11 @@
diff --git a/resources/views/partial/sidebar-admin.blade.php b/resources/views/partial/sidebar-admin.blade.php index 47ea901..c2aef72 100644 --- a/resources/views/partial/sidebar-admin.blade.php +++ b/resources/views/partial/sidebar-admin.blade.php @@ -46,7 +46,7 @@