368 lines
19 KiB
PHP
368 lines
19 KiB
PHP
{{-- resources/views/user/ahp.blade.php --}}
|
||
@extends('user.layouts.user')
|
||
|
||
@push('new')
|
||
<!-- Google Font: Poppins -->
|
||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||
<!-- Bootstrap 5 -->
|
||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||
<!-- Animate.css -->
|
||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" />
|
||
<!-- Bootstrap Icons -->
|
||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css" />
|
||
<style>
|
||
body {
|
||
font-family: 'Poppins', sans-serif;
|
||
}
|
||
|
||
.section-title {
|
||
font-size: 1.75rem;
|
||
font-weight: 600;
|
||
margin-bottom: 1.5rem;
|
||
text-align: center;
|
||
}
|
||
|
||
.card-header {
|
||
font-weight: 500;
|
||
}
|
||
|
||
.recommend-card {
|
||
cursor: pointer;
|
||
}
|
||
</style>
|
||
@endpush
|
||
|
||
@section('content')
|
||
@include('user.partials.navbar')
|
||
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css" rel="stylesheet">
|
||
<style>
|
||
.star-rating {
|
||
position: relative;
|
||
display: inline-block;
|
||
font-size: 1rem; /* ubah sesuai keinginan */
|
||
line-height: 1;
|
||
}
|
||
.star-rating .star-back,
|
||
.star-rating .star-front {
|
||
display: flex;
|
||
}
|
||
.star-rating .star-front {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
overflow: hidden;
|
||
width: var(--fill-width); /* sealur dengan persentase */
|
||
}
|
||
.star-rating i {
|
||
margin-right: 2px;
|
||
color: #e4e5e9; /* warna empty star */
|
||
}
|
||
.star-rating .star-front i {
|
||
color: #ffc107; /* warna filled star */
|
||
}
|
||
</style>
|
||
|
||
<div class="container my-5">
|
||
<h2 class="section-title">SPK JURUSAN</h2>
|
||
|
||
@if ($errors->any())
|
||
<div class="alert alert-danger animate__animated animate__shakeX">
|
||
<ul class="mb-0">
|
||
@foreach ($errors->all() as $e)
|
||
<li>{{ $e }}</li>
|
||
@endforeach
|
||
</ul>
|
||
</div>
|
||
@endif
|
||
|
||
{{-- Form Input Nilai UN --}}
|
||
<form method="POST" action="{{ route('user.ahp.process') }}" class="mb-5">
|
||
@csrf
|
||
<div class="card shadow-sm animate__animated animate__fadeInUp">
|
||
<div class="card-header bg-primary text-white">Input Nilai UN (0–100)</div>
|
||
<div class="card-body row">
|
||
@foreach ($mapels as $mid => $mnama)
|
||
<div class="col-md-4 mb-3">
|
||
<label class="form-label">{{ $mnama }}</label>
|
||
<input type="number" name="nilai[{{ $mid }}]" step="0.01" min="0"
|
||
max="100" class="form-control" value="{{ old('nilai.' . $mid) }}">
|
||
</div>
|
||
@endforeach
|
||
</div>
|
||
<div class="card-footer text-end">
|
||
<button class="btn btn-success"><i class="bi bi-gear-fill me-1"></i> Proses AHP</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
|
||
@isset($critWeights)
|
||
@php
|
||
$topJid = array_key_first($globalScores);
|
||
$topName = $jurusans[$topJid] ?? '-';
|
||
$topScore = number_format($globalScores[$topJid] * 100, 2);
|
||
@endphp
|
||
|
||
{{-- Rekomendasi Terbaik --}}
|
||
<div class="row justify-content-center mb-4">
|
||
<div class="col-md-6">
|
||
<div class="card animate__animated animate__fadeInUp">
|
||
<div class="card-header d-flex align-items-center">
|
||
<i class="bi bi-award-fill me-2" style="font-size:1.5rem"></i>
|
||
<h5 class="mb-0">Rekomendasi Terbaik</h5>
|
||
</div>
|
||
<div class="card-body text-center">
|
||
<h3 class="fw-bold">{{ $topName }}</h3>
|
||
@php
|
||
$maxPercent = 0;
|
||
if (!empty($globalScores)) {
|
||
// Jika $globalScores berisi nilai float langsung (misal: 0.85, 0.92)
|
||
$maxRawScore = max(array_values($globalScores)); // Ambil nilai terbesar dari array
|
||
$maxPercent = $maxRawScore * 100; // Konversi ke persentase
|
||
} else {
|
||
// Handle kasus jika $globalScores kosong
|
||
$maxPercent = 1; // Atur nilai default jika tidak ada data
|
||
}
|
||
|
||
$n = 1; // Inisialisasi nomor urut
|
||
@endphp
|
||
@php
|
||
$currentPercent = $topScore; // Persentase untuk baris ini
|
||
$ratingFraction = ($currentPercent / $maxPercent) * 5; // Hitung bintang relatif terhadap maxPercent
|
||
$fillWidth = ($ratingFraction / 5) * 100; // Lebar pengisi bintang dalam persen
|
||
@endphp
|
||
<div class="mb-2">Skor:
|
||
<!-- <strong class="ms-2">({{ $topScore }}%)</strong> -->
|
||
</div>
|
||
<div class="star-rating" style="--fill-width: {{ $fillWidth }}%;">
|
||
<div class="star-back">
|
||
@for ($i = 0; $i < 5; $i++)
|
||
<i class="bi bi-star"></i>
|
||
@endfor
|
||
</div>
|
||
<div class="star-front">
|
||
@for ($i = 0; $i < 5; $i++)
|
||
<i class="bi bi-star-fill"></i>
|
||
@endfor
|
||
</div>
|
||
</div>
|
||
<small class="ms-2 text-muted">({{ number_format($ratingFraction, 1) }}/5.0)</small>
|
||
<p class="text-muted">Jurusan paling sesuai berdasarkan AHP.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{{-- Button Lihat Semua Tabel --}}
|
||
<div class="d-flex justify-content-end mb-4">
|
||
<button class="btn btn-primary me-2" data-bs-toggle="modal" data-bs-target="#tablesModal">
|
||
<i class="bi bi-table me-1"></i> Lihat Semua Tabel
|
||
</button>
|
||
</div>
|
||
|
||
{{-- Modal Semua Tabel --}}
|
||
<div class="modal fade" id="tablesModal" tabindex="-1" aria-hidden="true">
|
||
<div class="modal-dialog modal-xl modal-dialog-scrollable">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title"><i class="bi bi-graph-up me-2"></i>Detail Semua Tabel AHP</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
{{-- 1. Matriks Perbandingan Kriteria --}}
|
||
<h6>1. Matriks Perbandingan Kriteria</h6>
|
||
<div class="table-responsive mb-3">
|
||
<table class="table table-bordered text-center">
|
||
<thead class="table-light">
|
||
<tr>
|
||
<th></th>
|
||
@foreach ($mapels as $mnama)
|
||
<th>{{ $mnama }}</th>
|
||
@endforeach
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
@foreach ($matrixCrit as $i => $row)
|
||
<tr>
|
||
<td><strong>{{ $mapels[$i] }}</strong></td>
|
||
@foreach ($row as $v)
|
||
<td>{{ number_format($v, 4) }}</td>
|
||
@endforeach
|
||
</tr>
|
||
@endforeach
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
{{-- 2. Jumlah Kolom --}}
|
||
<h6>2. Jumlah Kolom</h6>
|
||
<div class="table-responsive mb-3">
|
||
<table class="table table-bordered text-center">
|
||
<tr class="table-light">
|
||
<th></th>
|
||
@foreach ($sumColCrit as $v)
|
||
<th>{{ number_format($v, 4) }}</th>
|
||
@endforeach
|
||
</tr>
|
||
</table>
|
||
</div>
|
||
{{-- 3. Normalisasi & Bobot --}}
|
||
<h6>3. Normalisasi & Bobot</h6>
|
||
<div class="table-responsive mb-3">
|
||
<table class="table table-bordered text-center">
|
||
<thead class="table-light">
|
||
<tr>
|
||
<th></th>
|
||
@foreach ($mapels as $name)
|
||
<th>{{ $name }}</th>
|
||
@endforeach
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
@foreach ($normCrit as $i => $r)
|
||
<tr>
|
||
<td><strong>{{ $mapels[$i] }}</strong></td>
|
||
@foreach ($r as $v)
|
||
<td>{{ number_format($v, 4) }}</td>
|
||
@endforeach
|
||
</tr>
|
||
@endforeach
|
||
<tr class="table-info">
|
||
<td><strong>Bobot</strong></td>
|
||
@foreach ($critWeights as $w)
|
||
<td><strong>{{ number_format($w, 4) }}</strong></td>
|
||
@endforeach
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
{{-- 4. Bobot Alternatif --}}
|
||
<h6>4. Bobot Alternatif</h6>
|
||
@foreach ($altWeights as $i => $weights)
|
||
<p><strong>{{ $mapels[$i] }}</strong></p>
|
||
<div class="table-responsive mb-3">
|
||
<table class="table table-bordered text-center">
|
||
<thead class="table-light">
|
||
<tr>
|
||
<th>Jurusan</th>
|
||
@foreach ($jurusans as $j)
|
||
<th>{{ $j }}</th>
|
||
@endforeach
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><strong>Bobot</strong></td>
|
||
@foreach ($weights as $w)
|
||
<td>{{ number_format($w, 4) }}</td>
|
||
@endforeach
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
@endforeach
|
||
{{-- 5. Ranking Global --}}
|
||
<h6>5. Ranking Global</h6>
|
||
<div class="table-responsive">
|
||
<table class="table table-bordered text-center table-striped">
|
||
<thead class="table-light">
|
||
<tr>
|
||
<th>No.</th>
|
||
<th>Jurusan</th>
|
||
<th>Skor</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
@foreach ($globalScores as $j => $s)
|
||
<tr>
|
||
@php
|
||
$currentPercent = number_format($s * 100, 2); // Persentase untuk baris ini
|
||
$ratingFraction = ($currentPercent / $maxPercent) * 5; // Hitung bintang relatif terhadap maxPercent
|
||
$fillWidth = ($ratingFraction / 5) * 100; // Lebar pengisi bintang dalam persen
|
||
@endphp
|
||
<td>{{ $n++ }}</td>
|
||
<td>{{ $jurusans[$j] }}</td>
|
||
<td>
|
||
<div class="star-rating" style="--fill-width: {{ $fillWidth }}%;">
|
||
<div class="star-back">
|
||
@for ($i = 0; $i < 5; $i++)
|
||
<i class="bi bi-star"></i>
|
||
@endfor
|
||
</div>
|
||
<div class="star-front">
|
||
@for ($i = 0; $i < 5; $i++)
|
||
<i class="bi bi-star-fill"></i>
|
||
@endfor
|
||
</div>
|
||
</div>
|
||
<small class="ms-2 text-muted">({{ number_format($ratingFraction, 1) }}/5.0)</small>
|
||
</td>
|
||
</tr>
|
||
@endforeach
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Tutup</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{{-- Modal Jurusan Rekomendasi --}}
|
||
<div class="modal fade" id="recommendModal" tabindex="-1" aria-hidden="true">
|
||
<div class="modal-dialog modal-dialog-centered">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title">Detail Rekomendasi Terbaik</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||
</div>
|
||
<div class="modal-body text-center">
|
||
<div class="card border-primary mb-3">
|
||
<div class="card-header bg-primary text-white">#1 Recommendation</div>
|
||
<div class="card-body">
|
||
<h5 class="card-title">{{ $topName }} <i class="bi bi-award-fill" style="font-size:2rem; color:gold;"></i></h5>
|
||
@php
|
||
$currentPercent = $topScore; // Persentase untuk baris ini
|
||
$ratingFraction = ($currentPercent / $maxPercent) * 5; // Hitung bintang relatif terhadap maxPercent
|
||
$fillWidth = ($ratingFraction / 5) * 100; // Lebar pengisi bintang dalam persen
|
||
@endphp
|
||
<div class="star-rating" style="--fill-width: {{ $fillWidth }}%;">
|
||
<div class="star-back">
|
||
@for ($i = 0; $i < 5; $i++)
|
||
<i class="bi bi-star"></i>
|
||
@endfor
|
||
</div>
|
||
<div class="star-front">
|
||
@for ($i = 0; $i < 5; $i++)
|
||
<i class="bi bi-star-fill"></i>
|
||
@endfor
|
||
</div>
|
||
</div>
|
||
<small class="ms-2 text-muted">({{ number_format($ratingFraction, 1) }}/5.0)</small>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Tutup</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
@endisset
|
||
</div>
|
||
@endsection
|
||
|
||
@push('scripts')
|
||
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js"></script>
|
||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.min.js"></script>
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
@isset($critWeights)
|
||
// Tampilkan rekomendasi secara otomatis setelah proses AHP
|
||
var recommendModal = new bootstrap.Modal(document.getElementById('recommendModal'));
|
||
recommendModal.show();
|
||
@endisset
|
||
});
|
||
</script>
|
||
@endpush
|