567 lines
36 KiB
PHP
567 lines
36 KiB
PHP
@extends('layout.app')
|
|
|
|
@section('content')
|
|
@php
|
|
// GENERATE PASANGAN SUB-KRITERIA SECARA DINAMIS
|
|
$dynamicPairs = [];
|
|
if (isset($subs) && count($subs) > 0) {
|
|
$n = count($subs);
|
|
for ($i = 0; $i < $n; $i++) {
|
|
for ($j = $i + 1; $j < $n; $j++) {
|
|
$dynamicPairs[] = [
|
|
'kiri_kode' => $subs[$i]->kode,
|
|
'kiri_nama' => $subs[$i]->nama_sub ?? $subs[$i]->nama,
|
|
'kanan_kode' => $subs[$j]->kode,
|
|
'kanan_nama' => $subs[$j]->nama_sub ?? $subs[$j]->nama,
|
|
];
|
|
}
|
|
}
|
|
}
|
|
|
|
// Helper Matriks Crisp (Sama persis dengan Kriteria Utama)
|
|
if (!function_exists('formatCrispMatrix')) {
|
|
function formatCrispMatrix($val)
|
|
{
|
|
if ($val == 1) return '1';
|
|
if ($val < 1 && $val > 0) {
|
|
$pembagi = round(1 / $val);
|
|
return "<span class='text-danger font-weight-bold'>1/$pembagi</span>";
|
|
}
|
|
if ($val > 1 && floor($val) != $val) {
|
|
$bulat = round($val);
|
|
return "<span class='text-success font-weight-bold'>" . number_format($val, 2) . " <small class='text-muted'>($bulat)</small></span>";
|
|
}
|
|
return "<span class='text-success font-weight-bold'>" . round($val) . '</span>';
|
|
}
|
|
}
|
|
|
|
// Helper Skala Kuesioner
|
|
if (!function_exists('formatSkalaKuesioner')) {
|
|
function formatSkalaKuesioner($val)
|
|
{
|
|
if ($val == 1) return '1';
|
|
if ($val < 1) {
|
|
$pembagi = round(1 / $val);
|
|
return "1/$pembagi";
|
|
}
|
|
return round($val);
|
|
}
|
|
}
|
|
|
|
// Grouping data pakar
|
|
$groupedKuesioner = $allData->groupBy('pakar_ke');
|
|
$pakarList = $groupedKuesioner->keys()->sort();
|
|
@endphp
|
|
|
|
<div class="page-header d-flex justify-content-between align-items-center">
|
|
<ol class="breadcrumb">
|
|
<li class="breadcrumb-item"><a href="{{ route('perbandingansub.index') }}">Perbandingan Sub</a></li>
|
|
<li class="breadcrumb-item active">Detail Tahapan Perhitungan F-AHP</li>
|
|
</ol>
|
|
<div class="d-print-none">
|
|
<a href="{{ route('perbandingansub.detail', ['kriteria_id' => $selectedKriteriaId, 'export' => 'pdf']) }}" target="_blank" class="btn btn-outline-primary btn-sm rounded-pill font-weight-bold shadow-sm">
|
|
<i class="icon-printer"></i> Cetak Laporan Perhitungan
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
{{-- FILTER PILIH KRITERIA --}}
|
|
<div class="col-12 mb-4 d-print-none">
|
|
<div class="card shadow-sm border-0">
|
|
<div class="card-body bg-light">
|
|
<form action="{{ route('perbandingansub.detail') }}" method="GET" class="form-inline">
|
|
<label class="mr-3 font-weight-bold">Lihat Detail Untuk:</label>
|
|
<select name="kriteria_id" class="form-control select2 mr-3" onchange="this.form.submit()"
|
|
style="min-width: 300px;">
|
|
<option value="">-- Pilih Kriteria --</option>
|
|
@foreach ($kriterias as $k)
|
|
<option value="{{ $k->id }}" {{ $selectedKriteriaId == $k->id ? 'selected' : '' }}>
|
|
{{ $k->kode }} - {{ $k->nama }}
|
|
</option>
|
|
@endforeach
|
|
</select>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
@if ($selectedKriteriaId && isset($kriteriaInduk))
|
|
{{-- INFO UTAMA --}}
|
|
<div class="col-12 mb-4">
|
|
<div class="alert alert-info border-0 shadow-sm d-flex align-items-center">
|
|
<i class="icon-layers mr-3" style="font-size: 2rem;"></i>
|
|
<div>
|
|
<h5 class="mb-1 font-weight-bold">Kriteria Induk: {{ $kriteriaInduk->nama }} ({{ $kriteriaInduk->kode }})</h5>
|
|
<p class="mb-0 small">Menampilkan transparansi perhitungan <b>F-AHP</b> untuk Sub-Kriteria sesuai teori Chang's Extent Analysis.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- BAGIAN 1: REFERENSI TFN --}}
|
|
<div class="col-xl-6 col-lg-12 col-md-12 mb-4">
|
|
<div class="card shadow-sm border-0 h-100">
|
|
<div class="card-header bg-dark text-white d-flex justify-content-between align-items-center">
|
|
<h6 class="mb-0 font-weight-bold"><i class="icon-book-open"></i> Referensi Skala TFN (Chang)</h6>
|
|
</div>
|
|
<div class="card-body p-0">
|
|
<div class="p-2 bg-light border-bottom small text-dark">
|
|
Rumus Konversi Bilangan Fuzzy Segitiga (Triangular Fuzzy Number):<br>
|
|
<strong>M = (l, m, u)</strong> → <i>l = lower (batas bawah), m = medium (nilai tengah/puncak), u = upper (batas atas)</i>
|
|
</div>
|
|
<table class="table table-sm mb-0 text-center table-hover" style="font-size: 0.85rem;">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th>Skala Saaty</th>
|
|
<th>Linguistik</th>
|
|
<th>TFN (l, m, u)</th>
|
|
<th class="text-primary">Nilai Kebalikan (1/u, 1/m, 1/l)</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr><td>1</td><td class="text-left">Sama Penting</td><td>(1, 1, 1)</td><td class="text-muted">(1.000, 1.000, 1.000)</td></tr>
|
|
<tr><td>2</td><td class="text-left">Mendekati Sedikit Lebih Penting</td><td>(0.5, 1, 1.5)</td><td class="text-muted">(0.667, 1.000, 2.000)</td></tr>
|
|
<tr><td>3</td><td class="text-left">Sedikit Lebih Penting</td><td>(1, 1.5, 2)</td><td class="text-muted">(0.500, 0.667, 1.000)</td></tr>
|
|
<tr><td>4</td><td class="text-left">Mendekati Lebih Penting</td><td>(1.5, 2, 2.5)</td><td class="text-muted">(0.400, 0.500, 0.667)</td></tr>
|
|
<tr><td>5</td><td class="text-left">Lebih Penting</td><td>(2, 2.5, 3)</td><td class="text-muted">(0.333, 0.400, 0.500)</td></tr>
|
|
<tr><td>6</td><td class="text-left">Mendekati Sangat Penting</td><td>(2.5, 3, 3.5)</td><td class="text-muted">(0.286, 0.333, 0.400)</td></tr>
|
|
<tr><td>7</td><td class="text-left">Sangat Penting</td><td>(3, 3.5, 4)</td><td class="text-muted">(0.250, 0.286, 0.333)</td></tr>
|
|
<tr><td>8</td><td class="text-left">Mendekati Mutlak Penting</td><td>(3.5, 4, 4.5)</td><td class="text-muted">(0.222, 0.250, 0.286)</td></tr>
|
|
<tr><td>9</td><td class="text-left">Mutlak Lebih Penting</td><td>(4, 4.5, 4.5)</td><td class="text-muted">(0.222, 0.222, 0.250)</td></tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- BAGIAN 2: RINGKASAN KUESIONER MULTI-PAKAR & KONSENSUS --}}
|
|
<div class="col-xl-6 col-lg-12 col-md-12 mb-4">
|
|
<div class="card shadow-sm border-0 h-100">
|
|
<div class="card-header bg-secondary text-white d-flex justify-content-between align-items-center">
|
|
<h6 class="mb-0 font-weight-bold"><i class="icon-list"></i> Ringkasan Kuesioner & Konsensus</h6>
|
|
</div>
|
|
<div class="card-body p-0">
|
|
<div class="p-2 bg-light border-bottom">
|
|
<ul class="nav nav-pills nav-sm" id="ringkasanTab" role="tablist">
|
|
@foreach ($pakarList as $p)
|
|
<li class="nav-item">
|
|
<a class="nav-link {{ $loop->first ? 'active' : '' }} font-weight-bold px-3 py-1 mr-1" data-toggle="pill" href="#ringkasan-pakar-{{ $p }}">Pakar {{ $p }}</a>
|
|
</li>
|
|
@endforeach
|
|
<li class="nav-item">
|
|
<a class="nav-link font-weight-bold px-3 py-1 text-primary bg-white border border-primary ml-2" data-toggle="pill" href="#ringkasan-konsensus">
|
|
<i class="icon-layers"></i> Konsensus (GeoMean)
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="tab-content" style="max-height: 335px; overflow-y: auto;">
|
|
@foreach ($pakarList as $p)
|
|
<div class="tab-pane fade {{ $loop->first ? 'show active' : '' }}" id="ringkasan-pakar-{{ $p }}">
|
|
<table class="table table-sm table-hover mb-0 text-center" style="font-size: 0.85rem;">
|
|
<thead class="table-light sticky-top shadow-sm">
|
|
<tr>
|
|
<th class="text-left pl-3">Pasangan Sub-Kriteria</th>
|
|
<th>Skala Asli</th>
|
|
<th class="pr-3">Representasi TFN</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach ($groupedKuesioner[$p] as $item)
|
|
<tr>
|
|
<td class="text-left pl-3 font-weight-bold text-dark">{{ $item->subKiri->kode }} vs {{ $item->subKanan->kode }}</td>
|
|
<td class="font-weight-bold text-success">{{ formatSkalaKuesioner($item->nilai_skala) }}</td>
|
|
<td class="pr-3 text-muted">({{ number_format($item->tfn[0], 2) }}, {{ number_format($item->tfn[1], 2) }}, {{ number_format($item->tfn[2], 2) }})</td>
|
|
</tr>
|
|
@endforeach
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
@endforeach
|
|
<div class="tab-pane fade" id="ringkasan-konsensus">
|
|
<table class="table table-sm table-hover mb-0 text-center" style="font-size: 0.85rem;">
|
|
<thead class="table-primary sticky-top shadow-sm">
|
|
<tr>
|
|
<th class="text-left pl-3">Pasangan Sub-Kriteria</th>
|
|
<th>Nilai GeoMean (Bulat)</th>
|
|
<th class="pr-3">TFN Konsensus</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach ($dynamicPairs as $pair)
|
|
@php
|
|
$kiri = $pair['kiri_kode'];
|
|
$kanan = $pair['kanan_kode'];
|
|
$crispVal = $crispMatrix[$kiri][$kanan];
|
|
$tfnVal = $matrix[$kiri][$kanan];
|
|
if ($crispVal == 1) $displayGeo = '1';
|
|
elseif ($crispVal < 1) $displayGeo = '1/' . round(1 / $crispVal);
|
|
else $displayGeo = number_format($crispVal, 2) . ' (' . round($crispVal) . ')';
|
|
@endphp
|
|
<tr>
|
|
<td class="text-left pl-3 font-weight-bold text-dark" title="{{ $pair['kiri_nama'] }} vs {{ $pair['kanan_nama'] }}">{{ $kiri }} vs {{ $kanan }}</td>
|
|
<td class="font-weight-bold text-primary">{{ $displayGeo }}</td>
|
|
<td class="pr-3 font-weight-bold text-info">({{ number_format($tfnVal[0], 3) }}, {{ number_format($tfnVal[1], 3) }}, {{ number_format($tfnVal[2], 3) }})</td>
|
|
</tr>
|
|
@endforeach
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- TAHAP AWAL: MATRIKS CRISP --}}
|
|
<div class="col-12 mb-4">
|
|
<div class="card shadow-sm border-0">
|
|
<div class="card-header bg-warning text-dark d-flex justify-content-between align-items-center">
|
|
<h6 class="mb-0 font-weight-bold">Tahap Awal: Matriks Crisp (Rata-rata Ukur / GeoMean)</h6>
|
|
</div>
|
|
<div class="card-body p-0">
|
|
<div class="p-3 bg-light border-bottom small text-dark d-flex align-items-center">
|
|
<div class="mr-4">
|
|
<strong>Rumus Rata-rata Ukur (Geometric Mean):</strong><br>
|
|
Digunakan untuk menggabungkan penilaian dari banyak pakar menjadi satu matriks konsensus (Matriks Crisp).
|
|
</div>
|
|
<div class="bg-white p-2 border rounded font-weight-bold text-center text-primary" style="font-size: 1.1rem; letter-spacing: 1px;">
|
|
GM = <sup>n</sup>√(x<sub>1</sub> × x<sub>2</sub> × ... × x<sub>n</sub>)
|
|
</div>
|
|
</div>
|
|
<div class="table-responsive">
|
|
<table class="table table-bordered table-hover table-sm mb-0 text-center" style="font-size: 0.85rem;">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th width="100">Kode Sub</th>
|
|
@foreach ($kodes as $k) <th width="100" title="{{ $subs->where('kode', $k)->first()->nama_sub ?? '' }}">{{ $k }}</th> @endforeach
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach ($kodes as $i)
|
|
<tr>
|
|
<td class="table-light font-weight-bold" title="{{ $subs->where('kode', $i)->first()->nama_sub ?? '' }}">{{ $i }}</td>
|
|
@foreach ($kodes as $j)
|
|
<td>{!! formatCrispMatrix($crispMatrix[$i][$j]) !!}</td>
|
|
@endforeach
|
|
</tr>
|
|
@endforeach
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- TAHAP TAMBAHAN: UJI KONSISTENSI AHP (EIGEN & CR) --}}
|
|
<div class="col-12 mb-4">
|
|
<div class="card shadow-sm border-0 border-left-success">
|
|
<div class="card-header bg-white text-dark d-flex justify-content-between align-items-center py-3">
|
|
<h6 class="mb-0 font-weight-bold text-success"><i class="icon-check-square"></i> Tahap Validasi: Uji Konsistensi (AHP Klasik)</h6>
|
|
</div>
|
|
<div class="card-body p-0">
|
|
<div class="p-3 bg-light border-bottom small text-dark">
|
|
Sesuai kaidah AHP, matriks perbandingan harus diuji konsistensinya sebelum dikonversi ke Fuzzy.
|
|
Matriks dinyatakan konsisten dan valid jika nilai <strong>Consistency Ratio (CR) ≤ 0.10 (10%)</strong>.
|
|
</div>
|
|
|
|
<div class="row m-0">
|
|
{{-- Tabel Nilai Eigen --}}
|
|
<div class="col-md-7 p-3 border-right">
|
|
<h6 class="font-weight-bold small text-muted mb-2">1. Priority Vector (Nilai Eigen)</h6>
|
|
<div class="table-responsive">
|
|
<table class="table table-bordered table-sm text-center mb-0" style="font-size: 0.85rem;">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th>Sub-Kriteria</th>
|
|
<th>Total Kolom Matriks</th>
|
|
<th class="bg-primary text-white">Nilai Eigen (Priority Vector)</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach ($kodes as $k)
|
|
<tr>
|
|
<td class="font-weight-bold" title="{{ $subs->where('kode', $k)->first()->nama_sub ?? '' }}">{{ $k }}</td>
|
|
<td>{{ number_format($colSums[$k], 4) }}</td>
|
|
<td class="font-weight-bold text-primary">{{ number_format($priorityVector[$k], 4) }}</td>
|
|
</tr>
|
|
@endforeach
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Perhitungan CR --}}
|
|
<div class="col-md-5 p-3 bg-white d-flex flex-column justify-content-center">
|
|
<h6 class="font-weight-bold small text-muted mb-3">2. Hasil Uji Konsistensi (CR)</h6>
|
|
<ul class="list-group list-group-flush mb-3" style="font-size: 0.9rem;">
|
|
<li class="list-group-item d-flex justify-content-between align-items-center px-0 py-1 border-0">
|
|
<span>λ<sub>Max</sub> (Lambda Maksimum)</span>
|
|
<strong>{{ number_format($lambdaMax, 4) }}</strong>
|
|
</li>
|
|
<li class="list-group-item d-flex justify-content-between align-items-center px-0 py-1 border-0">
|
|
<span>n (Jumlah Sub-Kriteria)</span>
|
|
<strong>{{ $nKriteria }}</strong>
|
|
</li>
|
|
<li class="list-group-item d-flex justify-content-between align-items-center px-0 py-1 border-0">
|
|
<span>CI = (λ<sub>Max</sub> - n) / (n - 1)</span>
|
|
<strong>{{ number_format($ci, 4) }}</strong>
|
|
</li>
|
|
<li class="list-group-item d-flex justify-content-between align-items-center px-0 py-1 border-0 border-bottom mb-2 pb-2">
|
|
<span>RI (Random Index n={{ $nKriteria }})</span>
|
|
<strong>{{ number_format($ri, 2) }}</strong>
|
|
</li>
|
|
</ul>
|
|
|
|
@php $crPersen = $cr * 100; @endphp
|
|
<div class="p-3 rounded text-center {{ $cr <= 0.10 ? 'bg-success text-white' : 'bg-danger text-white' }}">
|
|
<span class="d-block small text-uppercase font-weight-bold mb-1">Consistency Ratio (CR)</span>
|
|
<h3 class="mb-0 font-weight-bold">{{ number_format($crPersen, 2) }}%</h3>
|
|
<div class="mt-1 small">
|
|
@if($cr <= 0.10)
|
|
<i class="icon-check-circle"></i> MATRIKS KONSISTEN & VALID
|
|
@else
|
|
<i class="icon-x-circle"></i> MATRIKS TIDAK KONSISTEN
|
|
@endif
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- TAHAP 1: MATRIKS F-AHP --}}
|
|
<div class="col-12 mb-4">
|
|
<div class="card shadow-sm border-0">
|
|
<div class="card-header bg-primary text-white d-flex justify-content-between align-items-center">
|
|
<h6 class="mb-0 font-weight-bold">Tahap 1: Matriks Perbandingan Berpasangan Fuzzy (F-AHP)</h6>
|
|
</div>
|
|
<div class="card-body p-0">
|
|
<div class="p-3 bg-light border-bottom small text-dark">
|
|
<strong>Langkah Konversi (Fuzzifikasi):</strong> Matriks perbandingan AHP yang telah dinyatakan konsisten (CR ≤ 0.1) di atas, kemudian dikonversikan ke dalam bilangan Fuzzy (l, m, u) menggunakan skala TFN Chang. Untuk nilai di bawah garis diagonal, digunakan matriks kebalikan: <strong>M<sup>-1</sup> = (1/u, 1/m, 1/l)</strong>.
|
|
</div>
|
|
<div class="table-responsive">
|
|
<table class="table table-bordered table-sm mb-0 text-center" style="font-size: 0.8rem;">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th width="100">Kode Sub</th>
|
|
@foreach ($kodes as $k) <th width="150" title="{{ $subs->where('kode', $k)->first()->nama_sub ?? '' }}">{{ $k }}</th> @endforeach
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach ($kodes as $i)
|
|
<tr>
|
|
<td class="table-light font-weight-bold" title="{{ $subs->where('kode', $i)->first()->nama_sub ?? '' }}">{{ $i }}</td>
|
|
@foreach ($kodes as $j)
|
|
@php $val = $matrix[$i][$j]; @endphp
|
|
<td>({{ number_format($val[0], 3) }}, {{ number_format($val[1], 3) }}, {{ number_format($val[2], 3) }})</td>
|
|
@endforeach
|
|
</tr>
|
|
@endforeach
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- TAHAP 2 --}}
|
|
<div class="col-xl-5 col-lg-5 col-md-12 mb-4">
|
|
<div class="card shadow-sm border-0 h-100">
|
|
<div class="card-header bg-info text-white">
|
|
<h6 class="mb-0 font-weight-bold">Tahap 2: Nilai Sintesis Fuzzy (S<sub>i</sub>)</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="alert alert-light border small mb-3 text-dark">
|
|
<strong>Rumus Sintesis Extent (Chang):</strong><br>
|
|
Menjumlahkan nilai TFN pada tiap baris, lalu dikalikan dengan invers dari grand total matriks.
|
|
<div class="mt-2 bg-white p-2 border rounded font-weight-bold text-center text-primary" style="font-size: 1rem;">
|
|
S<sub>i</sub> = ∑ M<sub>gi</sub> ⊗ [ ∑ ∑ M<sub>gi</sub> ]<sup>-1</sup>
|
|
</div>
|
|
</div>
|
|
<div class="table-responsive">
|
|
<table class="table table-hover table-sm mb-0 text-center" style="font-size: 0.85rem;">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th>Kode Sub</th>
|
|
<th>Vektor S<sub>i</sub> (l, m, u)</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach ($si as $kode => $val)
|
|
<tr>
|
|
<td class="font-weight-bold text-info" title="{{ $subs->where('kode', $kode)->first()->nama_sub ?? '' }}">{{ $kode }}</td>
|
|
<td class="font-family-monospace text-dark">
|
|
({{ number_format($val[0], 4) }}, {{ number_format($val[1], 4) }}, {{ number_format($val[2], 4) }})
|
|
</td>
|
|
</tr>
|
|
@endforeach
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- TAHAP 3 --}}
|
|
<div class="col-xl-7 col-lg-7 col-md-12 mb-4">
|
|
<div class="card shadow-sm border-0 h-100">
|
|
<div class="card-header bg-dark text-white">
|
|
<h6 class="mb-0 font-weight-bold">Tahap 3: Derajat Kemungkinan (V)</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="alert alert-light border small mb-3 text-dark d-flex align-items-center">
|
|
<div class="mr-3">
|
|
<strong>Rumus Derajat Kemungkinan:</strong><br>
|
|
Mencari nilai probabilitas irisan antar bilangan Fuzzy. <br>
|
|
• Jika m<sub>2</sub> ≥ m<sub>1</sub> maka V = 1. <br>
|
|
• Jika l<sub>1</sub> ≥ u<sub>2</sub> maka V = 0.
|
|
</div>
|
|
<div class="bg-white p-2 border rounded font-weight-bold text-center text-primary" style="font-size: 1rem;">
|
|
V = <span style="border-bottom: 1px solid #007bff;">(l<sub>1</sub> - u<sub>2</sub>)</span><br>
|
|
((m<sub>2</sub> - u<sub>2</sub>) - (m<sub>1</sub> - l<sub>1</sub>))
|
|
</div>
|
|
</div>
|
|
<div class="table-responsive">
|
|
<table class="table table-bordered table-sm text-center mb-0" style="font-size: 0.85rem;">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th class="bg-white font-weight-bold text-muted">V(S<sub>Baris</sub> ≥ S<sub>Kolom</sub>)</th>
|
|
@foreach ($kodes as $k) <th title="{{ $subs->where('kode', $k)->first()->nama_sub ?? '' }}">{{ $k }}</th> @endforeach
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach ($vMatrix as $i => $rows)
|
|
<tr>
|
|
<td class="table-light font-weight-bold" title="{{ $subs->where('kode', $i)->first()->nama_sub ?? '' }}">{{ $i }}</td>
|
|
@foreach ($rows as $val)
|
|
<td class="{{ $val == 1 ? 'text-success font-weight-bold' : ($val == 0 ? 'text-danger' : 'text-primary') }}">
|
|
{{ number_format($val, 3) }}
|
|
</td>
|
|
@endforeach
|
|
</tr>
|
|
@endforeach
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- TAHAP 4: NORMALISASI DAN SKALA 1000 --}}
|
|
<div class="col-12">
|
|
<div class="card shadow-sm border-0 border-top-success" style="border-top: 4px solid #28a745 !important;">
|
|
<div class="card-header bg-white py-3">
|
|
<h6 class="mb-0 text-success font-weight-bold"><i class="icon-check-circle"></i> Tahap 4: Vektor Bobot (d') & Normalisasi Lokal (W)</h6>
|
|
</div>
|
|
<div class="card-body p-0">
|
|
<div class="p-3 bg-light border-bottom small text-dark d-flex align-items-center">
|
|
<div class="mr-4">
|
|
<strong>Rumus Nilai Bobot & Normalisasi:</strong><br>
|
|
Nilai awal d' diambil dari nilai V terkecil (Minimum) pada baris tersebut: <strong>d'(A<sub>i</sub>) = min V(S<sub>i</sub> ≥ S<sub>k</sub>)</strong>.<br>
|
|
Kemudian dinormalisasi agar total keseluruhan = 1. Terakhir, dikonversi ke skala pasti (1000).
|
|
</div>
|
|
<div class="bg-white p-2 border rounded font-weight-bold text-center text-primary" style="font-size: 1rem;">
|
|
W<sub>i</sub> = <span style="border-bottom: 1px solid #007bff;">d'(A<sub>i</sub>)</span><br>
|
|
∑ d'(A<sub>k</sub>)
|
|
</div>
|
|
</div>
|
|
<div class="table-responsive">
|
|
<table class="table table-hover mb-0" style="font-size: 0.9rem;">
|
|
<thead class="table-light text-muted">
|
|
<tr>
|
|
<th class="pl-4">Sub-Kriteria</th>
|
|
<th>Nilai Minimal (d' = min V)</th>
|
|
<th>Bobot Normalisasi (W)</th>
|
|
<th>Tingkat Kepentingan (%)</th>
|
|
<th class="pr-4 text-center bg-warning text-dark" style="border-radius: 5px 5px 0 0;">Bobot Final (Skala 1000)</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@php $sumDPrime = array_sum($dPrime); @endphp
|
|
@foreach ($dPrime as $kode => $minV)
|
|
@php
|
|
$w = ($sumDPrime > 0) ? ($minV / $sumDPrime) : 0;
|
|
$subInfo = $subs->where('kode', $kode)->first();
|
|
$namaSub = $subInfo->nama_sub ?? $subInfo->nama ?? '-';
|
|
@endphp
|
|
<tr>
|
|
<td class="pl-4 font-weight-bold text-dark">
|
|
{{ $kode }} - {{ $namaSub }}
|
|
</td>
|
|
<td>{{ number_format($minV, 4) }}</td>
|
|
<td class="font-weight-bold text-primary">{{ number_format($w, 4) }}</td>
|
|
<td>
|
|
<div class="d-flex align-items-center">
|
|
<span class="mr-2 font-weight-bold text-muted" style="width: 50px;">{{ number_format($w * 100, 2) }}%</span>
|
|
<div class="progress flex-grow-1 border" style="height: 8px; border-radius: 4px;">
|
|
<div class="progress-bar bg-success" style="width: {{ $w * 100 }}%"></div>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
<td class="pr-4 text-center font-weight-bold" style="font-size: 1.1rem; color: #d35400;">
|
|
{{ isset($bobot1000[$kode]) ? $bobot1000[$kode] : '-' }}
|
|
</td>
|
|
</tr>
|
|
@endforeach
|
|
</tbody>
|
|
<tfoot class="table-light font-weight-bold border-top">
|
|
<tr>
|
|
<td class="pl-4 text-uppercase text-muted">Total</td>
|
|
<td>{{ number_format($sumDPrime, 4) }}</td>
|
|
<td class="text-primary">1.0000</td>
|
|
<td class="text-success">100%</td>
|
|
<td class="pr-4 text-center text-dark" style="font-size: 1.1rem;">
|
|
{{ isset($bobot1000) ? array_sum($bobot1000) : '-' }}
|
|
</td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@else
|
|
<div class="col-12 py-5 text-center">
|
|
<h5 class="text-muted">Pilih kriteria induk terlebih dahulu untuk melihat detail perhitungan.</h5>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
|
|
<style>
|
|
body, .card-header h6, .table, .breadcrumb-item, .alert, .badge {
|
|
font-family: 'Inter', 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif !important;
|
|
}
|
|
|
|
.font-family-monospace {
|
|
font-family: 'Fira Code', 'Roboto Mono', 'Courier New', monospace !important;
|
|
}
|
|
|
|
.border-left-success {
|
|
border-left: 5px solid #28a745 !important;
|
|
}
|
|
.list-group-item {
|
|
background-color: transparent;
|
|
}
|
|
|
|
/* Styling untuk rumus agar terlihat rapi */
|
|
sup { vertical-align: super; font-size: smaller; }
|
|
sub { vertical-align: sub; font-size: smaller; }
|
|
|
|
@media print {
|
|
.page-header, .sidebar-wrapper, .app-header, .d-print-none, .breadcrumb, .sticky-top {
|
|
display: none !important;
|
|
}
|
|
.main-container { margin: 0 !important; padding: 0 !important; }
|
|
.card { border: 1px solid #ddd !important; box-shadow: none !important; margin-bottom: 25px !important; page-break-inside: avoid; }
|
|
.table-responsive { overflow: visible !important; }
|
|
.card-header { background-color: #f1f1f1 !important; color: #000 !important; border-bottom: 1px solid #ddd !important; }
|
|
.progress { border: 1px solid #000 !important; }
|
|
.progress-bar { background-color: #28a745 !important; -webkit-print-color-adjust: exact; }
|
|
body { background: white !important; color: black !important; }
|
|
.bg-warning { background-color: #ffeeba !important; -webkit-print-color-adjust: exact; }
|
|
.nav-pills { display: none !important; }
|
|
}
|
|
</style>
|
|
@endsection
|