Compare commits
10 Commits
ac235634ee
...
794e2af471
Author | SHA1 | Date |
---|---|---|
|
794e2af471 | |
|
33cff2186a | |
|
c3165955c1 | |
|
df989d1551 | |
|
7cfe92dcec | |
|
ae72f2717e | |
|
7b20b29157 | |
|
b309e56152 | |
|
5dd6f4a297 | |
|
967b012cf1 |
File diff suppressed because it is too large
Load Diff
|
@ -5,10 +5,11 @@
|
|||
use App\Models\Klaster;
|
||||
use App\Models\Curanmor;
|
||||
use App\Models\Kecamatan;
|
||||
use App\Models\Detail_Curanmor;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\Detail_Curanmor;
|
||||
use App\Services\KMeansService;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class CuranmorController extends Controller
|
||||
{
|
||||
|
@ -17,7 +18,7 @@ class CuranmorController extends Controller
|
|||
*/
|
||||
public function index()
|
||||
{
|
||||
$curanmors = Curanmor::orderBy('jumlah_curanmor', 'desc')->get();
|
||||
$curanmors = Curanmor::orderBy('id', 'asc')->get();
|
||||
return view('admin.dashboardListCuranmor', compact('curanmors'));
|
||||
|
||||
}
|
||||
|
@ -35,13 +36,14 @@ public function create()
|
|||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'kecamatan_id' => 'required|exists:kecamatans,id',
|
||||
'jumlah_curanmor' => 'required|numeric',
|
||||
]);
|
||||
try{
|
||||
|
||||
$request->validate([
|
||||
'kecamatan_id' => 'required|exists:kecamatans,id',
|
||||
'jumlah_curanmor' => 'required|numeric',
|
||||
]);
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
$kecamatan_id = $request->kecamatan_id;
|
||||
$tambahan_curanmor = $request->jumlah_curanmor;
|
||||
|
||||
|
@ -72,18 +74,14 @@ public function store(Request $request)
|
|||
$hasil = $service->hitungKMeansCuranmor();
|
||||
file_put_contents(storage_path('app/public/hasil_kmeans_curanmor.json'), json_encode($hasil));
|
||||
|
||||
// =====CODE TAMBAH SEBELUMNYA=========
|
||||
// $validateData = $request->validate([
|
||||
// 'kecamatan_id' =>'required|max:255|exists:kecamatans,id|unique:curanmors,kecamatan_id',
|
||||
// 'jumlah_curanmor' =>'required',
|
||||
// 'klaster_id' =>'required|max:255|exists:klasters,id',
|
||||
$serviceSSECuranmor = new KMeansService();
|
||||
$serviceSSECuranmor->SSEElbowCuranmor();
|
||||
|
||||
// ]);
|
||||
|
||||
// Curanmor::create($validateData);
|
||||
DB::commit();
|
||||
return redirect('/dashboard/curanmor')->with('succes', 'Berhasil Menambahkan Data Curanmor Baru');
|
||||
}catch (\Exception $e){
|
||||
return redirect('/dashboard/curanmor')->with('error', 'Gagal Menambahkan Data Curanmor Baru');
|
||||
DB::rollBack();
|
||||
return redirect('/dashboard/curanmor')->with('error', 'Gagal Menambahkan Data Curanmor Baru '. $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,18 +98,6 @@ public function show(Curanmor $curanmor)
|
|||
*/
|
||||
public function edit($curanmor)
|
||||
{
|
||||
try {
|
||||
|
||||
$edit = Curanmor::find($curanmor);
|
||||
|
||||
return view('admin.dashboardEditCuranmor', [
|
||||
'curanmor' => $edit,
|
||||
'kecamatans' => Kecamatan::all(),
|
||||
'klasters' => Klaster::all(),
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
abort(404);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -119,36 +105,7 @@ public function edit($curanmor)
|
|||
*/
|
||||
public function update(Request $request, Curanmor $curanmor)
|
||||
{
|
||||
try {
|
||||
|
||||
// Validasi input
|
||||
$request->validate([
|
||||
'kecamatan_id' => [
|
||||
'required',
|
||||
'exists:kecamatans,id',
|
||||
Rule::unique('curanmors')->ignore($curanmor->id),
|
||||
],
|
||||
'klaster_id' => 'required|exists:klasters,id',
|
||||
'jumlah_curanmor' => 'required|numeric|min:0',
|
||||
]);
|
||||
|
||||
// Update data
|
||||
$curanmor->update([
|
||||
'kecamatan_id' => $request->kecamatan_id,
|
||||
'klaster_id' => $request->klaster_id,
|
||||
'jumlah_curanmor' => $request->jumlah_curanmor,
|
||||
]);
|
||||
|
||||
$service = new KMeansService();
|
||||
$hasil = $service->hitungKMeansCuranmor();
|
||||
|
||||
// simpan hasil ke file json
|
||||
file_put_contents(storage_path('app/public/hasil_kmeans_curanmor.json'), json_encode($hasil));
|
||||
|
||||
return redirect('/dashboard/curanmor')->with('succes', 'Data Kecamatan Berhasil Diubah');
|
||||
} catch (\Exception $e) {
|
||||
return redirect('/dashboard/curanmor')->with('error', 'Data Kecamatan Gagal Diubah: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -156,22 +113,6 @@ public function update(Request $request, Curanmor $curanmor)
|
|||
*/
|
||||
public function destroy($curanmor)
|
||||
{
|
||||
try {
|
||||
// Cari data berdasarkan ID
|
||||
$hapus = Curanmor::find($curanmor);
|
||||
|
||||
// Pastikan data ditemukan sebelum menghapus
|
||||
if (!$hapus) {
|
||||
return redirect('/dashboard/curanmor')->with('error', 'Data tidak ditemukan.');
|
||||
}
|
||||
|
||||
// Hapus data
|
||||
$hapus->delete();
|
||||
|
||||
return redirect('/dashboard/curanmor')->with('succes', 'Data Curanmor Berhasil Dihapus');
|
||||
} catch (\Exception $e) {
|
||||
return redirect('/dashboard/curanmor')->with('error', 'Terjadi kesalahan: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
use Illuminate\Http\Request;
|
||||
use App\Services\KMeansService;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class CurasController extends Controller
|
||||
{
|
||||
|
@ -17,7 +18,7 @@ class CurasController extends Controller
|
|||
*/
|
||||
public function index()
|
||||
{
|
||||
$curases = Curas::orderBy('jumlah_curas', 'desc')->get();
|
||||
$curases = Curas::orderBy('id', 'asc')->get();
|
||||
return view('admin.dashboardListCuras', compact('curases'));
|
||||
|
||||
}
|
||||
|
@ -36,13 +37,14 @@ public function create()
|
|||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'kecamatan_id' => 'required|exists:kecamatans,id',
|
||||
'jumlah_curas' => 'required|numeric',
|
||||
]);
|
||||
try{
|
||||
|
||||
$request->validate([
|
||||
'kecamatan_id' => 'required|exists:kecamatans,id',
|
||||
'jumlah_curas' => 'required|numeric',
|
||||
]);
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
$kecamatan_id = $request->kecamatan_id;
|
||||
$tambahan_curas = $request->jumlah_curas;
|
||||
|
||||
|
@ -74,13 +76,19 @@ public function store(Request $request)
|
|||
|
||||
$service = new KMeansService();
|
||||
$hasil = $service->hitungKMeansCuras();
|
||||
|
||||
// simpan hasil ke file json
|
||||
|
||||
file_put_contents(storage_path('app/public/hasil_kmeans_curas.json'), json_encode($hasil));
|
||||
|
||||
|
||||
$serviceSSECuras = new KMeansService();
|
||||
$serviceSSECuras->SSEElbowCuras();
|
||||
|
||||
DB::commit();
|
||||
|
||||
return redirect('/dashboard/curas')->with('succes', 'Data curas berhasil ditambahkan.');
|
||||
}catch (\Exception $e){
|
||||
return redirect('/dashboard/curas')->with('error', 'Gagal Menambahkan Data Curas Baru');
|
||||
|
||||
DB::rollBack();
|
||||
return redirect('/dashboard/curas')->with('error', 'Gagal Menambahkan Data Curas Baru'. $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,18 +105,6 @@ public function show(Curas $curas)
|
|||
*/
|
||||
public function edit($curas)
|
||||
{
|
||||
try {
|
||||
|
||||
$edit = Curas::find($curas);
|
||||
|
||||
return view('admin.dashboardEditCuras', [
|
||||
'curas' => $edit,
|
||||
'kecamatans' => Kecamatan::all(),
|
||||
'klasters' => Klaster::all(),
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
abort(404);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -116,68 +112,13 @@ public function edit($curas)
|
|||
*/
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
try {
|
||||
// Cari data berdasarkan ID yang dikirim
|
||||
$curas = Curas::findOrFail($id);
|
||||
|
||||
// Debugging untuk memastikan data ditemukan
|
||||
// dd($curas->toArray()); // Jika berhasil, ini akan menampilkan data curas
|
||||
|
||||
// Validasi input
|
||||
$request->validate([
|
||||
'kecamatan_id' => [
|
||||
'required',
|
||||
'exists:kecamatans,id',
|
||||
Rule::unique('curas')->ignore($curas->id),
|
||||
],
|
||||
'klaster_id' => 'required|exists:klasters,id',
|
||||
'jumlah_curas' => 'required|integer|min:0',
|
||||
]);
|
||||
|
||||
// Update data
|
||||
$curas->update([
|
||||
'kecamatan_id' => $request->kecamatan_id,
|
||||
'klaster_id' => $request->klaster_id,
|
||||
'jumlah_curas' => $request->jumlah_curas,
|
||||
]);
|
||||
|
||||
$service = new KMeansService();
|
||||
$hasil = $service->hitungKMeansCuras();
|
||||
|
||||
// simpan hasil ke file json
|
||||
file_put_contents(storage_path('app/public/hasil_kmeans_curas.json'), json_encode($hasil));
|
||||
|
||||
return redirect('/dashboard/curas')->with('succes', 'Data Kecamatan Berhasil Diubah');
|
||||
} catch (\Exception $e) {
|
||||
return redirect('/dashboard/curas')->with('error', 'Data Kecamatan Gagal Diubah: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy($curas)
|
||||
{
|
||||
try {
|
||||
// Cari data berdasarkan ID
|
||||
$hapus = Curas::find($curas);
|
||||
|
||||
// Pastikan data ditemukan sebelum menghapus
|
||||
if (!$hapus) {
|
||||
return redirect('/dashboard/curas')->with('error', 'Data tidak ditemukan.');
|
||||
}
|
||||
|
||||
// Hapus data
|
||||
$hapus->delete();
|
||||
|
||||
return redirect('/dashboard/curas')->with('succes', 'Data Curas Berhasil Dihapus');
|
||||
} catch (\Exception $e) {
|
||||
return redirect('/dashboard/curas')->with('error', 'Terjadi kesalahan: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
use Illuminate\Http\Request;
|
||||
use App\Models\Detail_Curanmor;
|
||||
use App\Services\KMeansService;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class DetailCuranmorController extends Controller
|
||||
{
|
||||
|
@ -65,6 +66,8 @@ public function update(Request $request, Detail_Curanmor $detail_Curanmor)
|
|||
public function destroy($id)
|
||||
{
|
||||
try {
|
||||
|
||||
DB::beginTransaction();
|
||||
$detail = Detail_Curanmor::findOrFail($id);
|
||||
|
||||
$curanmor = Curanmor::findOrFail($detail->curanmor_id);
|
||||
|
@ -86,8 +89,15 @@ public function destroy($id)
|
|||
// simpan hasil ke file json
|
||||
file_put_contents(storage_path('app/public/hasil_kmeans_curanmor.json'), json_encode($hasil));
|
||||
|
||||
$serviceSSECuranmor = new KMeansService();
|
||||
$serviceSSECuranmor->SSEElbowCuranmor();
|
||||
|
||||
DB::commit();
|
||||
|
||||
return redirect('/dashboard/detail-curanmor')->with('succes', 'Data berhasil dihapus dan curanmor diperbarui.');
|
||||
} catch (\Exception $e) {
|
||||
|
||||
DB::rollback();
|
||||
return redirect('/dashboard/detail-curanmor')->with('error', 'Terjadi kesalahan Ketika Menghapus Data : ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
use App\Models\Detail_Curas;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Services\KMeansService;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class DetailCurasController extends Controller
|
||||
{
|
||||
|
@ -65,6 +66,9 @@ public function update(Request $request, Detail_Curas $detail_Curas)
|
|||
public function destroy($id)
|
||||
{
|
||||
try {
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
$detail = Detail_Curas::findOrFail($id);
|
||||
|
||||
// Ambil curas terkait
|
||||
|
@ -89,8 +93,15 @@ public function destroy($id)
|
|||
// simpan hasil ke file json
|
||||
file_put_contents(storage_path('app/public/hasil_kmeans_curas.json'), json_encode($hasil));
|
||||
|
||||
$serviceSSECuras = new KMeansService();
|
||||
$serviceSSECuras->SSEElbowCuras();
|
||||
|
||||
DB::commit();
|
||||
|
||||
return redirect('/dashboard/detail-curas')->with('succes', 'Data berhasil dihapus dan curas diperbarui.');
|
||||
} catch (\Exception $e) {
|
||||
|
||||
DB::rollBack();
|
||||
return redirect('/dashboard/detail-curas')->with('error', 'Terjadi kesalahan Ketika Menghapus Data : ' . $e->getMessage());
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
use App\Models\Kecamatan;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Services\KMeansService;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
|
||||
class KecamatanController extends Controller
|
||||
|
@ -30,14 +32,28 @@ public function create()
|
|||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$validateData = $request->validate([
|
||||
'nama_kecamatan' =>'required|max:255|unique:kecamatans,nama_kecamatan',
|
||||
]);
|
||||
|
||||
try{
|
||||
$validateData = $request->validate([
|
||||
'nama_kecamatan' =>'required|max:255|unique:kecamatans,nama_kecamatan',
|
||||
]);
|
||||
|
||||
DB::beginTransaction();
|
||||
Kecamatan::create($validateData);
|
||||
|
||||
$serviceKMeans = new KMeansService();
|
||||
$serviceKMeans->SSEElbowCuranmor();
|
||||
$serviceKMeans->SSEElbowCuras();
|
||||
|
||||
$hasilKMeansCuras = $serviceKMeans->hitungKMeansCuras();
|
||||
file_put_contents(storage_path('app/public/hasil_kmeans_curas.json'), json_encode($hasilKMeansCuras));
|
||||
|
||||
$hasilKMeansCuranmor = $serviceKMeans->hitungKMeansCuranmor();
|
||||
file_put_contents(storage_path('app/public/hasil_kmeans_curanmor.json'), json_encode($hasilKMeansCuranmor));
|
||||
|
||||
DB::commit();
|
||||
return redirect('/dashboard/kecamatan')->with('succes', 'Berhasil Menambahkan Data Kecamatan Baru');
|
||||
}catch (\Exception $e){
|
||||
DB::rollBack();
|
||||
return redirect('/dashboard/kecamatan')->with('error', 'Gagal Menambahkan Data Kecamatan Baru');
|
||||
}
|
||||
|
||||
|
@ -71,14 +87,28 @@ public function edit(Kecamatan $kecamatan)
|
|||
*/
|
||||
public function update(Request $request, Kecamatan $kecamatan)
|
||||
{
|
||||
$validateData = $request->validate([
|
||||
'nama_kecamatan' =>'required|max:255|unique:kecamatans,nama_kecamatan',
|
||||
]);
|
||||
|
||||
try{
|
||||
$validateData = $request->validate([
|
||||
'nama_kecamatan' =>'required|max:255|unique:kecamatans,nama_kecamatan',
|
||||
]);
|
||||
|
||||
DB::beginTransaction();
|
||||
Kecamatan::where('id', $kecamatan->id)->update($validateData);
|
||||
|
||||
$serviceKMeans = new KMeansService();
|
||||
$serviceKMeans->SSEElbowCuranmor();
|
||||
$serviceKMeans->SSEElbowCuras();
|
||||
|
||||
$hasilKMeansCuras = $serviceKMeans->hitungKMeansCuras();
|
||||
file_put_contents(storage_path('app/public/hasil_kmeans_curas.json'), json_encode($hasilKMeansCuras));
|
||||
|
||||
$hasilKMeansCuranmor = $serviceKMeans->hitungKMeansCuranmor();
|
||||
file_put_contents(storage_path('app/public/hasil_kmeans_curanmor.json'), json_encode($hasilKMeansCuranmor));
|
||||
|
||||
DB::commit();
|
||||
return redirect('/dashboard/kecamatan')->with('succes', 'Data Kecamatan Berhasil Di Ubah');
|
||||
}catch (\Exception $e){
|
||||
DB::rollBack();
|
||||
return redirect('/dashboard/kecamatan')->with('error', 'Data Kecamatan Gagal Di Ubah');
|
||||
}
|
||||
|
||||
|
@ -91,10 +121,24 @@ public function update(Request $request, Kecamatan $kecamatan)
|
|||
public function destroy(Kecamatan $kecamatan)
|
||||
{
|
||||
try{
|
||||
DB::beginTransaction();
|
||||
Kecamatan::destroy($kecamatan->id);
|
||||
|
||||
$serviceKMeans = new KMeansService();
|
||||
$serviceKMeans->SSEElbowCuranmor();
|
||||
$serviceKMeans->SSEElbowCuras();
|
||||
|
||||
$hasilKMeansCuras = $serviceKMeans->hitungKMeansCuras();
|
||||
file_put_contents(storage_path('app/public/hasil_kmeans_curas.json'), json_encode($hasilKMeansCuras));
|
||||
|
||||
$hasilKMeansCuranmor = $serviceKMeans->hitungKMeansCuranmor();
|
||||
file_put_contents(storage_path('app/public/hasil_kmeans_curanmor.json'), json_encode($hasilKMeansCuranmor));
|
||||
|
||||
DB::commit();
|
||||
return redirect('/dashboard/kecamatan')->with('succes', 'Data Kecamatan Berhasil Di Hapus');
|
||||
|
||||
}catch (\Exception $e){
|
||||
DB::rollBack();
|
||||
return redirect('/dashboard/kecamatan')->with('error', 'Data Kecamatan '. $kecamatan->nama_kecamatan .' Gagal Di Hapus | Hapus Data Curas Atau Curanmor Untuk Kecamatan '. $kecamatan->nama_kecamatan.' Terlebih Dahulu');
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
use App\Models\Klaster;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Services\KMeansService;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class KlasterController extends Controller
|
||||
{
|
||||
|
@ -28,18 +30,36 @@ public function create()
|
|||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$validateData = $request->validate([
|
||||
'nama_klaster' =>'required|max:255|unique:klasters,nama_klaster',
|
||||
'warna' =>'required|max:255',
|
||||
]);
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
try{
|
||||
$validateData = $request->validate([
|
||||
'nama_klaster' =>'required|max:255|unique:klasters,nama_klaster',
|
||||
'warna' =>'required|max:255',
|
||||
]);
|
||||
|
||||
|
||||
Klaster::create($validateData);
|
||||
|
||||
|
||||
$serviceKMeans = new KMeansService();
|
||||
$serviceKMeans->SSEElbowCuranmor();
|
||||
$serviceKMeans->SSEElbowCuras();
|
||||
|
||||
$hasilKMeansCuras = $serviceKMeans->hitungKMeansCuras();
|
||||
file_put_contents(storage_path('app/public/hasil_kmeans_curas.json'), json_encode($hasilKMeansCuras));
|
||||
|
||||
$hasilKMeansCuranmor = $serviceKMeans->hitungKMeansCuranmor();
|
||||
file_put_contents(storage_path('app/public/hasil_kmeans_curanmor.json'), json_encode($hasilKMeansCuranmor));
|
||||
|
||||
DB::commit();
|
||||
|
||||
return redirect('/dashboard/klaster')->with('succes', 'Berhasil Menambahkan Klaster Baru');
|
||||
}catch (\Exception $e){
|
||||
|
||||
return redirect('/dashboard/klaster')->with('error', 'Gagal Menambahkan Klaster Baru');
|
||||
DB::rollBack();
|
||||
|
||||
return redirect('/dashboard/klaster')->with('error', 'Gagal Menambahkan Klaster Baru ' .$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,17 +91,32 @@ public function edit(Klaster $klaster)
|
|||
*/
|
||||
public function update(Request $request, Klaster $klaster)
|
||||
{
|
||||
$validateData = $request->validate([
|
||||
'nama_klaster' => 'sometimes|required|max:255|unique:klasters,nama_klaster,' . $klaster->id,
|
||||
'warna' => 'sometimes|required|max:255',
|
||||
]);
|
||||
|
||||
try {
|
||||
$validateData = $request->validate([
|
||||
'nama_klaster' => 'sometimes|required|max:255|unique:klasters,nama_klaster,' . $klaster->id,
|
||||
'warna' => 'sometimes|required|max:255',
|
||||
]);
|
||||
|
||||
DB::beginTransaction();
|
||||
// Hanya update data yang diisi (tidak mengganti dengan null)
|
||||
Klaster::where('id', $klaster->id)->update(array_filter($validateData));
|
||||
|
||||
|
||||
$serviceKMeans = new KMeansService();
|
||||
$serviceKMeans->SSEElbowCuranmor();
|
||||
$serviceKMeans->SSEElbowCuras();
|
||||
|
||||
$hasilKMeansCuras = $serviceKMeans->hitungKMeansCuras();
|
||||
file_put_contents(storage_path('app/public/hasil_kmeans_curas.json'), json_encode($hasilKMeansCuras));
|
||||
|
||||
$hasilKMeansCuranmor = $serviceKMeans->hitungKMeansCuranmor();
|
||||
file_put_contents(storage_path('app/public/hasil_kmeans_curanmor.json'), json_encode($hasilKMeansCuranmor));
|
||||
|
||||
DB::commit();
|
||||
|
||||
return redirect('/dashboard/klaster')->with('success', 'Data Klaster Berhasil Diubah');
|
||||
} catch (\Exception $e) {
|
||||
|
||||
DB::rollBack();
|
||||
return redirect('/dashboard/klaster')->with('error', 'Data Klaster Gagal Diubah');
|
||||
}
|
||||
|
||||
|
@ -93,11 +128,27 @@ public function update(Request $request, Klaster $klaster)
|
|||
public function destroy(Klaster $klaster)
|
||||
{
|
||||
try{
|
||||
|
||||
DB::beginTransaction();
|
||||
Klaster::destroy($klaster->id);
|
||||
DB::commit();
|
||||
|
||||
$serviceKMeans = new KMeansService();
|
||||
$serviceKMeans->SSEElbowCuranmor();
|
||||
$serviceKMeans->SSEElbowCuras();
|
||||
|
||||
$hasilKMeansCuras = $serviceKMeans->hitungKMeansCuras();
|
||||
file_put_contents(storage_path('app/public/hasil_kmeans_curas.json'), json_encode($hasilKMeansCuras));
|
||||
|
||||
$hasilKMeansCuranmor = $serviceKMeans->hitungKMeansCuranmor();
|
||||
file_put_contents(storage_path('app/public/hasil_kmeans_curanmor.json'), json_encode($hasilKMeansCuranmor));
|
||||
|
||||
return redirect('/dashboard/klaster')->with('succes', 'Data Klaster Berhasil Di Hapus');
|
||||
|
||||
}catch (\Exception $e){
|
||||
return redirect('/dashboard/klaster')->with('error', 'Data Klaster '. $klaster->nama_kecamatan .' Gagal Di Hapus | Hapus Data Curas Atau Curanmor Untuk Klaster '. $klaster->nama_kecamatan.' Terlebih Dahulu');
|
||||
|
||||
DB::rollBack();
|
||||
return redirect('/dashboard/klaster')->with('error', 'Data Klaster '. $klaster->nama_kecamatan .' Gagal Di Hapus | Hapus Data Curas Atau Curanmor Untuk Klaster '. $klaster->nama_kecamatan.' Terlebih Dahulu '. $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,116 +9,35 @@
|
|||
|
||||
class KmeansController extends Controller
|
||||
{
|
||||
|
||||
public function KMeansCuras()
|
||||
{
|
||||
{
|
||||
$data = Curas::select('id', 'kecamatan_id', 'klaster_id', 'jumlah_curas')
|
||||
->orderBy('jumlah_curas', 'asc')->get();
|
||||
|
||||
$data = Curas::select('id', 'kecamatan_id', 'klaster_id', 'jumlah_curas')->orderBy('jumlah_curas', 'asc')->get();
|
||||
// Hitung min dan max untuk normalisasi
|
||||
$min = $data->min('jumlah_curas');
|
||||
$max = $data->max('jumlah_curas');
|
||||
|
||||
$k = Klaster::count('id');
|
||||
$maxIterasi = 100;
|
||||
|
||||
// Simpan centroid awal ke variabel terpisah
|
||||
$uniqueJumlahCuras = $data->pluck('jumlah_curas')->unique()->shuffle()->take($k)->values();
|
||||
|
||||
$initialCentroids = $uniqueJumlahCuras->map(function ($jumlah) {
|
||||
return ['jumlah_curas' => $jumlah];
|
||||
});
|
||||
|
||||
|
||||
// Salin untuk digunakan dalam proses iterasi
|
||||
$centroids = $initialCentroids->map(function ($item) {
|
||||
return $item;
|
||||
});
|
||||
|
||||
$iterasi = [];
|
||||
$prevAssignment = [];
|
||||
|
||||
for ($i = 0; $i < $maxIterasi; $i++) {
|
||||
$clustered = [];
|
||||
$currentAssignment = [];
|
||||
|
||||
foreach ($data as $item) {
|
||||
$jarak = [];
|
||||
|
||||
foreach ($centroids as $idx => $centroid) {
|
||||
$dist = abs($item->jumlah_curas - $centroid['jumlah_curas']);
|
||||
$jarak["jarakC" . ($idx + 1)] = $dist;
|
||||
}
|
||||
|
||||
$iterasi[$i][] = array_merge(['kecamatan_id' => $item->kecamatan_id], $jarak);
|
||||
|
||||
$minIndex = array_keys($jarak, min($jarak))[0]; // e.g. "jarakC2"
|
||||
$clusterNumber = (int) str_replace("jarakC", "", $minIndex);
|
||||
|
||||
$clustered[$clusterNumber][] = $item;
|
||||
$item->temp_klaster = $clusterNumber;
|
||||
$currentAssignment[$item->id] = $clusterNumber;
|
||||
}
|
||||
|
||||
if ($currentAssignment === $prevAssignment) {
|
||||
break;
|
||||
}
|
||||
|
||||
$prevAssignment = $currentAssignment;
|
||||
|
||||
// Update centroid berdasarkan rata-rata
|
||||
foreach ($clustered as $key => $group) {
|
||||
$avg = collect($group)->avg('jumlah_curas');
|
||||
$centroids = $centroids->map(function ($item, $index) use ($key, $avg) {
|
||||
return $index === ($key - 1)
|
||||
? ['jumlah_curas' => $avg]
|
||||
: $item;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Final mapping centroid ke klaster_id
|
||||
$finalCentroids = $centroids->map(function ($item, $index) {
|
||||
return ['index' => $index + 1, 'jumlah_curas' => $item['jumlah_curas']];
|
||||
})->sortBy('jumlah_curas')->values();
|
||||
|
||||
$centroidToKlaster = [];
|
||||
foreach ($finalCentroids as $i => $centroid) {
|
||||
$centroidToKlaster[$centroid['index']] = $i + 1;
|
||||
}
|
||||
|
||||
foreach ($data as $item) {
|
||||
Curas::where('id', $item->id)->update([
|
||||
'klaster_id' => $centroidToKlaster[$item->temp_klaster],
|
||||
]);
|
||||
}
|
||||
|
||||
// Simpan hasil iterasi dan centroid awal ke session
|
||||
session([
|
||||
'hasil_iterasi' => $iterasi,
|
||||
'centroid_awal' => $initialCentroids
|
||||
]);
|
||||
|
||||
// Format ulang centroid awal dengan label 'Centroid 1', dst.
|
||||
$formattedInitialCentroids = [];
|
||||
foreach ($initialCentroids as $i => $centroid) {
|
||||
$formattedInitialCentroids['Centroid ' . ($i + 1)] = $centroid['jumlah_curas'];
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'centroid_awal' => $formattedInitialCentroids,
|
||||
'hasil_iterasi' => $iterasi,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
public function KMeansCuranmor()
|
||||
{
|
||||
$data = Curanmor::select('id', 'kecamatan_id', 'klaster_id', 'jumlah_curanmor')->orderBy('jumlah_curanmor', 'asc')->get();
|
||||
$maxIterasi = 100;
|
||||
$hasilElbow = [];
|
||||
|
||||
for ($k = 1; $k <= 10; $k++) {
|
||||
// Ambil centroid awal secara acak
|
||||
$centroids = $data->random($k)->values()->map(function ($item) {
|
||||
return ['jumlah_curanmor' => $item->jumlah_curanmor];
|
||||
// Normalisasi jumlah_curas ke skala 0–1
|
||||
$data = $data->map(function ($item) use ($min, $max) {
|
||||
$item->jumlah_curas_normalized = $max == $min
|
||||
? 1
|
||||
: round(($item->jumlah_curas - $min) / ($max - $min), 2);
|
||||
return $item;
|
||||
});
|
||||
|
||||
$maxIterasi = 100;
|
||||
|
||||
// Centroid awal langsung dalam skala 0–1
|
||||
$centroidManual = [0.0, 0.5, 1];
|
||||
$centroids = collect($centroidManual)->map(function ($value) {
|
||||
return ['C' => round($value, 2)];
|
||||
});
|
||||
|
||||
$centroidAwal = $centroids->toArray();
|
||||
|
||||
$iterasi = [];
|
||||
$prevAssignment = [];
|
||||
|
||||
for ($i = 0; $i < $maxIterasi; $i++) {
|
||||
|
@ -129,106 +48,200 @@ public function KMeansCuranmor()
|
|||
$jarak = [];
|
||||
|
||||
foreach ($centroids as $idx => $centroid) {
|
||||
$dist = abs($item->jumlah_curanmor - $centroid['jumlah_curanmor']);
|
||||
$jarak[$idx] = $dist;
|
||||
$dist = abs($item->jumlah_curas_normalized - $centroid['C']);
|
||||
$jarak["C" . ($idx + 1)] = round($dist, 2);
|
||||
}
|
||||
|
||||
$iterasi[$i][] = array_merge([
|
||||
'kecamatan_id' => $item->kecamatan_id,
|
||||
'normal' => round($item->jumlah_curas_normalized, 2)
|
||||
], $jarak);
|
||||
|
||||
$minIndex = array_keys($jarak, min($jarak))[0];
|
||||
$clustered[$minIndex][] = $item;
|
||||
$currentAssignment[$item->id] = $minIndex;
|
||||
$item->temp_klaster = $minIndex;
|
||||
$clusterNumber = (int) str_replace("C", "", $minIndex);
|
||||
|
||||
$clustered[$clusterNumber][] = $item;
|
||||
$item->temp_klaster = $clusterNumber;
|
||||
$currentAssignment[$item->id] = $clusterNumber;
|
||||
}
|
||||
|
||||
if ($currentAssignment === $prevAssignment) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ($currentAssignment === $prevAssignment) break;
|
||||
$prevAssignment = $currentAssignment;
|
||||
|
||||
// Update centroid dengan rata-rata nilai normalized
|
||||
foreach ($clustered as $key => $group) {
|
||||
$avg = collect($group)->avg('jumlah_curanmor');
|
||||
$centroids[$key] = ['jumlah_curanmor' => $avg];
|
||||
$avg = collect($group)->avg('jumlah_curas_normalized');
|
||||
$centroids = $centroids->map(function ($item, $index) use ($key, $avg) {
|
||||
return $index === ($key - 1)
|
||||
? ['C' => round($avg, 2)]
|
||||
: $item;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Hitung SSE (Sum of Squared Errors)
|
||||
$sse = 0;
|
||||
foreach ($data as $item) {
|
||||
$centroidVal = $centroids[$item->temp_klaster]['jumlah_curanmor'];
|
||||
$sse += pow($item->jumlah_curanmor - $centroidVal, 2);
|
||||
// Mapping centroid ke klaster_id
|
||||
$finalCentroids = $centroids->map(function ($item, $index) {
|
||||
return ['index' => $index + 1, 'C' => round($item['C'], 2)];
|
||||
})->sortBy('C')->values();
|
||||
|
||||
$availableKlasterIDs = Klaster::orderBy('id', 'asc')->pluck('id')->values();
|
||||
|
||||
foreach ($finalCentroids as $i => $centroid) {
|
||||
$centroidToKlaster[$centroid['index']] = $availableKlasterIDs[$i];
|
||||
}
|
||||
|
||||
$hasilElbow[] = ['k' => $k, 'sse' => $sse];
|
||||
foreach ($data as $item) {
|
||||
Curas::where('id', $item->id)->update([
|
||||
'klaster_id' => $centroidToKlaster[$item->temp_klaster],
|
||||
]);
|
||||
}
|
||||
|
||||
$centroidAwalFormatted = collect($centroidAwal)->values()->map(function ($item, $index) {
|
||||
return ['C' . ($index + 1) => round($item['C'], 2)];
|
||||
});
|
||||
|
||||
$centroidAkhirFormatted = $centroids->values()->map(function ($item, $index) {
|
||||
return ['C' . ($index + 1) => round($item['C'], 2)];
|
||||
});
|
||||
|
||||
$hasilKMeansCuras = [
|
||||
'centroid_awal' => $centroidAwalFormatted,
|
||||
'centroid_akhir' => $centroidAkhirFormatted,
|
||||
'iterasi' => $iterasi,
|
||||
'min' => $min,
|
||||
'max' => $max
|
||||
];
|
||||
|
||||
file_put_contents(
|
||||
storage_path('app/public/hasil_kmeans_curas.json'),
|
||||
json_encode($hasilKMeansCuras, JSON_PRETTY_PRINT)
|
||||
);
|
||||
|
||||
return redirect('/dashboard/TampilHitungCuras');
|
||||
}
|
||||
|
||||
// Simpan hasil Elbow Method ke file
|
||||
file_put_contents(storage_path('app/public/hasil_elbow_curanmor.json'), json_encode($hasilElbow, JSON_PRETTY_PRINT));
|
||||
public function KMeansCuranmor()
|
||||
{
|
||||
// Ambil data awal
|
||||
$data = Curanmor::select('id', 'kecamatan_id', 'klaster_id', 'jumlah_curanmor')
|
||||
->orderBy('jumlah_curanmor', 'asc')->get();
|
||||
|
||||
// ===================== //
|
||||
// === Hitung k akhir === //
|
||||
// ===================== //
|
||||
// Hitung min dan max untuk normalisasi Min-Max
|
||||
$min = $data->min('jumlah_curanmor');
|
||||
$max = $data->max('jumlah_curanmor');
|
||||
|
||||
$k = Klaster::count(); // misalnya 3
|
||||
$centroids = $data->random($k)->values()->map(function ($item) {
|
||||
return ['jumlah_curanmor' => $item->jumlah_curanmor];
|
||||
});
|
||||
// Normalisasi jumlah_curanmor ke skala 1-100
|
||||
$data = $data->map(function ($item) use ($min, $max) {
|
||||
$item->jumlah_curanmor_normalized = $max == $min
|
||||
? 1
|
||||
: round((($item->jumlah_curanmor - $min) / ($max - $min)), 2);
|
||||
return $item;
|
||||
});
|
||||
|
||||
$iterasi = [];
|
||||
$prevAssignment = [];
|
||||
$maxIterasi = 100;
|
||||
|
||||
for ($i = 0; $i < $maxIterasi; $i++) {
|
||||
$clustered = [];
|
||||
$currentAssignment = [];
|
||||
// Centroid awal dalam skala 1–100
|
||||
$centroidManual = [0.2, 0.5, 0.8];
|
||||
$centroids = collect($centroidManual)->map(function ($value) {
|
||||
return ['C' => round($value, 2)];
|
||||
});
|
||||
|
||||
foreach ($data as $item) {
|
||||
$jarak = [];
|
||||
$centroidAwal = $centroids->toArray();
|
||||
|
||||
foreach ($centroids as $idx => $centroid) {
|
||||
$dist = abs($item->jumlah_curanmor - $centroid['jumlah_curanmor']);
|
||||
$jarak["jarakC" . ($idx + 1)] = $dist;
|
||||
$iterasi = [];
|
||||
$prevAssignment = [];
|
||||
|
||||
for ($i = 0; $i < $maxIterasi; $i++) {
|
||||
$clustered = [];
|
||||
$currentAssignment = [];
|
||||
|
||||
foreach ($data as $item) {
|
||||
$jarak = [];
|
||||
|
||||
foreach ($centroids as $idx => $centroid) {
|
||||
$dist = abs($item->jumlah_curanmor_normalized - $centroid['C']);
|
||||
$jarak["C" . ($idx + 1)] = round($dist, 2); // Dua angka di belakang koma
|
||||
}
|
||||
|
||||
$iterasi[$i][] = array_merge([
|
||||
'kecamatan_id' => $item->kecamatan_id,
|
||||
'normal' => round($item->jumlah_curanmor_normalized, 2)
|
||||
], $jarak);
|
||||
|
||||
$minIndex = array_keys($jarak, min($jarak))[0];
|
||||
$clusterNumber = (int) str_replace("C", "", $minIndex);
|
||||
|
||||
$clustered[$clusterNumber][] = $item;
|
||||
$item->temp_klaster = $clusterNumber;
|
||||
$currentAssignment[$item->id] = $clusterNumber;
|
||||
}
|
||||
|
||||
$iterasi[$i][] = array_merge(['kecamatan_id' => $item->kecamatan_id], $jarak);
|
||||
// Cek konvergensi
|
||||
if ($currentAssignment === $prevAssignment) {
|
||||
break;
|
||||
}
|
||||
|
||||
$minIndex = array_keys($jarak, min($jarak))[0];
|
||||
$clusterNumber = (int) str_replace("jarakC", "", $minIndex);
|
||||
$prevAssignment = $currentAssignment;
|
||||
|
||||
$clustered[$clusterNumber][] = $item;
|
||||
$item->temp_klaster = $clusterNumber;
|
||||
$currentAssignment[$item->id] = $clusterNumber;
|
||||
// Update centroid berdasarkan rata-rata nilai yang sudah dinormalisasi
|
||||
foreach ($clustered as $key => $group) {
|
||||
$avg = collect($group)->avg('jumlah_curanmor_normalized');
|
||||
$centroids = $centroids->map(function ($item, $index) use ($key, $avg) {
|
||||
return $index === ($key - 1)
|
||||
? ['C' => round($avg, 2)]
|
||||
: $item;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if ($currentAssignment === $prevAssignment) {
|
||||
break;
|
||||
// Final mapping centroid ke klaster_id
|
||||
$finalCentroids = $centroids->map(function ($item, $index) {
|
||||
return ['index' => $index + 1, 'C' => round($item['C'], 2)];
|
||||
})->sortBy('C')->values();
|
||||
|
||||
$availableKlasterIDs = Klaster::orderBy('id', 'asc')->pluck('id')->values();
|
||||
|
||||
foreach ($finalCentroids as $i => $centroid) {
|
||||
$centroidToKlaster[$centroid['index']] = $availableKlasterIDs[$i];
|
||||
}
|
||||
|
||||
$prevAssignment = $currentAssignment;
|
||||
|
||||
foreach ($clustered as $key => $group) {
|
||||
$avg = collect($group)->avg('jumlah_curanmor');
|
||||
$centroids = $centroids->map(function ($item, $index) use ($key, $avg) {
|
||||
return $index === ($key - 1)
|
||||
? ['jumlah_curanmor' => $avg]
|
||||
: $item;
|
||||
});
|
||||
// Update hasil clustering ke database
|
||||
foreach ($data as $item) {
|
||||
Curanmor::where('id', $item->id)->update([
|
||||
'klaster_id' => $centroidToKlaster[$item->temp_klaster],
|
||||
]);
|
||||
}
|
||||
|
||||
// Format centroid awal
|
||||
$centroidAwalFormatted = collect($centroidAwal)->values()->map(function ($item, $index) {
|
||||
return ['C' . ($index + 1) => round($item['C'], 2)];
|
||||
});
|
||||
|
||||
// Format centroid akhir
|
||||
$centroidAkhirFormatted = $centroids->values()->map(function ($item, $index) {
|
||||
return ['C' . ($index + 1) => round($item['C'], 2)];
|
||||
});
|
||||
|
||||
$hasilKMeansCuranmor = [
|
||||
'centroid_awal' => $centroidAwalFormatted,
|
||||
'centroid_akhir' => $centroidAkhirFormatted,
|
||||
'iterasi' => $iterasi,
|
||||
'min' => $min,
|
||||
'max' => $max
|
||||
];
|
||||
|
||||
file_put_contents(
|
||||
storage_path('app/public/hasil_kmeans_curanmor.json'),
|
||||
json_encode($hasilKMeansCuranmor, JSON_PRETTY_PRINT)
|
||||
);
|
||||
|
||||
return redirect('/dashboard/TampilHitungCuranmor');
|
||||
}
|
||||
|
||||
$finalCentroids = $centroids->map(function ($item, $index) {
|
||||
return ['index' => $index + 1, 'jumlah_curanmor' => $item['jumlah_curanmor']];
|
||||
})->sortBy('jumlah_curanmor')->values();
|
||||
|
||||
$centroidToKlaster = [];
|
||||
|
||||
foreach ($finalCentroids as $i => $centroid) {
|
||||
$centroidToKlaster[$centroid['index']] = $i + 1;
|
||||
}
|
||||
|
||||
foreach ($data as $item) {
|
||||
Curanmor::where('id', $item->id)->update([
|
||||
'klaster_id' => $centroidToKlaster[$item->temp_klaster],
|
||||
]);
|
||||
}
|
||||
|
||||
session(['hasil_iterasi' => $iterasi]);
|
||||
return $iterasi;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
use App\Models\Klaster;
|
||||
use App\Models\Curanmor;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Services\KMeansService;
|
||||
|
||||
class LandingController extends Controller
|
||||
{
|
||||
|
@ -18,5 +19,26 @@ public function index()
|
|||
$tanggalCuranmor = \Carbon\Carbon::parse($updateCuranmor->updated_at)->translatedFormat('d F Y');
|
||||
return view('landing', compact('klasters', 'tanggalCuras', 'tanggalCuranmor'));
|
||||
}
|
||||
public function runKmeans()
|
||||
{
|
||||
|
||||
$serviceKMeans = new KMeansService();
|
||||
$serviceKMeans->SSEElbowCuranmor();
|
||||
$serviceKMeans->SSEElbowCuras();
|
||||
$serviceKMeans->hitungDBSCANManual();
|
||||
$serviceKMeans->kmeansWithSilhouetteSingleMethod();
|
||||
|
||||
|
||||
$serviceKMeansCuras = new KMeansService();
|
||||
$hasilKMeansCuras = $serviceKMeansCuras->hitungKMeansCuras();
|
||||
file_put_contents(storage_path('app/public/hasil_kmeans_curas.json'), json_encode($hasilKMeansCuras));
|
||||
|
||||
$serviceKmeansCuranmor = new KMeansService();
|
||||
$hasilKMeansCuranmor = $serviceKmeansCuranmor->hitungKMeansCuranmor();
|
||||
file_put_contents(storage_path('app/public/hasil_kmeans_curanmor.json'), json_encode($hasilKMeansCuranmor));
|
||||
|
||||
return redirect('/dashboard');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Kecamatan;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class TampilHitunganController extends Controller
|
||||
{
|
||||
public function TampilHitungCuras()
|
||||
{
|
||||
$file = storage_path('app/public/hasil_kmeans_curas.json');
|
||||
|
||||
if (!file_exists($file)) {
|
||||
return abort(404, 'File hasil KMeans tidak ditemukan.');
|
||||
}
|
||||
|
||||
$data = json_decode(file_get_contents($file), true);
|
||||
|
||||
// Ambil nama kecamatan berdasarkan ID
|
||||
$kecamatan = Kecamatan::pluck('nama_kecamatan', 'id')->toArray();
|
||||
|
||||
return view('admin.HitungKmeans.HitunganCuras', compact('data', 'kecamatan'));
|
||||
}
|
||||
|
||||
public function TampilHitungCuranmor()
|
||||
{
|
||||
$file = storage_path('app/public/hasil_kmeans_curanmor.json');
|
||||
|
||||
if (!file_exists($file)) {
|
||||
return abort(404, 'File hasil KMeans tidak ditemukan.');
|
||||
}
|
||||
|
||||
$data = json_decode(file_get_contents($file), true);
|
||||
|
||||
// Ambil nama kecamatan berdasarkan ID
|
||||
$kecamatan = Kecamatan::pluck('nama_kecamatan', 'id')->toArray();
|
||||
|
||||
return view('admin.HitungKmeans.HitunganCuranmor', compact('data', 'kecamatan'));
|
||||
}
|
||||
}
|
|
@ -14,12 +14,19 @@ public function index()
|
|||
{
|
||||
$jumlahRawanCuras = Curas::where('klaster_id', '3')->count();
|
||||
$jumlahTotalCuras = Curas::count();
|
||||
$prosentaseCuras = ($jumlahRawanCuras / $jumlahTotalCuras) * 100;
|
||||
|
||||
$jumlahRawanCuranmor = Curanmor::where('klaster_id', '3')->count();
|
||||
$jumlahTotalCuranmor = Curanmor::count();
|
||||
$namaUser = Auth::user()->nama;
|
||||
$prosentaseCuras = ($jumlahRawanCuras / $jumlahTotalCuras) * 100;
|
||||
$prosentaseCuranmor = ($jumlahRawanCuranmor / $jumlahTotalCuranmor) * 100;
|
||||
|
||||
$totalKecamatan = Kecamatan::count();
|
||||
return view('admin.dashboardAdmin', compact('jumlahRawanCuras', 'jumlahRawanCuranmor', 'namaUser', 'prosentaseCuras', 'prosentaseCuranmor', 'totalKecamatan'));
|
||||
|
||||
$curasTertinggis = Curas::orderBy('jumlah_curas', 'desc')->take(5)->get();
|
||||
$curanmorTertinggis = Curanmor::orderBy('jumlah_curanmor', 'desc')->take(5)->get();
|
||||
|
||||
|
||||
$namaUser = Auth::user()->nama;
|
||||
return view('admin.dashboardAdmin', compact('jumlahRawanCuras', 'jumlahRawanCuranmor', 'namaUser', 'prosentaseCuras', 'prosentaseCuranmor', 'totalKecamatan', 'curasTertinggis', 'curanmorTertinggis'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class hasilIterasiController extends Controller
|
||||
{
|
||||
public function iterasiCuras()
|
||||
{
|
||||
$iterasi = session('hasil_iterasi');
|
||||
dd($iterasi);
|
||||
|
||||
// Kirim ke view atau proses lainnya
|
||||
return view('admin.dashboarditerasiCuras', compact('iterasi'));
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
use App\Models\Curas;
|
||||
use App\Models\Klaster;
|
||||
use App\Models\Curanmor;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
|
||||
class KMeansService
|
||||
|
@ -12,15 +13,32 @@ class KMeansService
|
|||
public function hitungKMeansCuras()
|
||||
{
|
||||
$data = Curas::select('id', 'kecamatan_id', 'klaster_id', 'jumlah_curas')->orderBy('jumlah_curas', 'asc')->get();
|
||||
|
||||
$k = Klaster::count('id');
|
||||
$maxIterasi = 100;
|
||||
$centroids = $data->random($k)->values()->map(function ($item) {
|
||||
return [
|
||||
'jumlah_curas' => $item->jumlah_curas,
|
||||
];
|
||||
|
||||
// Hitung min dan max untuk normalisasi
|
||||
$minValue = $data->min('jumlah_curas');
|
||||
$maxValue = $data->max('jumlah_curas');
|
||||
|
||||
// Normalisasi data dan simpan hasilnya ke dalam array baru
|
||||
$normalizedData = $data->map(function ($item) use ($minValue, $maxValue) {
|
||||
$normalized = ($item->jumlah_curas - $minValue) / ($maxValue - $minValue);
|
||||
$item->normalized_curas = round($normalized, 2); // 2 angka di belakang koma
|
||||
return $item;
|
||||
});
|
||||
|
||||
// Inisialisasi centroid dengan nilai acak dari rentang normalisasi [0, 1]
|
||||
$generated = collect();
|
||||
while ($generated->count() < $k) {
|
||||
$random = round(mt_rand(0, 100) / 100, 2); // Random 0.00–1.00
|
||||
if (!$generated->contains($random)) {
|
||||
$generated->push($random);
|
||||
}
|
||||
}
|
||||
|
||||
$centroids = $generated->map(fn($value) => ['C' => $value]);
|
||||
$centroidAwal = $centroids->toArray();
|
||||
|
||||
$iterasi = [];
|
||||
$prevAssignment = [];
|
||||
|
||||
|
@ -28,58 +46,57 @@ public function hitungKMeansCuras()
|
|||
$clustered = [];
|
||||
$currentAssignment = [];
|
||||
|
||||
foreach ($data as $item) {
|
||||
foreach ($normalizedData as $item) {
|
||||
$jarak = [];
|
||||
|
||||
foreach ($centroids as $idx => $centroid) {
|
||||
$dist = abs($item->jumlah_curas - $centroid['jumlah_curas']);
|
||||
$jarak["jarakC" . ($idx + 1)] = $dist;
|
||||
$dist = abs($item->normalized_curas - $centroid['C']);
|
||||
$jarak["C" . ($idx + 1)] = round($dist, 2); // Format 2 angka koma
|
||||
}
|
||||
|
||||
$iterasi[$i][] = array_merge(['kecamatan_id' => $item->kecamatan_id], $jarak);
|
||||
|
||||
$minIndex = array_keys($jarak, min($jarak))[0]; // e.g. "jarakC2"
|
||||
$clusterNumber = (int) str_replace("jarakC", "", $minIndex);
|
||||
$minIndex = array_keys($jarak, min($jarak))[0];
|
||||
$clusterNumber = (int) str_replace("C", "", $minIndex);
|
||||
|
||||
$clustered[$clusterNumber][] = $item;
|
||||
$item->temp_klaster = $clusterNumber;
|
||||
$currentAssignment[$item->id] = $clusterNumber;
|
||||
|
||||
// Tambahkan nilai normalisasi ke dalam iterasi
|
||||
$iterasi[$i][] = array_merge(
|
||||
['kecamatan_id' => $item->kecamatan_id],
|
||||
['normal' => round($item->normalized_curas, 2)],
|
||||
$jarak
|
||||
);
|
||||
}
|
||||
|
||||
// ✨ Cek konvergensi: jika assignment sekarang == sebelumnya, break
|
||||
if ($currentAssignment === $prevAssignment) {
|
||||
break;
|
||||
}
|
||||
|
||||
$prevAssignment = $currentAssignment;
|
||||
|
||||
|
||||
|
||||
// Update centroid berdasarkan rata-rata
|
||||
// Update centroid
|
||||
foreach ($clustered as $key => $group) {
|
||||
$avg = collect($group)->avg('jumlah_curas');
|
||||
$avg = collect($group)->avg('normalized_curas');
|
||||
$avg = round($avg, 2); // Format 2 angka koma
|
||||
$centroids = $centroids->map(function ($item, $index) use ($key, $avg) {
|
||||
return $index === ($key - 1)
|
||||
? ['jumlah_curas' => $avg]
|
||||
? ['C' => $avg]
|
||||
: $item;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Final mapping centroid ke klaster_id (aman/sedang/rawan)
|
||||
// Final mapping centroid ke klaster_id
|
||||
$finalCentroids = $centroids->map(function ($item, $index) {
|
||||
return ['index' => $index + 1, 'jumlah_curas' => $item['jumlah_curas']];
|
||||
})->sortBy('jumlah_curas')->values();
|
||||
|
||||
$centroidToKlaster = [];
|
||||
return ['index' => $index + 1, 'C' => round($item['C'], 2)];
|
||||
})->sortBy('C')->values();
|
||||
|
||||
$availableKlasterIDs = Klaster::orderBy('id', 'asc')->pluck('id')->values();
|
||||
foreach ($finalCentroids as $i => $centroid) {
|
||||
// Klaster ID mulai dari 1 (asumsi klaster di DB bernomor 1, 2, 3, ...)
|
||||
$centroidToKlaster[$centroid['index']] = $i + 1;
|
||||
$centroidToKlaster[$centroid['index']] = $availableKlasterIDs[$i];
|
||||
}
|
||||
|
||||
|
||||
// Update ke database
|
||||
foreach ($data as $item) {
|
||||
Curas::where('id', $item->id)->update([
|
||||
|
@ -87,8 +104,23 @@ public function hitungKMeansCuras()
|
|||
]);
|
||||
}
|
||||
|
||||
// Format centroid awal
|
||||
$centroidAwalFormatted = collect($centroidAwal)->values()->map(function ($item, $index) {
|
||||
return ['C' . ($index + 1) => round($item['C'], 2)];
|
||||
});
|
||||
|
||||
// Format centroid akhir
|
||||
$centroidAkhirFormatted = $centroids->values()->map(function ($item, $index) {
|
||||
return ['C' . ($index + 1) => round($item['C'], 2)];
|
||||
});
|
||||
|
||||
// Simpan hasil ke file JSON (opsional)
|
||||
return [
|
||||
'centroid_awal' => $centroidAwalFormatted,
|
||||
'centroid_akhir' => $centroidAkhirFormatted,
|
||||
'iterasi' => $iterasi
|
||||
];
|
||||
|
||||
return $iterasi;
|
||||
}
|
||||
|
||||
|
||||
|
@ -98,12 +130,31 @@ public function hitungKMeansCuranmor()
|
|||
|
||||
$k = Klaster::count('id');
|
||||
$maxIterasi = 100;
|
||||
$centroids = $data->random($k)->values()->map(function ($item) {
|
||||
return [
|
||||
'jumlah_curanmor' => $item->jumlah_curanmor,
|
||||
];
|
||||
|
||||
// Hitung min dan max untuk normalisasi
|
||||
$minValue = $data->min('jumlah_curanmor');
|
||||
$maxValue = $data->max('jumlah_curanmor');
|
||||
|
||||
// Normalisasi data dan simpan hasilnya ke dalam property baru
|
||||
$normalizedData = $data->map(function ($item) use ($minValue, $maxValue) {
|
||||
$normalized = ($maxValue - $minValue) == 0 ? 0 : ($item->jumlah_curanmor - $minValue) / ($maxValue - $minValue);
|
||||
$item->normalized_curanmor = round($normalized, 2);
|
||||
return $item;
|
||||
});
|
||||
|
||||
// Generate centroid awal unik dari data ter-normalisasi
|
||||
$generated = collect();
|
||||
while ($generated->count() < $k) {
|
||||
$rand = mt_rand(0, 100) / 100; // antara 0 dan 1 dengan 2 desimal
|
||||
$rand = round($rand, 2);
|
||||
if (!$generated->contains($rand)) {
|
||||
$generated->push($rand);
|
||||
}
|
||||
}
|
||||
|
||||
$centroids = $generated->map(fn($val) => ['C' => $val]);
|
||||
$centroidAwal = $centroids->toArray();
|
||||
|
||||
$iterasi = [];
|
||||
$prevAssignment = [];
|
||||
|
||||
|
@ -111,67 +162,497 @@ public function hitungKMeansCuranmor()
|
|||
$clustered = [];
|
||||
$currentAssignment = [];
|
||||
|
||||
foreach ($data as $item) {
|
||||
foreach ($normalizedData as $item) {
|
||||
$jarak = [];
|
||||
|
||||
foreach ($centroids as $idx => $centroid) {
|
||||
$dist = abs($item->jumlah_curanmor - $centroid['jumlah_curanmor']);
|
||||
$jarak["jarakC" . ($idx + 1)] = $dist;
|
||||
$dist = abs($item->normalized_curanmor - $centroid['C']);
|
||||
$jarak["C" . ($idx + 1)] = round($dist, 2);
|
||||
}
|
||||
|
||||
$iterasi[$i][] = array_merge(['kecamatan_id' => $item->kecamatan_id], $jarak);
|
||||
// Tambahkan data ke iterasi, termasuk nilai normalisasi
|
||||
$iterasi[$i][] = array_merge(
|
||||
['kecamatan_id' => $item->kecamatan_id],
|
||||
['normal' => $item->normalized_curanmor], // tampilkan nilai normalisasi
|
||||
$jarak
|
||||
);
|
||||
|
||||
$minIndex = array_keys($jarak, min($jarak))[0]; // e.g. "jarakC2"
|
||||
$clusterNumber = (int) str_replace("jarakC", "", $minIndex);
|
||||
$minIndex = array_keys($jarak, min($jarak))[0];
|
||||
$clusterNumber = (int) str_replace("C", "", $minIndex);
|
||||
|
||||
$clustered[$clusterNumber][] = $item;
|
||||
$item->temp_klaster = $clusterNumber;
|
||||
$currentAssignment[$item->id] = $clusterNumber;
|
||||
}
|
||||
|
||||
// ✨ Cek konvergensi: jika assignment sekarang == sebelumnya, break
|
||||
if ($currentAssignment === $prevAssignment) {
|
||||
break;
|
||||
}
|
||||
|
||||
$prevAssignment = $currentAssignment;
|
||||
|
||||
|
||||
|
||||
// Update centroid berdasarkan rata-rata
|
||||
// Update centroid berdasarkan rata-rata normalisasi
|
||||
foreach ($clustered as $key => $group) {
|
||||
$avg = collect($group)->avg('jumlah_curanmor');
|
||||
$avg = collect($group)->avg('normalized_curanmor');
|
||||
$avg = round($avg, 2);
|
||||
$centroids = $centroids->map(function ($item, $index) use ($key, $avg) {
|
||||
return $index === ($key - 1)
|
||||
? ['jumlah_curanmor' => $avg]
|
||||
? ['C' => $avg]
|
||||
: $item;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Final mapping centroid ke klaster_id (aman/sedang/rawan)
|
||||
// Final mapping centroid ke klaster_id
|
||||
$finalCentroids = $centroids->map(function ($item, $index) {
|
||||
return ['index' => $index + 1, 'jumlah_curanmor' => $item['jumlah_curanmor']];
|
||||
})->sortBy('jumlah_curanmor')->values();
|
||||
return ['index' => $index + 1, 'C' => round($item['C'], 2)];
|
||||
})->sortBy('C')->values();
|
||||
|
||||
$availableKlasterIDs = Klaster::orderBy('id', 'asc')->pluck('id')->values();
|
||||
$centroidToKlaster = [];
|
||||
|
||||
foreach ($finalCentroids as $i => $centroid) {
|
||||
// Klaster ID mulai dari 1 (asumsi klaster di DB bernomor 1, 2, 3, ...)
|
||||
$centroidToKlaster[$centroid['index']] = $i + 1;
|
||||
$centroidToKlaster[$centroid['index']] = $availableKlasterIDs[$i];
|
||||
}
|
||||
|
||||
|
||||
// Update ke database
|
||||
// Update database
|
||||
foreach ($data as $item) {
|
||||
Curanmor::where('id', $item->id)->update([
|
||||
'klaster_id' => $centroidToKlaster[$item->temp_klaster],
|
||||
]);
|
||||
}
|
||||
|
||||
session(['hasil_iterasi' => $iterasi]);
|
||||
// Format centroid awal
|
||||
$centroidAwalFormatted = collect($centroidAwal)->values()->map(function ($item, $index) {
|
||||
return ['C' . ($index + 1) => round($item['C'], 2)];
|
||||
});
|
||||
|
||||
return $iterasi;
|
||||
// Format centroid akhir
|
||||
$centroidAkhirFormatted = $centroids->values()->map(function ($item, $index) {
|
||||
return ['C' . ($index + 1) => round($item['C'], 2)];
|
||||
});
|
||||
|
||||
return [
|
||||
'centroid_awal' => $centroidAwalFormatted,
|
||||
'centroid_akhir' => $centroidAkhirFormatted,
|
||||
'iterasi' => $iterasi
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function SSEElbowCuranmor()
|
||||
{
|
||||
$data = Curanmor::select('id', 'jumlah_curanmor')->get();
|
||||
$maxK = 15;
|
||||
$maxIterasi = 100;
|
||||
$elbowData = [];
|
||||
|
||||
$min = $data->min('jumlah_curanmor');
|
||||
$max = $data->max('jumlah_curanmor');
|
||||
|
||||
// Normalisasi jumlah_curanmor
|
||||
$normalizedData = $data->map(function ($item) use ($min, $max) {
|
||||
$item->normalized = ($max - $min) == 0 ? 0 : round(($item->jumlah_curanmor - $min) / ($max - $min), 2);
|
||||
return $item;
|
||||
});
|
||||
|
||||
for ($k = 2; $k <= $maxK; $k++) {
|
||||
$usedValues = [];
|
||||
$centroids = collect();
|
||||
|
||||
// Inisialisasi centroid secara acak dari nilai 0 sampai 1 dengan 2 desimal
|
||||
while ($centroids->count() < $k) {
|
||||
$randVal = round(mt_rand(0, 10000) / 10000, 2); // 2 angka desimal
|
||||
if (!in_array($randVal, $usedValues)) {
|
||||
$centroids->push(['normalized' => $randVal]);
|
||||
$usedValues[] = $randVal;
|
||||
}
|
||||
}
|
||||
|
||||
$prevAssignment = [];
|
||||
|
||||
for ($iter = 0; $iter < $maxIterasi; $iter++) {
|
||||
$clustered = [];
|
||||
$currentAssignment = [];
|
||||
|
||||
foreach ($normalizedData as $item) {
|
||||
$jarak = [];
|
||||
|
||||
foreach ($centroids as $idx => $centroid) {
|
||||
$dist = abs($item->normalized - $centroid['normalized']);
|
||||
$jarak[$idx] = $dist;
|
||||
}
|
||||
|
||||
$minIndex = array_keys($jarak, min($jarak))[0];
|
||||
$clustered[$minIndex][] = $item;
|
||||
$currentAssignment[$item->id] = $minIndex;
|
||||
}
|
||||
|
||||
if ($currentAssignment === $prevAssignment) {
|
||||
break;
|
||||
}
|
||||
|
||||
$prevAssignment = $currentAssignment;
|
||||
|
||||
foreach ($clustered as $key => $group) {
|
||||
$avg = round(collect($group)->avg('normalized'), 2); // 2 angka desimal
|
||||
$centroids = $centroids->map(function ($centroid, $idx) use ($key, $avg) {
|
||||
return $idx == $key
|
||||
? ['normalized' => $avg]
|
||||
: $centroid;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Hitung SSE
|
||||
$sse = 0;
|
||||
foreach ($clustered as $key => $group) {
|
||||
$centroidVal = $centroids[$key]['normalized'];
|
||||
foreach ($group as $item) {
|
||||
$sse += pow($item->normalized - $centroidVal, 2);
|
||||
}
|
||||
}
|
||||
|
||||
$elbowData[] = [
|
||||
'k' => $k,
|
||||
'sse' => round($sse, 2) // 2 angka desimal
|
||||
];
|
||||
}
|
||||
|
||||
file_put_contents(
|
||||
storage_path('app/public/sse_elbow_curanmor.json'),
|
||||
json_encode($elbowData, JSON_PRETTY_PRINT)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function SSEElbowCuras()
|
||||
{
|
||||
$data = Curas::select('id', 'jumlah_curas')->get();
|
||||
$maxK = 4;
|
||||
$maxIterasi = 100;
|
||||
$elbowData = [];
|
||||
|
||||
$min = $data->min('jumlah_curas');
|
||||
$max = $data->max('jumlah_curas');
|
||||
|
||||
// Normalisasi nilai jumlah_curas
|
||||
$normalizedData = $data->map(function ($item) use ($min, $max) {
|
||||
$item->normalized = ($max - $min) == 0 ? 0 : round(($item->jumlah_curas - $min) / ($max - $min), 2);
|
||||
return $item;
|
||||
});
|
||||
|
||||
for ($k = 2; $k <= $maxK; $k++) {
|
||||
$usedValues = [];
|
||||
$centroids = collect();
|
||||
|
||||
// Inisialisasi centroid secara acak dari nilai 0 sampai 1 dengan 2 desimal
|
||||
while ($centroids->count() < $k) {
|
||||
$randVal = round(mt_rand(0, 10000) / 10000, 2); // 0.00 - 1.00
|
||||
if (!in_array($randVal, $usedValues)) {
|
||||
$centroids->push(['normalized' => $randVal]);
|
||||
$usedValues[] = $randVal;
|
||||
}
|
||||
}
|
||||
|
||||
$prevAssignment = [];
|
||||
|
||||
for ($iter = 0; $iter < $maxIterasi; $iter++) {
|
||||
$clustered = [];
|
||||
$currentAssignment = [];
|
||||
|
||||
foreach ($normalizedData as $item) {
|
||||
$jarak = [];
|
||||
|
||||
// Hitung jarak absolut (Manhattan Distance)
|
||||
foreach ($centroids as $idx => $centroid) {
|
||||
$dist = abs($item->normalized - $centroid['normalized']);
|
||||
$jarak[$idx] = $dist;
|
||||
}
|
||||
|
||||
$minIndex = array_keys($jarak, min($jarak))[0];
|
||||
$clustered[$minIndex][] = $item;
|
||||
$currentAssignment[$item->id] = $minIndex;
|
||||
}
|
||||
|
||||
if ($currentAssignment === $prevAssignment) {
|
||||
break;
|
||||
}
|
||||
|
||||
$prevAssignment = $currentAssignment;
|
||||
|
||||
// Update centroid
|
||||
foreach ($clustered as $key => $group) {
|
||||
$avg = round(collect($group)->avg('normalized'), 2);
|
||||
$centroids = $centroids->map(function ($centroid, $idx) use ($key, $avg) {
|
||||
return $idx == $key
|
||||
? ['normalized' => $avg]
|
||||
: $centroid;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Hitung SSE
|
||||
$sse = 0;
|
||||
foreach ($clustered as $key => $group) {
|
||||
$centroidVal = $centroids[$key]['normalized'];
|
||||
foreach ($group as $item) {
|
||||
$sse += pow($item->normalized - $centroidVal, 2);
|
||||
}
|
||||
}
|
||||
|
||||
$elbowData[] = [
|
||||
'k' => $k,
|
||||
'sse' => round($sse, 2) // dibulatkan ke 2 desimal
|
||||
];
|
||||
}
|
||||
|
||||
file_put_contents(
|
||||
storage_path('app/public/sse_elbow_curas.json'),
|
||||
json_encode($elbowData, JSON_PRETTY_PRINT)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function hitungDBSCANManual()
|
||||
{
|
||||
$eps = 1.5; // Jarak maksimum antar titik
|
||||
$minPts = 3; // Minimum tetangga agar jadi core point
|
||||
|
||||
$data = Curas::select('jumlah_curas')->get()->pluck('jumlah_curas')->map(fn($v) => (float)$v)->toArray();
|
||||
$n = count($data);
|
||||
|
||||
$visited = array_fill(0, $n, false);
|
||||
$labels = array_fill(0, $n, null);
|
||||
$clusterId = 0;
|
||||
|
||||
// Fungsi cari tetangga
|
||||
$regionQuery = function ($pointIndex) use ($data, $eps) {
|
||||
$neighbors = [];
|
||||
foreach ($data as $i => $val) {
|
||||
if (abs($val - $data[$pointIndex]) <= $eps) {
|
||||
$neighbors[] = $i;
|
||||
}
|
||||
}
|
||||
return $neighbors;
|
||||
};
|
||||
|
||||
// DBSCAN Proses
|
||||
for ($i = 0; $i < $n; $i++) {
|
||||
if ($visited[$i]) continue;
|
||||
$visited[$i] = true;
|
||||
|
||||
$neighbors = $regionQuery($i);
|
||||
if (count($neighbors) < $minPts) {
|
||||
$labels[$i] = -1; // noise
|
||||
continue;
|
||||
}
|
||||
|
||||
$labels[$i] = $clusterId;
|
||||
$seeds = array_diff($neighbors, [$i]);
|
||||
|
||||
foreach ($seeds as $seed) {
|
||||
if (!$visited[$seed]) {
|
||||
$visited[$seed] = true;
|
||||
$newNeighbors = $regionQuery($seed);
|
||||
if (count($newNeighbors) >= $minPts) {
|
||||
$seeds = array_unique(array_merge($seeds, $newNeighbors));
|
||||
}
|
||||
}
|
||||
|
||||
if ($labels[$seed] === null || $labels[$seed] === -1) {
|
||||
$labels[$seed] = $clusterId;
|
||||
}
|
||||
}
|
||||
|
||||
$clusterId++;
|
||||
}
|
||||
|
||||
// Hitung silhouette (manual satu dimensi)
|
||||
$silhouetteScores = [];
|
||||
foreach ($data as $i => $val) {
|
||||
$label = $labels[$i];
|
||||
if ($label === -1) continue; // skip noise
|
||||
|
||||
$sameCluster = [];
|
||||
$otherClusters = [];
|
||||
|
||||
foreach ($data as $j => $otherVal) {
|
||||
if ($i === $j || $labels[$j] === -1) continue;
|
||||
if ($labels[$j] === $label) {
|
||||
$sameCluster[] = abs($val - $otherVal);
|
||||
} else {
|
||||
$otherClusters[$labels[$j]][] = abs($val - $otherVal);
|
||||
}
|
||||
}
|
||||
|
||||
$a = count($sameCluster) > 0 ? array_sum($sameCluster) / count($sameCluster) : 0;
|
||||
$b = count($otherClusters) > 0 ? min(array_map(fn($d) => array_sum($d) / count($d), $otherClusters)) : 0;
|
||||
|
||||
$s = ($a === $b && $a === 0) ? 0 : ($b - $a) / max($a, $b);
|
||||
$silhouetteScores[] = $s;
|
||||
}
|
||||
|
||||
$meanSilhouette = count($silhouetteScores) > 0 ? round(array_sum($silhouetteScores) / count($silhouetteScores), 4) : 0;
|
||||
|
||||
// Susun hasil anggota klaster
|
||||
$anggotaKlaster = [];
|
||||
foreach ($labels as $i => $label) {
|
||||
$anggotaKlaster[$label][] = $data[$i];
|
||||
}
|
||||
|
||||
$jumlahKlaster = count(array_filter(array_keys($anggotaKlaster), fn($k) => $k !== -1));
|
||||
|
||||
$hasil = [
|
||||
'silhouette' => $meanSilhouette,
|
||||
'jumlah_klaster' => $jumlahKlaster,
|
||||
'anggota_klaster' => $anggotaKlaster,
|
||||
];
|
||||
|
||||
file_put_contents(
|
||||
storage_path('app/public/dbscan_curas.json'),
|
||||
json_encode($hasil, JSON_PRETTY_PRINT)
|
||||
);
|
||||
return $hasil;
|
||||
}
|
||||
|
||||
public function kmeansWithSilhouetteSingleMethod(int $k = 2, int $maxIter = 100): array
|
||||
{
|
||||
// Ambil data dari tabel curas
|
||||
$data = \App\Models\Curas::select('kecamatan_id', 'jumlah_curas')
|
||||
->get()
|
||||
->pluck('jumlah_curas', 'kecamatan_id')
|
||||
->toArray();
|
||||
|
||||
$ids = array_keys($data);
|
||||
$values = array_values($data);
|
||||
|
||||
// Inisialisasi centroid secara random
|
||||
// Ambil nilai min dan max dari data
|
||||
$minValue = min($values);
|
||||
$maxValue = max($values);
|
||||
|
||||
$centroids = [];
|
||||
|
||||
if ($k == 1) {
|
||||
// Jika cuma 1 klaster, centroid random antara min dan max
|
||||
$centroids[] = rand($minValue, $maxValue);
|
||||
} else {
|
||||
// Untuk k >= 2, inisialisasi centroid unik integer dalam rentang min-max
|
||||
$centroids = [];
|
||||
while (count($centroids) < $k) {
|
||||
$randCentroid = rand($minValue, $maxValue);
|
||||
if (!in_array($randCentroid, $centroids)) {
|
||||
$centroids[] = $randCentroid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$clusters = [];
|
||||
$iter = 0;
|
||||
|
||||
do {
|
||||
$clusters = array_fill(0, $k, []);
|
||||
|
||||
// Assign ke klaster terdekat (jarak absolut 1 dimensi)
|
||||
foreach ($values as $idx => $val) {
|
||||
$distances = [];
|
||||
foreach ($centroids as $cidx => $centroid) {
|
||||
$distances[$cidx] = abs($val - $centroid);
|
||||
}
|
||||
asort($distances);
|
||||
$nearestCluster = key($distances);
|
||||
$clusters[$nearestCluster][] = $idx;
|
||||
}
|
||||
|
||||
// Hitung centroid baru
|
||||
$newCentroids = [];
|
||||
foreach ($clusters as $cluster) {
|
||||
if (count($cluster) > 0) {
|
||||
$sum = 0;
|
||||
foreach ($cluster as $i) {
|
||||
$sum += $values[$i];
|
||||
}
|
||||
$newCentroids[] = $sum / count($cluster);
|
||||
} else {
|
||||
// Jika cluster kosong, pilih centroid random
|
||||
$newCentroids[] = $values[array_rand($values)];
|
||||
}
|
||||
}
|
||||
|
||||
$iter++;
|
||||
if ($newCentroids === $centroids) break;
|
||||
if ($iter >= $maxIter) break;
|
||||
$centroids = $newCentroids;
|
||||
|
||||
} while (true);
|
||||
|
||||
// Fungsi hitung rata-rata jarak
|
||||
$avgDistance = function(int $i, array $cluster) use ($values): float {
|
||||
if (count($cluster) <= 1) return 0;
|
||||
$sum = 0;
|
||||
foreach ($cluster as $idx) {
|
||||
if ($idx == $i) continue;
|
||||
$sum += abs($values[$i] - $values[$idx]);
|
||||
}
|
||||
return $sum / (count($cluster) - 1);
|
||||
};
|
||||
|
||||
// Hitung silhouette untuk setiap data
|
||||
$silhouetteScores = [];
|
||||
for ($i = 0; $i < count($values); $i++) {
|
||||
// Cari klaster data ke-i
|
||||
$clusterIdx = null;
|
||||
foreach ($clusters as $cidx => $cluster) {
|
||||
if (in_array($i, $cluster)) {
|
||||
$clusterIdx = $cidx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$a = $avgDistance($i, $clusters[$clusterIdx]);
|
||||
$b = INF;
|
||||
foreach ($clusters as $cidx => $cluster) {
|
||||
if ($cidx == $clusterIdx) continue;
|
||||
$dist = $avgDistance($i, $cluster);
|
||||
if ($dist < $b) $b = $dist;
|
||||
}
|
||||
|
||||
$silhouetteScores[] = ($b - $a) / max($a, $b);
|
||||
}
|
||||
|
||||
$silhouette = array_sum($silhouetteScores) / count($silhouetteScores);
|
||||
|
||||
// Bentuk output anggota klaster dengan kecamatan_id
|
||||
$clusterMembers = [];
|
||||
foreach ($clusters as $cidx => $cluster) {
|
||||
$clusterMembers[$cidx] = [];
|
||||
foreach ($cluster as $idx) {
|
||||
$clusterMembers[$cidx][] = $ids[$idx];
|
||||
}
|
||||
}
|
||||
|
||||
$hasil = [
|
||||
'silhouette' => $silhouette,
|
||||
'jumlah_klaster' => $k,
|
||||
'anggota_klaster' => $clusterMembers,
|
||||
'iterasi' => $iter,
|
||||
'centroid' => $centroids,
|
||||
];
|
||||
|
||||
// Simpan ke file JSON
|
||||
file_put_contents(
|
||||
storage_path('app/public/silhoute_kmeans_curas.json'),
|
||||
json_encode($hasil, JSON_PRETTY_PRINT)
|
||||
);
|
||||
|
||||
return $hasil;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ public function up(): void
|
|||
table: 'kecamatans', indexName: 'curas_kecamatan_id');
|
||||
$table->float('jumlah_curas');
|
||||
$table->foreignId('klaster_id')->nullable()->constrained(
|
||||
table: 'klasters', indexName: 'curas_klaster_id');
|
||||
table: 'klasters', indexName: 'curas_klaster_id')->nullOnDelete();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ public function up(): void
|
|||
table: 'kecamatans', indexName: 'curanmor_kecamatan_id');
|
||||
$table->float('jumlah_curanmor');
|
||||
$table->foreignId('klaster_id')->nullable()->constrained(
|
||||
table: 'klasters', indexName: 'klaster_kecamatan_id');
|
||||
table: 'klasters', indexName: 'klaster_kecamatan_id')->nullOnDelete();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -19,38 +19,68 @@ public function run(): void
|
|||
|
||||
// Data jumlah curanmor untuk setiap kecamatan
|
||||
$dataCuranmor= [
|
||||
1 => 5,
|
||||
2 => 4,
|
||||
3 => 2,
|
||||
4 => 22,
|
||||
5 => 4,
|
||||
6 => 18,
|
||||
7 => 0,
|
||||
8 => 37,
|
||||
9 => 9,
|
||||
10 => 3,
|
||||
11 => 2,
|
||||
12 => 13,
|
||||
13 => 1,
|
||||
14 => 21,
|
||||
15 => 14,
|
||||
16 => 4,
|
||||
17 => 10,
|
||||
18 => 0,
|
||||
19 => 1,
|
||||
1 => 11,
|
||||
2 => 14,
|
||||
3 => 21,
|
||||
4 => 59,
|
||||
5 => 8,
|
||||
6 => 42,
|
||||
7 => 13,
|
||||
8 => 188,
|
||||
9 => 30,
|
||||
10 => 13,
|
||||
11 => 4,
|
||||
12 => 33,
|
||||
13 => 3,
|
||||
14 => 48,
|
||||
15 => 53,
|
||||
16 => 12,
|
||||
17 => 30,
|
||||
18 => 5,
|
||||
19 => 4,
|
||||
20 => 10,
|
||||
21 => 1,
|
||||
22 => 2,
|
||||
21 => 5,
|
||||
22 => 7,
|
||||
23 => 15,
|
||||
24 => 4,
|
||||
];
|
||||
|
||||
// $dataCuranmor= [
|
||||
// 1 => 5,
|
||||
// 2 => 4,
|
||||
// 3 => 2,
|
||||
// 4 => 22,
|
||||
// 5 => 4,
|
||||
// 6 => 18,
|
||||
// 7 => 0,
|
||||
// 8 => 37,
|
||||
// 9 => 9,
|
||||
// 10 => 3,
|
||||
// 11 => 2,
|
||||
// 12 => 13,
|
||||
// 13 => 1,
|
||||
// 14 => 21,
|
||||
// 15 => 14,
|
||||
// 16 => 4,
|
||||
// 17 => 10,
|
||||
// 18 => 0,
|
||||
// 19 => 1,
|
||||
// 20 => 5,
|
||||
// 21 => 1,
|
||||
// 22 => 2,
|
||||
// 23 => 5,
|
||||
// 24 => 2,
|
||||
// ];
|
||||
|
||||
$defaultDate = '2024-12-31 00:00:00';
|
||||
// Looping untuk membuat data curanmor berdasarkan kecamatan
|
||||
foreach ($kecamatanIds as $kecamatanId) {
|
||||
Curanmor::create([
|
||||
'kecamatan_id' => $kecamatanId,
|
||||
'jumlah_curanmor' => $dataCuranmor[$kecamatanId], // Gunakan nilai default jika tidak ada data
|
||||
'klaster_id' => $klasterIds->random(), // Pilih klaster secara acak
|
||||
'created_at' => $defaultDate,
|
||||
'updated_at' => $defaultDate,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,20 +17,20 @@ public function run(): void
|
|||
|
||||
$dataCuras = [
|
||||
1 => 0,
|
||||
2 => 0,
|
||||
3 => 0,
|
||||
4 => 0,
|
||||
2 => 1,
|
||||
3 => 2,
|
||||
4 => 1,
|
||||
5 => 1,
|
||||
6 => 1,
|
||||
7 => 0,
|
||||
8 => 0,
|
||||
9 => 0,
|
||||
8 => 1,
|
||||
9 => 1,
|
||||
10 => 0,
|
||||
11 => 0,
|
||||
12 => 0,
|
||||
13 => 0,
|
||||
14 => 0,
|
||||
15 => 0,
|
||||
15 => 1,
|
||||
16 => 0,
|
||||
17 => 0,
|
||||
18 => 0,
|
||||
|
@ -42,6 +42,33 @@ public function run(): void
|
|||
24 => 2,
|
||||
];
|
||||
|
||||
// $dataCuras = [
|
||||
// 1 => 0,
|
||||
// 2 => 0,
|
||||
// 3 => 0,
|
||||
// 4 => 0,
|
||||
// 5 => 1,
|
||||
// 6 => 1,
|
||||
// 7 => 0,
|
||||
// 8 => 0,
|
||||
// 9 => 0,
|
||||
// 10 => 0,
|
||||
// 11 => 0,
|
||||
// 12 => 0,
|
||||
// 13 => 0,
|
||||
// 14 => 0,
|
||||
// 15 => 0,
|
||||
// 16 => 0,
|
||||
// 17 => 0,
|
||||
// 18 => 0,
|
||||
// 19 => 0,
|
||||
// 20 => 1,
|
||||
// 21 => 0,
|
||||
// 22 => 0,
|
||||
// 23 => 3,
|
||||
// 24 => 2,
|
||||
// ];
|
||||
|
||||
|
||||
$defaultDate = '2024-12-31 00:00:00'; // Default date to be used for both created_at and updated_at
|
||||
|
||||
|
|
|
@ -25,6 +25,10 @@ public function run(): void
|
|||
CuranmorSeeder::class,
|
||||
]);
|
||||
|
||||
$serviceKMeans = new KMeansService();
|
||||
$serviceKMeans->SSEElbowCuranmor();
|
||||
$serviceKMeans->SSEElbowCuras();
|
||||
|
||||
$serviceKMeansCuras = new KMeansService();
|
||||
$hasilKMeansCuras = $serviceKMeansCuras->hitungKMeansCuras();
|
||||
file_put_contents(storage_path('app/public/hasil_kmeans_curas.json'), json_encode($hasilKMeansCuras));
|
||||
|
|
|
@ -15,17 +15,17 @@ public function run(): void
|
|||
{
|
||||
Klaster::create([
|
||||
'nama_klaster'=> 'Aman',
|
||||
'warna'=> '#00FF00',
|
||||
'warna'=> '#27AE60',
|
||||
]);
|
||||
|
||||
Klaster::create([
|
||||
'nama_klaster'=> 'Sedang',
|
||||
'warna'=> '#FFFF00',
|
||||
'warna'=> '#F1C40F',
|
||||
]);
|
||||
|
||||
Klaster::create([
|
||||
'nama_klaster'=> 'Rawan',
|
||||
'warna'=> '#FF0000',
|
||||
'warna'=> '#E74C3C',
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 36 KiB |
|
@ -1012,6 +1012,7 @@ if (jQuery("#radar-multiple-chart").length) {
|
|||
|
||||
// Create series
|
||||
var series = chart.series.push(new am4charts.ColumnSeries());
|
||||
|
||||
series.dataFields.valueY = "visits";
|
||||
series.dataFields.categoryX = "country";
|
||||
series.name = "Visits";
|
||||
|
@ -5193,135 +5194,69 @@ if (jQuery("#editor").length) {
|
|||
apexChartUpdate(chart, e.detail)
|
||||
})
|
||||
}
|
||||
if(jQuery('#layout1-chart-2').length){
|
||||
|
||||
if (jQuery('#layout1-chart-2').length) {
|
||||
am4core.ready(function() {
|
||||
am4core.useTheme(am4themes_animated);
|
||||
|
||||
// Themes begin
|
||||
am4core.useTheme(am4themes_animated);
|
||||
// Themes end
|
||||
|
||||
// Create chart instance
|
||||
var chart = am4core.create("layout1-chart-2", am4charts.XYChart);
|
||||
chart.colors.list = [
|
||||
am4core.color("#32BDEA"),
|
||||
am4core.color("#32BDEA"),
|
||||
am4core.color("#32BDEA"),
|
||||
am4core.color("#32BDEA"),
|
||||
am4core.color("#32BDEA"),
|
||||
am4core.color("#32BDEA"),
|
||||
am4core.color("#32BDEA"),
|
||||
am4core.color("#32BDEA"),
|
||||
am4core.color("#32BDEA")
|
||||
];
|
||||
chart.scrollbarX = new am4core.Scrollbar();
|
||||
|
||||
// Add data
|
||||
chart.data = [{
|
||||
"country": "Jan",
|
||||
"visits": 3025
|
||||
}, {
|
||||
"country": "Feb",
|
||||
"visits": 1882
|
||||
}, {
|
||||
"country": "Mar",
|
||||
"visits": 1809
|
||||
}, {
|
||||
"country": "Apr",
|
||||
"visits": 1322
|
||||
}, {
|
||||
"country": "May",
|
||||
"visits": 1122
|
||||
}, {
|
||||
"country": "Jun",
|
||||
"visits": 1114
|
||||
}, {
|
||||
"country": "Jul",
|
||||
"visits": 984
|
||||
}, {
|
||||
"country": "Aug",
|
||||
"visits": 711
|
||||
}];
|
||||
|
||||
prepareParetoData();
|
||||
|
||||
function prepareParetoData(){
|
||||
var total = 0;
|
||||
|
||||
for(var i = 0; i < chart.data.length; i++){
|
||||
var value = chart.data[i].visits;
|
||||
total += value;
|
||||
}
|
||||
|
||||
var sum = 0;
|
||||
for(var i = 0; i < chart.data.length; i++){
|
||||
var value = chart.data[i].visits;
|
||||
sum += value;
|
||||
chart.data[i].pareto = sum / total * 100;
|
||||
}
|
||||
}
|
||||
|
||||
// Create axes
|
||||
var categoryAxis = chart.xAxes.push(new am4charts.CategoryAxis());
|
||||
categoryAxis.dataFields.category = "country";
|
||||
categoryAxis.renderer.grid.template.location = 0;
|
||||
categoryAxis.renderer.minGridDistance = 60;
|
||||
categoryAxis.tooltip.disabled = true;
|
||||
|
||||
var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
|
||||
valueAxis.renderer.minWidth = 50;
|
||||
valueAxis.min = 0;
|
||||
valueAxis.cursorTooltipEnabled = false;
|
||||
// Buat chart instance
|
||||
var chart = am4core.create("layout1-chart-2", am4charts.XYChart);
|
||||
|
||||
// Create series
|
||||
var series = chart.series.push(new am4charts.ColumnSeries());
|
||||
series.sequencedInterpolation = true;
|
||||
series.dataFields.valueY = "visits";
|
||||
series.dataFields.categoryX = "country";
|
||||
series.tooltipText = "[{categoryX}: bold]{valueY}[/]";
|
||||
series.columns.template.strokeWidth = 0;
|
||||
|
||||
series.tooltip.pointerOrientation = "vertical";
|
||||
|
||||
series.columns.template.column.cornerRadiusTopLeft = 10;
|
||||
series.columns.template.column.cornerRadiusTopRight = 10;
|
||||
series.columns.template.column.fillOpacity = 0.8;
|
||||
|
||||
// on hover, make corner radiuses bigger
|
||||
var hoverState = series.columns.template.column.states.create("hover");
|
||||
hoverState.properties.cornerRadiusTopLeft = 0;
|
||||
hoverState.properties.cornerRadiusTopRight = 0;
|
||||
hoverState.properties.fillOpacity = 1;
|
||||
|
||||
series.columns.template.adapter.add("fill", function(fill, target) {
|
||||
return chart.colors.getIndex(target.dataItem.index);
|
||||
})
|
||||
|
||||
|
||||
var paretoValueAxis = chart.yAxes.push(new am4charts.ValueAxis());
|
||||
paretoValueAxis.renderer.opposite = true;
|
||||
paretoValueAxis.min = 0;
|
||||
paretoValueAxis.max = 100;
|
||||
paretoValueAxis.strictMinMax = true;
|
||||
paretoValueAxis.renderer.grid.template.disabled = true;
|
||||
paretoValueAxis.numberFormatter = new am4core.NumberFormatter();
|
||||
paretoValueAxis.numberFormatter.numberFormat = "#'%'"
|
||||
paretoValueAxis.cursorTooltipEnabled = false;
|
||||
|
||||
var paretoSeries = chart.series.push(new am4charts.LineSeries())
|
||||
paretoSeries.dataFields.valueY = "pareto";
|
||||
paretoSeries.dataFields.categoryX = "country";
|
||||
paretoSeries.yAxis = paretoValueAxis;
|
||||
paretoSeries.tooltipText = "pareto: {valueY.formatNumber('#.0')}%[/]";
|
||||
paretoSeries.bullets.push(new am4charts.CircleBullet());
|
||||
paretoSeries.strokeWidth = 2;
|
||||
paretoSeries.stroke = new am4core.InterfaceColorSet().getFor("alternativeBackground");
|
||||
paretoSeries.strokeOpacity = 0.5;
|
||||
|
||||
// Cursor
|
||||
chart.cursor = new am4charts.XYCursor();
|
||||
chart.cursor.behavior = "panX";
|
||||
|
||||
}); // end am4core.ready()
|
||||
// Inisialisasi axes & series di luar agar tidak duplikat
|
||||
let categoryAxis = chart.xAxes.push(new am4charts.CategoryAxis());
|
||||
categoryAxis.dataFields.category = "k";
|
||||
categoryAxis.renderer.grid.template.location = 0;
|
||||
categoryAxis.renderer.minGridDistance = 30;
|
||||
categoryAxis.title.text = "Jumlah Klaster (K)";
|
||||
|
||||
let valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
|
||||
valueAxis.title.text = "Nilai SSE";
|
||||
|
||||
let lineSeries = chart.series.push(new am4charts.LineSeries());
|
||||
lineSeries.dataFields.valueY = "sse";
|
||||
lineSeries.dataFields.categoryX = "k";
|
||||
lineSeries.name = "SSE";
|
||||
lineSeries.strokeWidth = 2;
|
||||
lineSeries.tooltipText = "K={categoryX}\nSSE={valueY}"; // Tooltip tanpa centroid_awal
|
||||
lineSeries.tensionX = 1;
|
||||
|
||||
let bullet = lineSeries.bullets.push(new am4charts.CircleBullet());
|
||||
bullet.circle.radius = 4;
|
||||
|
||||
chart.cursor = new am4charts.XYCursor();
|
||||
chart.cursor.behavior = "panX";
|
||||
chart.cursor.lineX.disabled = false;
|
||||
chart.cursor.lineY.disabled = false;
|
||||
|
||||
chart.scrollbarX = new am4core.Scrollbar();
|
||||
|
||||
// Fungsi untuk load data berdasarkan tipe
|
||||
function loadChartData(type) {
|
||||
fetch(`/storage/sse_elbow_${type}.json`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
// Format data untuk chart
|
||||
chart.data = data.map(item => ({
|
||||
k: item.k,
|
||||
sse: item.sse
|
||||
}));
|
||||
console.log("Data yang dimuat ke chart:", chart.data);
|
||||
});
|
||||
}
|
||||
|
||||
// Load data default saat pertama kali (curanmor)
|
||||
loadChartData('curanmor');
|
||||
|
||||
// Event listener dropdown untuk memilih tipe data
|
||||
document.querySelectorAll('.chart-option').forEach(item => {
|
||||
item.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
const selected = this.getAttribute('data-value');
|
||||
loadChartData(selected);
|
||||
document.getElementById('dropdownMenuButton002').innerHTML = this.innerText + '<i class="ri-arrow-down-s-line ml-1"></i>';
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
if (jQuery("#layout1-chart-3").length) {
|
||||
options = {
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
<x-layoutAdmin>
|
||||
<div class="content-page">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="d-flex flex-wrap align-items-center justify-content-between mb-4">
|
||||
<div>
|
||||
<h4 class="mb-3">Detail Perhitungan Curanmor</h4>
|
||||
<p class="mb-0">Berikut merupakan detail perhitungan jarak antar setiap data terhadap setiap centroid pada masing masing iterasi. </p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@if (session()->has('succes'))
|
||||
<div class="alert alert-success" role="alert">
|
||||
{{ session('succes') }}
|
||||
</div>
|
||||
@endif
|
||||
@if (session()->has('error'))
|
||||
<div class="alert alert-danger" role="alert">
|
||||
{{ session('error') }}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-lg-12">
|
||||
<h5>Nilai Centroid Awal</h5>
|
||||
<table class="data-table table mb-0 tbl-server-info">
|
||||
<thead class="bg-white text-uppercase">
|
||||
<tr class="ligth ligth-data">
|
||||
@foreach ($data['centroid_awal'] as $centroid)
|
||||
<th class="text-center">{{ array_key_first($centroid) }}</th>
|
||||
@endforeach
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="ligth-body">
|
||||
<tr>
|
||||
@foreach ($data['centroid_awal'] as $centroid)
|
||||
<td class="text-center">{{ array_values($centroid)[0] }}</td>
|
||||
@endforeach
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-lg-12">
|
||||
<br><br><br>
|
||||
@foreach ($data['iterasi'] as $index => $iterasi)
|
||||
<h5>Iterasi ke-{{ $index + 1 }}</h5>
|
||||
<div class="table-responsive rounded mb-3">
|
||||
<table class="data-table table mb-0 tbl-server-info">
|
||||
<thead class="bg-white text-uppercase">
|
||||
<tr class="ligth ligth-data">
|
||||
<th>Nama Kecamatan</th>
|
||||
@foreach (array_keys($iterasi[0]) as $key)
|
||||
@if ($key !== 'kecamatan_id')
|
||||
<th class="text-center">{{ $key }}</th>
|
||||
@endif
|
||||
@endforeach
|
||||
<th>Hasil</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="ligth-body">
|
||||
@foreach ($iterasi as $row)
|
||||
@php
|
||||
$minKey = null;
|
||||
$minVal = INF;
|
||||
foreach ($row as $key => $val) {
|
||||
if (strpos($key, 'C') === 0 && $val < $minVal) {
|
||||
$minVal = $val;
|
||||
$minKey = $key;
|
||||
}
|
||||
}
|
||||
@endphp
|
||||
<tr>
|
||||
<td class="text-left">{{ $kecamatan[$row['kecamatan_id']] ?? 'Tidak Diketahui' }}</td>
|
||||
@foreach ($row as $key => $val)
|
||||
@if ($key !== 'kecamatan_id')
|
||||
<td class="text-center">{{ $val }}</td>
|
||||
@endif
|
||||
@endforeach
|
||||
<td><strong>{{ strtoupper($minKey) }}</strong></td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
<!-- Page end -->
|
||||
</div>
|
||||
</div>
|
||||
</x-layoutAdmin>
|
|
@ -0,0 +1,91 @@
|
|||
<x-layoutAdmin>
|
||||
<div class="content-page">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="d-flex flex-wrap align-items-center justify-content-between mb-4">
|
||||
<div>
|
||||
<h4 class="mb-3">Detail Perhitungan Curas</h4>
|
||||
<p class="mb-0">Berikut merupakan detail perhitungan jarak antar setiap data terhadap setiap centroid pada masing masing iterasi. </p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@if (session()->has('succes'))
|
||||
<div class="alert alert-success" role="alert">
|
||||
{{ session('succes') }}
|
||||
</div>
|
||||
@endif
|
||||
@if (session()->has('error'))
|
||||
<div class="alert alert-danger" role="alert">
|
||||
{{ session('error') }}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-lg-12">
|
||||
<h5>Nilai Centroid Awal</h5>
|
||||
<table class="data-table table mb-0 tbl-server-info">
|
||||
<thead class="bg-white text-uppercase">
|
||||
<tr class="ligth ligth-data">
|
||||
@foreach ($data['centroid_awal'] as $centroid)
|
||||
<th class="text-center">{{ array_key_first($centroid) }}</th>
|
||||
@endforeach
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="ligth-body">
|
||||
<tr>
|
||||
@foreach ($data['centroid_awal'] as $centroid)
|
||||
<td class="text-center">{{ array_values($centroid)[0] }}</td>
|
||||
@endforeach
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-lg-12">
|
||||
<br><br><br>
|
||||
@foreach ($data['iterasi'] as $index => $iterasi)
|
||||
<h5>Iterasi ke-{{ $index + 1 }}</h5>
|
||||
<div class="table-responsive rounded mb-3">
|
||||
<table class="data-table table mb-0 tbl-server-info">
|
||||
<thead class="bg-white text-uppercase">
|
||||
<tr class="ligth ligth-data">
|
||||
<th>Nama Kecamatan</th>
|
||||
@foreach (array_keys($iterasi[0]) as $key)
|
||||
@if ($key !== 'kecamatan_id')
|
||||
<th class="text-center">{{ $key }}</th>
|
||||
@endif
|
||||
@endforeach
|
||||
<th>Hasil</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="ligth-body">
|
||||
@foreach ($iterasi as $row)
|
||||
@php
|
||||
$minKey = null;
|
||||
$minVal = INF;
|
||||
foreach ($row as $key => $val) {
|
||||
if (strpos($key, 'C') === 0 && $val < $minVal) {
|
||||
$minVal = $val;
|
||||
$minKey = $key;
|
||||
}
|
||||
}
|
||||
@endphp
|
||||
<tr>
|
||||
<td class="text-left">{{ $kecamatan[$row['kecamatan_id']] ?? 'Tidak Diketahui' }}</td>
|
||||
@foreach ($row as $key => $val)
|
||||
@if ($key !== 'kecamatan_id')
|
||||
<td class="text-center">{{ $val }}</td>
|
||||
@endif
|
||||
@endforeach
|
||||
<td><strong>{{ strtoupper($minKey) }}</strong></td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
<!-- Page end -->
|
||||
</div>
|
||||
</div>
|
||||
</x-layoutAdmin>
|
|
@ -77,11 +77,72 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 col-lg-6">
|
||||
<div class="card">
|
||||
<div class="card-header d-flex justify-content-between">
|
||||
<div class="header-title">
|
||||
<h4 class="card-title">5 Kecamatan Tertinggi Kasus Curas</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>Berikut merupakan 5 Kecamatan yang memiliki kasus CURAS tertinggi</p>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr class="ligth">
|
||||
<th scope="col">Nama Kecamatan</th>
|
||||
<th scope="col">Jumlah Curas</th>
|
||||
<th scope="col">Klaster</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ( $curasTertinggis as $curasTertinggi )
|
||||
<tr style="background-color: {{ $curasTertinggi->punyaKlasterCuras->warna }}">
|
||||
<td>{{ $curasTertinggi->punyaKecamatanCuras->nama_kecamatan }}</td>
|
||||
<td>{{ $curasTertinggi->jumlah_curas }}</td>
|
||||
<td>{{ $curasTertinggi->punyaKlasterCuras->nama_klaster }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-lg-6">
|
||||
<div class="card">
|
||||
<div class="card-header d-flex justify-content-between">
|
||||
<div class="header-title">
|
||||
<h4 class="card-title">5 Kecamatan Tertinggi Kasus Curanmor</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>Berikut merupakan 5 Kecamatan yang memiliki kasus CURANMOR tertinggi</p>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr class="ligth">
|
||||
<th scope="col">Nama Kecamatan</th>
|
||||
<th scope="col">Jumlah Curanmor</th>
|
||||
<th scope="col">Klaster</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ( $curanmorTertinggis as $curanmorTertinggi )
|
||||
<tr style="background-color: {{ $curanmorTertinggi->punyaKlasterCuranmor->warna }}">
|
||||
<td>{{ $curanmorTertinggi->punyaKecamatanCuranmor->nama_kecamatan }}</td>
|
||||
<td>{{ $curanmorTertinggi->jumlah_curanmor }}</td>
|
||||
<td>{{ $curanmorTertinggi->punyaKlasterCuranmor->nama_klaster }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-12">
|
||||
<div class="card card-block card-stretch card-height">
|
||||
<div class="card-header d-flex justify-content-between">
|
||||
<div class="header-title">
|
||||
<h4 class="card-title">Pemetaan Curas dan Curanmor Kab Probolinggo</h4>
|
||||
<h4 class="card-title" id="map-card-title">Pemetaan Curas dan Curanmor Kab Probolinggo</h4>
|
||||
</div>
|
||||
<div class="card-header-toolbar d-flex align-items-center">
|
||||
<div class="dropdown">
|
||||
|
@ -103,7 +164,33 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-12">
|
||||
<div class="card card-block card-stretch card-height">
|
||||
<div class="card-header d-flex align-items-center justify-content-between">
|
||||
<div class="header-title">
|
||||
<h4 class="card-title">Nilai K Terbaik</h4>
|
||||
</div>
|
||||
<div class="card-header-toolbar d-flex align-items-center">
|
||||
<div class="dropdown">
|
||||
<span class="dropdown-toggle dropdown-bg btn" id="dropdownMenuButton002"
|
||||
data-toggle="dropdown">
|
||||
Curanmor<i class="ri-arrow-down-s-line ml-1"></i>
|
||||
</span>
|
||||
<div class="dropdown-menu dropdown-menu-right shadow-none"
|
||||
aria-labelledby="dropdownMenuButton002">
|
||||
<a class="dropdown-item chart-option" data-value="curanmor" href="#">Curanmor</a>
|
||||
<a class="dropdown-item chart-option" data-value="curas" href="#">Curas</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>Perhitungan Nilai K terbaik menggunakan rumus Sum of Squared Errors (SSE) dengan nilai k = 1 sampa k = 10. Kemudian nilai SSE tersebut ditampilkan dalam Grafik Elbow Method</p>
|
||||
<div id="layout1-chart-2" style="min-height: 360px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Page end -->
|
||||
|
||||
|
@ -112,7 +199,7 @@
|
|||
<script>
|
||||
let map;
|
||||
let geoLayer;
|
||||
let mapTitle = document.querySelector('.card-title');
|
||||
let mapTitle = document.getElementById('map-card-title');
|
||||
let apiUrl = "{{ url('/api/map/curas') }}"; // default awal curas
|
||||
let curasData = {};
|
||||
|
||||
|
@ -177,6 +264,7 @@ function loadInitialMap() {
|
|||
map = L.map('map').setView([-7.843271790154591, 113.2990930356143], 10);
|
||||
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 19,
|
||||
minZoom: 10,
|
||||
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
||||
}).addTo(map);
|
||||
fetchAndLoadMap(apiUrl, 'Pemetaan Curas Kab Probolinggo');
|
||||
|
|
|
@ -11,7 +11,8 @@
|
|||
</div>
|
||||
<a href="/dashboard/curas/create" class="btn btn-primary add-list"><i class="las la-plus mr-3"></i>Tambah Kasus Curas</a>
|
||||
</div>
|
||||
@if (session()->has('succes'))
|
||||
</div>
|
||||
@if (session()->has('succes'))
|
||||
<div class="alert alert-success" role="alert">
|
||||
{{ session('succes') }}
|
||||
</div>
|
||||
|
@ -21,7 +22,7 @@
|
|||
{{ session('error') }}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="col-lg-12">
|
||||
<div class="table-responsive rounded mb-3">
|
||||
<table class="data-table table mb-0 tbl-server-info">
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
Kabupaten Probolinggo. </p>
|
||||
</div>
|
||||
|
||||
<a href="/dashboard/kecamatan/create" class="btn btn-primary add-list"><i class="las la-plus mr-3"></i>Tambah Kecamatan</a>
|
||||
{{-- <a href="/dashboard/kecamatan/create" class="btn btn-primary add-list"><i class="las la-plus mr-3"></i>Tambah Kecamatan</a> --}}
|
||||
</div>
|
||||
@if (session()->has('succes'))
|
||||
<div class="alert alert-success" role="alert">
|
||||
|
@ -35,8 +35,8 @@
|
|||
</div>
|
||||
</th>
|
||||
<th>No</th>
|
||||
<th>Nama Kecamatan</th>
|
||||
<th>Action</th>
|
||||
<th class="text-center">Nama Kecamatan</th>
|
||||
{{-- <th>Action</th> --}}
|
||||
</tr>
|
||||
</thead>
|
||||
@foreach ( $kecamatans as $kecamatan )
|
||||
|
@ -50,7 +50,7 @@
|
|||
</td>
|
||||
<td>{{ $kecamatan -> id }}</td>
|
||||
<td>{{ $kecamatan -> nama_kecamatan }}</td>
|
||||
<td>
|
||||
{{-- <td class="text-center">
|
||||
<div class="d-flex align-items-center list-action">
|
||||
<a class="badge bg-success mr-2" data-toggle="tooltip" data-placement="top" title=""
|
||||
href="/dashboard/kecamatan/{{ $kecamatan ->id}}/edit"><i class="ri-pencil-line mr-0"></i></a>
|
||||
|
@ -61,7 +61,7 @@
|
|||
|
||||
</form>
|
||||
</div>
|
||||
</td>
|
||||
</td> --}}
|
||||
</tr>
|
||||
</tbody>
|
||||
@endforeach
|
||||
|
|
|
@ -9,19 +9,18 @@
|
|||
<p class="mb-0">Berikut merupakan data Klaster atau Kategori yang dijadikan sebagai acuan pemetaan.<br>
|
||||
Ingat dalam pengisian data klaster, kategori aman atau rendah dimulai dari id 1</p>
|
||||
</div>
|
||||
<a href="/dashboard/klaster/create" class="btn btn-primary add-list"><i class="las la-plus mr-3"></i>Tambah Klaster</a>
|
||||
</div>
|
||||
</div>
|
||||
@if (session()->has('succes'))
|
||||
<div class="alert alert-success" role="alert">
|
||||
{{ session('succes') }}
|
||||
</div>
|
||||
@endif
|
||||
@if (session()->has('error'))
|
||||
<div class="alert alert-danger" role="alert">
|
||||
{{ session('error') }}
|
||||
</div>
|
||||
@endif
|
||||
<div class="alert alert-success" role="alert">
|
||||
{{ session('succes') }}
|
||||
</div>
|
||||
@endif
|
||||
@if (session()->has('error'))
|
||||
<div class="alert alert-danger" role="alert">
|
||||
{{ session('error') }}
|
||||
</div>
|
||||
@endif
|
||||
<div class="col-lg-12">
|
||||
<div class="table-responsive rounded mb-3">
|
||||
<table class="data-table table mb-0 tbl-server-info">
|
||||
|
@ -36,7 +35,7 @@
|
|||
<th>id</th>
|
||||
<th>Nama Klaster</th>
|
||||
<th>Warna</th>
|
||||
<th>Action</th>
|
||||
{{-- <th>Action</th> --}}
|
||||
</tr>
|
||||
</thead>
|
||||
@foreach ( $klasters as $klaster )
|
||||
|
@ -51,7 +50,7 @@
|
|||
<td>{{ $klaster -> id }}</td>
|
||||
<td>{{ $klaster -> nama_klaster }}</td>
|
||||
<td style="background-color: {{ $klaster->warna }}" >{{ $klaster -> warna }}</td>
|
||||
<td>
|
||||
{{-- <td>
|
||||
<div class="d-flex align-items-center list-action">
|
||||
<a class="badge bg-success mr-2" data-toggle="tooltip" data-placement="top" title=""
|
||||
href="/dashboard/klaster/{{ $klaster->id }}/edit"><i class="ri-pencil-line mr-0"></i></a>
|
||||
|
@ -62,7 +61,7 @@
|
|||
|
||||
</form>
|
||||
</div>
|
||||
</td>
|
||||
</td> --}}
|
||||
</tr>
|
||||
</tbody>
|
||||
@endforeach
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<x-layoutAdmin>
|
||||
<div class="content-page">
|
||||
<div class="container-fluid add-form-list">
|
||||
<div class="container-fluid add-form-
|
||||
">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div class="card">
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
<div class="iq-sidebar sidebar-default ">
|
||||
<div class="iq-sidebar-logo d-flex align-items-center justify-content-between">
|
||||
<a href="/dashboard" class="header-logo">
|
||||
<img src="{{ asset('/assets/images/logo.png') }}" class="img-fluid rounded-normal light-logo" alt="logo"><h5 class="logo-title light-logo ml-3">PROTECT</h5>
|
||||
<img src="{{ asset('assets/images/logo.png') }}" class="img-fluid rounded-normal light-logo" alt="logo"><h5 class="logo-title light-logo ml-3">KPROTECT</h5>
|
||||
</a>
|
||||
<div class="iq-menu-bt-sidebar ml-0">
|
||||
<i class="las la-bars wrapper-menu"></i>
|
||||
|
@ -56,7 +56,21 @@
|
|||
<span class="ml-4">Dashboard</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class=" {{ Request::is('dashboard/kecamatan')||Request::is('dashboard/kecamatan/create') ? 'active' : '' }}">
|
||||
<li class="{{ Request::is('dashboard/kecamatan') ? 'active' : '' }}">
|
||||
<a href="/dashboard/kecamatan" class="svg-icon">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <path d="M5.875 12.5729C5.30847 11.2498 5 9.84107 5 8.51463C5 4.9167 8.13401 2 12 2C15.866 2 19 4.9167 19 8.51463C19 12.0844 16.7658 16.2499 13.2801 17.7396C12.4675 18.0868 11.5325 18.0868 10.7199 17.7396C9.60664 17.2638 8.62102 16.5151 7.79508 15.6" stroke="#676e8a" stroke-width="1.9200000000000004" stroke-linecap="round"></path> <path d="M14 9C14 10.1046 13.1046 11 12 11C10.8954 11 10 10.1046 10 9C10 7.89543 10.8954 7 12 7C13.1046 7 14 7.89543 14 9Z" stroke="#676e8a" stroke-width="1.9200000000000004"></path> <path d="M20.9605 15.5C21.6259 16.1025 22 16.7816 22 17.5C22 18.4251 21.3797 19.285 20.3161 20M3.03947 15.5C2.37412 16.1025 2 16.7816 2 17.5C2 19.9853 6.47715 22 12 22C13.6529 22 15.2122 21.8195 16.5858 21.5" stroke="#676e8a" stroke-width="1.9200000000000004" stroke-linecap="round"></path> </g></svg>
|
||||
<span class="ml-4">Kecamatan</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="{{ Request::is('dashboard/klaster') ? 'active' : '' }}">
|
||||
<a href="/dashboard/klaster" class="svg-icon">
|
||||
<svg class="svg-icon" id="p-dash4" width="20" height="20" xmlns="http://www.w3.org/ 2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M21.21 15.89A10 10 0 1 1 8 2.83"></path><path d="M22 12A10 10 0 0 0 12 2v10z"></path>
|
||||
</svg>
|
||||
<span class="ml-4">Klaster</span>
|
||||
</a>
|
||||
</li>
|
||||
{{-- <li class=" {{ Request::is('dashboard/kecamatan')||Request::is('dashboard/kecamatan/create') ? 'active' : '' }}">
|
||||
<a href="#product" class="collapsed" data-toggle="collapse" aria-expanded="false">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <path d="M5.875 12.5729C5.30847 11.2498 5 9.84107 5 8.51463C5 4.9167 8.13401 2 12 2C15.866 2 19 4.9167 19 8.51463C19 12.0844 16.7658 16.2499 13.2801 17.7396C12.4675 18.0868 11.5325 18.0868 10.7199 17.7396C9.60664 17.2638 8.62102 16.5151 7.79508 15.6" stroke="#676e8a" stroke-width="1.9200000000000004" stroke-linecap="round"></path> <path d="M14 9C14 10.1046 13.1046 11 12 11C10.8954 11 10 10.1046 10 9C10 7.89543 10.8954 7 12 7C13.1046 7 14 7.89543 14 9Z" stroke="#676e8a" stroke-width="1.9200000000000004"></path> <path d="M20.9605 15.5C21.6259 16.1025 22 16.7816 22 17.5C22 18.4251 21.3797 19.285 20.3161 20M3.03947 15.5C2.37412 16.1025 2 16.7816 2 17.5C2 19.9853 6.47715 22 12 22C13.6529 22 15.2122 21.8195 16.5858 21.5" stroke="#676e8a" stroke-width="1.9200000000000004" stroke-linecap="round"></path> </g></svg>
|
||||
<span class="ml-4">Kecamatan</span>
|
||||
|
@ -77,7 +91,7 @@
|
|||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="{{ Request::is('dashboard/klaster') || Request::is('dashboard/klaster/create') ? 'active' : '' }}">
|
||||
<li class="{{ Request::is('dashboard/klaster') || Request::is('dashboard/klaster/create') ? 'active' : '' }}">
|
||||
<a href="#sale" class="collapsed" data-toggle="collapse" aria-expanded="false">
|
||||
<svg class="svg-icon" id="p-dash4" width="20" height="20" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M21.21 15.89A10 10 0 1 1 8 2.83"></path><path d="M22 12A10 10 0 0 0 12 2v10z"></path>
|
||||
|
@ -99,7 +113,7 @@
|
|||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</li> --}}
|
||||
<li class=" {{ Request::is('dashboard/curas')||Request::is('dashboard/curas/create') ||Request::is('dashboard/curanmor/create') ||Request::is('dashboard/curanmor/create') ||Request::is('dashboard/detail-curas') ||Request::is('dashboard/detail-curanmor') ? 'active' : '' }}">
|
||||
<a href="#people" class="collapsed" data-toggle="collapse" aria-expanded="false">
|
||||
<svg class="svg-icon" id="p-dash8" width="20" height="20" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
@ -166,6 +180,28 @@
|
|||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class=" {{ Request::is('dashboard/TampilHitungCuras')||Request::is('dashboard/TampilHitungCuranmor') ? 'active' : '' }}">
|
||||
<a href="#return" class="collapsed" data-toggle="collapse" aria-expanded="false">
|
||||
<svg fill="#676e8a" height="20px" width="20px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 512 512" xml:space="preserve" stroke="#676e8a"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <g> <g> <path d="M468.293,0c-6.07,0-418.515,0-424.585,0C19.607,0,0,19.607,0,43.707c0,6.07,0,418.515,0,424.585 C0,492.393,19.607,512,43.707,512c6.07,0,418.515,0,424.585,0c24.1,0,43.707-19.607,43.707-43.707c0-6.07,0-418.515,0-424.585 C512,19.607,492.393,0,468.293,0z M237.268,474.537H43.707c-3.443,0-6.244-2.801-6.244-6.244V274.732h199.805V474.537z M237.268,237.268H37.463V43.707c0-3.443,2.801-6.244,6.244-6.244h193.561V237.268z M474.537,468.293 c0,3.443-2.801,6.244-6.244,6.244H274.732V274.732h199.805V468.293z M474.537,237.268H274.732V37.463h193.561 c3.443,0,6.244,2.801,6.244,6.244V237.268z"></path> </g> </g> <g> <g> <path d="M177.327,118.634h-21.229V97.405c0-10.345-8.387-18.732-18.732-18.732s-18.732,8.387-18.732,18.732v21.229H97.405 c-10.345,0-18.732,8.387-18.732,18.732s8.387,18.732,18.732,18.732h21.229v21.229c0,10.345,8.387,18.732,18.732,18.732 s18.732-8.387,18.732-18.732v-21.229h21.229c10.345,0,18.732-8.387,18.732-18.732S187.672,118.634,177.327,118.634z"></path> </g> </g> <g> <g> <path d="M414.595,384.624h-79.43c-9.616,0-18.051,7.044-19.106,16.601c-1.246,11.299,7.568,20.862,18.614,20.862h79.43 c9.616,0,18.051-7.044,19.106-16.601C434.456,394.188,425.642,384.624,414.595,384.624z"></path> </g> </g> <g> <g> <path d="M414.595,327.18h-79.43c-9.616,0-18.051,7.044-19.106,16.601c-1.246,11.299,7.568,20.862,18.614,20.862h79.43 c9.616,0,18.051-7.044,19.106-16.601C434.456,336.744,425.642,327.18,414.595,327.18z"></path> </g> </g> <g> <g> <path d="M414.595,118.634h-79.922c-10.345,0-18.732,8.387-18.732,18.732s8.387,18.732,18.732,18.732h79.922 c10.345,0,18.732-8.387,18.732-18.732S424.94,118.634,414.595,118.634z"></path> </g> </g> <g> <g> <path d="M178.868,389.646l-15.012-15.012l15.012-15.012c7.315-7.315,7.315-19.175-0.001-26.49c-7.314-7.314-19.175-7.315-26.49,0 l-15.01,15.012l-15.012-15.012c-7.313-7.314-19.174-7.315-26.49,0c-7.315,7.315-7.315,19.175,0,26.49l15.012,15.012 l-15.012,15.012c-7.315,7.315-7.315,19.175,0,26.49c7.314,7.314,19.175,7.315,26.49,0l15.012-15.012l15.012,15.012 c7.314,7.315,19.174,7.315,26.49,0C186.183,408.821,186.183,396.961,178.868,389.646z"></path> </g> </g> </g></svg>
|
||||
<span class="ml-4">Detail Perhitungan
|
||||
</span>
|
||||
<svg class="svg-icon iq-arrow-right arrow-active" width="20" height="20" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polyline points="10 15 15 20 20 15"></polyline><path d="M4 4h7a4 4 0 0 1 4 4v12"></path>
|
||||
</svg>
|
||||
</a>
|
||||
<ul id="return" class="iq-submenu collapse" data-parent="#iq-sidebar-toggle">
|
||||
<li class="">
|
||||
<a href="/dashboard/TampilHitungCuras">
|
||||
<i class="las la-minus"></i><span>K - Means Curas</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="">
|
||||
<a href="/dashboard/TampilHitungCuranmor">
|
||||
<i class="las la-minus"></i><span>K - Means Curanmor</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
@ -178,9 +214,9 @@
|
|||
<nav class="navbar navbar-expand-lg navbar-light p-0">
|
||||
<div class="iq-navbar-logo d-flex align-items-center justify-content-between">
|
||||
<i class="ri-menu-line wrapper-menu"></i>
|
||||
<a href="../backend/index.html" class="header-logo">
|
||||
<a href="/dashboard" class="header-logo">
|
||||
<img src="{{ asset('assets/images/logo.png') }}" class="img-fluid rounded-normal" alt="logo">
|
||||
<h5 class="logo-title ml-3">PROTECT</h5>
|
||||
<h5 class="logo-title ml-3">KPROTECT</h5>
|
||||
|
||||
</a>
|
||||
</div>
|
||||
|
@ -335,12 +371,11 @@ class="rounded profile-img img-fluid avatar-70">
|
|||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<ul class="list-inline mb-0">
|
||||
<li class="list-inline-item"><a href="../backend/privacy-policy.html">Privacy Policy</a></li>
|
||||
<li class="list-inline-item"><a href="../backend/terms-of-service.html">Terms of Use</a></li>
|
||||
<li class="list-inline-item">Designed By : <a target="blank" href="https://iqonic.design/">Iconic.Design</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-lg-6 text-right">
|
||||
<span class="mr-1"><script>document.write(new Date().getFullYear())</script>©</span> <a href="#" class="">POS Dash</a>.
|
||||
<span class="mr-1"><script>document.write(new Date().getFullYear())</script>©</span> <a href="/" class="">KProtect</a>.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -88,7 +88,6 @@
|
|||
.legend-item {
|
||||
display: flex;
|
||||
align-items: left;
|
||||
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
|
@ -164,9 +163,10 @@ class="img-fluid"
|
|||
<!-- drop down third level -->
|
||||
</li>
|
||||
<li>
|
||||
<a href="#sectionMap">Map</a>
|
||||
<a href="#sectionOurTeam">Our Teams</a>
|
||||
</li>
|
||||
<li><a href="#sectionOurTeam">Our Teams</a>
|
||||
<li>
|
||||
<a href="#sectionMap">Map</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -1434,6 +1434,47 @@ class="img-fluid rounded-circle"
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="team-box">
|
||||
<div class="team-img text-center">
|
||||
<img
|
||||
src="{{ asset('assets/assetLanding/images/team/zahra.jpg') }}"
|
||||
class="img-fluid rounded-circle"
|
||||
alt="image"
|
||||
/>
|
||||
</div>
|
||||
<div class="team-detail">
|
||||
<a class="team-plus" href="#"><i class="fas fa-plus"></i></a>
|
||||
<div class="team-info">
|
||||
<h6 class="mb-0 text-white">
|
||||
<a href="">Fatimatuzzahra <br></a>
|
||||
</h6>
|
||||
<span class="mb-0 text-white text-gray iq-fw-4"
|
||||
>ANGGOTA PENGUJI</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="team-hover">
|
||||
<p>
|
||||
Dosen Politeknik Negeri Jember Program Studi D4 Teknik Informatika. Berperan sebagai Anggota Penguji pada Web SIG Pemetaan Daerah Rawan Curas dan Curanmor
|
||||
</p>
|
||||
<ul class="list-inline">
|
||||
<li class="list-inline-item">
|
||||
<a href="#sectionOurTeam"><i class="fab fa-facebook-f"></i></a>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<a href="#sectionOurTeam"><i class="fab fa-twitter"></i></a>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<a href="#sectionOurTeam"><i class="fab fa-linkedin-in"></i></a>
|
||||
</li>
|
||||
<li class="list-inline-item">
|
||||
<a href="#sectionOurTeam"><i class="fab fa-instagram"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1511,7 +1552,7 @@ class="tab-pane show active"
|
|||
<span class="legend-label">Update Terakhir Data Curas : {{ $tanggalCuras }}</span>
|
||||
</div>
|
||||
<div class="legend-item" id="update-curanmor" style="display: none;">
|
||||
<span class="legend-label">Update Terakhir Data Curanmor : {{ $tanggalCuranmor }}</span>
|
||||
<span class="legend-label">Update Terakhir Curanmor : {{ $tanggalCuranmor }}</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -1809,8 +1850,8 @@ class="form-control position-relative subscription-email"
|
|||
</li>
|
||||
<li class="list-item"><a href="#sectionCurasCuranmor">Curas</a></li>
|
||||
<li class="list-item"><a href="#sectionKmeans">Clustering</a></li>
|
||||
<li class="list-item"><a href="#sectionMap">Map</a></li>
|
||||
<li class="list-item"><a href="#sectionOurTeam">Our Team</a></li>
|
||||
<li class="list-item"><a href="#sectionMap">Map</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -2046,7 +2087,13 @@ function popUp(feature, layer) {
|
|||
}
|
||||
|
||||
function loadInitialMap() {
|
||||
map = L.map('map').setView([-7.843271790154591, 113.2990930356143], 10);
|
||||
map = L.map('map', {
|
||||
center: [-7.843271790154591, 113.2990930356143],
|
||||
zoom: 10,
|
||||
minZoom: 10,
|
||||
maxZoom: 19
|
||||
});
|
||||
|
||||
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 19,
|
||||
attribution: '© OpenStreetMap'
|
||||
|
@ -2056,41 +2103,37 @@ function loadInitialMap() {
|
|||
fetchAndLoadMap(apiUrl, 'Pemetaan Curas Kab Probolinggo');
|
||||
}
|
||||
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
loadInitialMap();
|
||||
// Jalankan peta awal
|
||||
loadInitialMap();
|
||||
|
||||
document.getElementById('btn-curas').addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
fetchAndLoadMap("{{ url('/api/map/curas') }}", "Pemetaan Curas Kab Probolinggo");
|
||||
});
|
||||
|
||||
document.getElementById('btn-curanmor').addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
fetchAndLoadMap("{{ url('/api/map/curanmor') }}", "Pemetaan Curanmor Kab Probolinggo");
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
document.getElementById('btn-curas').addEventListener('click', (e) => {
|
||||
// Tombol Curas diklik
|
||||
document.getElementById('btn-curas').addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
fetchAndLoadMap("{{ url('/api/map/curas') }}", "Pemetaan Curas Kab Probolinggo");
|
||||
|
||||
// Tampilkan info update curas, sembunyikan curanmor
|
||||
// Tampilkan info curas, sembunyikan curanmor
|
||||
document.getElementById('update-curas').style.display = 'block';
|
||||
document.getElementById('update-curanmor').style.display = 'none';
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementById('btn-curanmor').addEventListener('click', (e) => {
|
||||
// Tombol Curanmor diklik
|
||||
document.getElementById('btn-curanmor').addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
fetchAndLoadMap("{{ url('/api/map/curanmor') }}", "Pemetaan Curanmor Kab Probolinggo");
|
||||
|
||||
// Tampilkan info update curanmor, sembunyikan curas
|
||||
// Tampilkan info curanmor, sembunyikan curas
|
||||
document.getElementById('update-curas').style.display = 'none';
|
||||
document.getElementById('update-curanmor').style.display = 'block';
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -10,20 +10,33 @@
|
|||
use App\Http\Controllers\dashboardController;
|
||||
use App\Http\Controllers\KecamatanController;
|
||||
use App\Http\Controllers\DetailCurasController;
|
||||
use App\Http\Controllers\hasilIterasiController;
|
||||
use App\Http\Controllers\DetailCuranmorController;
|
||||
use App\Http\Controllers\TampilHitunganController;
|
||||
|
||||
|
||||
// Route Landing
|
||||
Route::get('/kmeans', [LandingController::class, 'runKmeans']);
|
||||
Route::get('/', [LandingController::class, 'index']);
|
||||
|
||||
Route::resource('/dashboard/detail-curas', DetailCurasController::class)->middleware('auth');
|
||||
Route::resource('/dashboard/detail-curanmor', DetailCuranmorController::class)->middleware('auth');
|
||||
|
||||
|
||||
Route::get('/blank', function () {
|
||||
return view('admin.dashboardBlank');
|
||||
});
|
||||
|
||||
// Route Auth
|
||||
Route::post('/login', [loginController::class, 'authenticate']);
|
||||
Route::post('/logout', [loginController::class, 'logout']);
|
||||
Route::get('/login', [loginController::class, 'index'])->name('login');
|
||||
|
||||
// Route Fitur Utama Controller
|
||||
Route::get('/dashboard', [dashboardController::class, 'index'])->middleware('auth');
|
||||
Route::get('/dashboard/TampilHitungCuras', [TampilHitunganController::class, 'TampilHitungCuras'])->middleware('auth');
|
||||
Route::get('/dashboard/TampilHitungCuranmor', [TampilHitunganController::class, 'TampilHitungCuranmor'])->middleware('auth');
|
||||
Route::resource('/dashboard/kecamatan', KecamatanController::class) ->parameters(['data-kecamatan' => 'kecamatan'])->middleware('auth');
|
||||
Route::resource('/dashboard/klaster', KlasterController::class) ->parameters(['data-klaster' => 'klaster'])->middleware('auth');
|
||||
Route::resource('/dashboard/curas', CurasController::class)->middleware('auth');
|
||||
Route::resource('/dashboard/curanmor', CuranmorController::class) ->parameters(['data-curanmor' => 'curanmor'])->middleware('auth');
|
||||
Route::resource('/dashboard/detail-curas', DetailCurasController::class)->middleware('auth');
|
||||
Route::resource('/dashboard/detail-curanmor', DetailCuranmorController::class)->middleware('auth');
|
||||
|
||||
// Route Fitur Tampil Map Admin
|
||||
Route::get('/dashboard/mapcuras', function () {
|
||||
return view('admin.dashboardMapCuras');
|
||||
})->middleware('auth');
|
||||
|
@ -31,16 +44,6 @@
|
|||
return view('admin.dashboardMapCuranmor');
|
||||
})->middleware('auth');
|
||||
|
||||
Route::get('/dashboard', [dashboardController::class, 'index'])->middleware('auth');
|
||||
Route::get('/login', [loginController::class, 'index'])->name('login');
|
||||
Route::post('/login', [loginController::class, 'authenticate']);
|
||||
Route::post('/logout', [loginController::class, 'logout']);
|
||||
Route::resource('/dashboard/kecamatan', KecamatanController::class) ->parameters(['data-kecamatan' => 'kecamatan'])->middleware('auth');
|
||||
Route::resource('/dashboard/curas', CurasController::class)->middleware('auth');
|
||||
Route::resource('/dashboard/curanmor', CuranmorController::class) ->parameters(['data-curanmor' => 'curanmor'])->middleware('auth');
|
||||
Route::resource('/dashboard/klaster', KlasterController::class) ->parameters(['data-klaster' => 'klaster'])->middleware('auth');
|
||||
|
||||
Route::get('/dashboard/iterasiCuras', [hasilIterasiController::class, 'iterasiCuras'])->middleware('auth');
|
||||
|
||||
Route::get('/kmeans-curas', [KmeansController::class, 'KMeansCuras']);
|
||||
Route::get('/kmeans-curanmor', [KmeansController::class, 'KMeansCuranmor']);
|
||||
// Route K-Means Centroid Tetap
|
||||
Route::get('/kmeans-curas', [KmeansController::class, 'KMeansCuras'])->middleware('auth');
|
||||
Route::get('/kmeans-curanmor', [KmeansController::class, 'KMeansCuranmor'])->middleware('auth');
|
||||
|
|
Loading…
Reference in New Issue