diff --git a/README.md b/README.md new file mode 100644 index 0000000..2fffb82 --- /dev/null +++ b/README.md @@ -0,0 +1,172 @@ +# 📚 Perpus Digital - Prototipe Frontend Aplikasi Perpustakaan + +Prototipe frontend untuk aplikasi **perpustakaan digital** yang ditujukan untuk siswa dan guru. +Aplikasi ini mencakup alur otentikasi (login & register) dan halaman dashboard yang komprehensif untuk menampilkan aktivitas perpustakaan. + +> ⚠️ Prototipe ini **dibangun tanpa backend atau database**. +> Semua data yang ditampilkan bersifat statis (**dummy data**) yang disimulasikan melalui Laravel Service untuk keperluan demonstrasi dan pengembangan antarmuka (**UI/UX**). + +--- + +## ✨ Fitur Utama + +- [x] **Autentikasi (Login & Register)** + Sistem login siswa menggunakan **NISN** dan registrasi sederhana. + +- [x] **Dashboard** + Menampilkan ringkasan aktivitas siswa/guru seperti statistik pinjaman, grafik, dan pengumuman. + +- [x] **Peminjaman Buku Offline** + Simulasi peminjaman buku fisik di perpustakaan. + +- [x] **Peminjaman Buku Online** + Simulasi membaca atau meminjam buku digital langsung di aplikasi. + +- [x] **Riwayat Peminjaman Offline** + Daftar histori buku fisik yang pernah dipinjam. + +- [x] **Riwayat Peminjaman Online** + Daftar histori buku digital yang pernah dipinjam atau dibaca. + +- [ ] **Role Management** + Manajemen peran (siswa & guru) untuk akses fitur yang berbeda. + - Siswa : [x] + - Penjaga Perpus : [x] + - Guru : [] + + +- [x] **Katalog Buku** + Daftar buku dengan informasi detail dan cover. + +--- + +## 🛠️ Teknologi yang Digunakan + +- **Framework**: Laravel 12 +- **Frontend**: + - Bootstrap 5 + - Sass (SCSS) untuk theming kustom + - Vite.js untuk kompilasi aset +- **Grafik (Charting)**: Chart.js +- **Ikon**: Bootstrap Icons +- **Bahasa**: PHP 8.4, JavaScript + +--- + +## 📦 Prasyarat + +Sebelum menjalankan proyek ini, pastikan sudah terinstal: + +- [PHP](https://www.php.net/) **8.2+** +- [Composer](https://getcomposer.org/) (manajer paket PHP) +- [Node.js & NPM](https://nodejs.org/) (manajer paket JavaScript) + +--- + +## 🚀 Instalasi & Cara Menjalankan + +### 1. Clone atau Unduh Proyek +Jika proyek ada di repositori Git: +```bash +git clone https://github.com/zhadaarsita/skripsi-perpus-fe.git +cd skripsi-perpus-fe + +```` + +Atau ekstrak file **ZIP** jika tidak menggunakan Git. + +--- + +### 2. Instal Dependensi PHP + +```bash +composer install +``` + +--- + +### 3. Buat File Environment + +```bash +cp .env.example .env +``` + +--- + +### 4. Hasilkan Kunci Aplikasi + +```bash +php artisan key:generate +``` + +--- + +### 5. Instal Dependensi Frontend + +```bash +npm install +``` + +--- + +### 6. Compile Aset Frontend & Jalankan Server + +**A. Development (auto-refresh browser)** +Gunakan 2 terminal terpisah: + +* Terminal 1: + + ```bash + npm run dev + ``` +* Terminal 2: + + ```bash + php artisan serve + ``` + +**B. Simulasi Produksi** + +```bash +npm run build +php artisan serve +``` + +--- + +### 7. Buka Aplikasi + +```text +http://127.0.0.1:8000 +``` + +--- + +## 🔑 Informasi Login (Dummy Data) + +Gunakan kredensial berikut untuk masuk sebagai siswa: + +* **NISN**: `1234567890` +* **Password**: `password` + +Gunakan kredensial berikut untuk masuk sebagai guru: + +* **email**: `rina.marlina@smkn1perpus.sch.id` +* **Password**: `password` + +Gunakan kredensial berikut untuk masuk sebagai penjaga perpus: + +* **email**: `budi.santoso@smkn1perpus.sch.id` +* **Password**: `password` + +--- + +## 📚 Belajar Laravel + +Untuk dokumentasi resmi Laravel: +👉 [https://laravel.com/docs](https://laravel.com/docs) + +--- +# skripsi-perpus-fe +# skripsi-perpus-fe +# skripsi-perpus-fe-main diff --git a/app/Auth/DummyUserProvider.php b/app/Auth/DummyUserProvider.php new file mode 100644 index 0000000..4d82d6a --- /dev/null +++ b/app/Auth/DummyUserProvider.php @@ -0,0 +1,41 @@ +firstWhere('id', $identifier); + + if ($userArray) { + $userModel = new User(); + $userArray['name'] = $userArray['nama_lengkap']; + $userModel->forceFill($userArray); + return $userModel; + } + + return null; + } + + /** + * Rehash the user's password if required. + */ + public function rehashPasswordIfRequired(Authenticatable $user, array $credentials, bool $force = false): void + { + } + + public function retrieveByToken($identifier, $token) { return null; } + public function updateRememberToken(Authenticatable $user, $token) { } + public function retrieveByCredentials(array $credentials) { return null; } + public function validateCredentials(Authenticatable $user, array $credentials) { return false; } +} \ No newline at end of file diff --git a/app/Http/Controllers/Admin/AdminPeminjamanController.php b/app/Http/Controllers/Admin/AdminPeminjamanController.php new file mode 100644 index 0000000..ac8c240 --- /dev/null +++ b/app/Http/Controllers/Admin/AdminPeminjamanController.php @@ -0,0 +1,210 @@ +map(function ($item) use ($allUsers) { + $userData = $allUsers->firstWhere('id', $item['user_id']); + $role = $userData ? strtolower($userData['role']) : 'siswa'; + $item['role'] = $role; + + // Hitung Denda Flat 1000/hari + $tenggat = Carbon::parse($item['tenggat_kembali']); + $now = Carbon::now(); + + $item['hari_terlambat'] = 0; + $item['total_denda'] = 0; + $item['denda_per_hari'] = 1000; + + if ($now->greaterThan($tenggat)) { + $hariTelat = $tenggat->diffInDays($now); + $item['hari_terlambat'] = $hariTelat; + + if ($role === 'guru') { + $item['total_denda'] = 0; + $item['denda_per_hari'] = 0; + } else { + $item['total_denda'] = $hariTelat * 1000; + } + } + + // Generate WA Link + $hp = $item['nomor_hp']; + if (substr($hp, 0, 1) == '0') { + $hp = '62' . substr($hp, 1); + } + + // Pesan WA dibedakan antara Guru dan Siswa + if ($role === 'guru') { + $pesan = "Halo Bapak/Ibu {$item['peminjam']}, buku yang dipinjam sudah melewati tenggat waktu {$item['hari_terlambat']} hari. Mohon berkenan untuk segera dikembalikan ke perpustakaan ya."; + } else { + $pesan = "Halo kak {$item['peminjam']}, buku anda sudah terlambat {$item['hari_terlambat']} hari dengan denda Rp " . number_format($item['total_denda'], 0, ',', '.') . ". Mohon segera dikembalikan ya."; + } + + $item['wa_link'] = "https://wa.me/{$hp}?text=" . urlencode($pesan); + + return $item; + }); + + $daftarPeminjam = $peminjamanAktif->pluck('peminjam')->unique(); + + return view('admin.peminjaman.index', [ + 'pageTitle' => 'Manajemen Peminjaman', + 'peminjamanAktif' => $peminjamanAktif, + 'daftarPeminjam' => $daftarPeminjam, + ]); + } + + public function create() + { + $allUsers = collect(DummyDataService::getAllSiswa()); + $peminjamanAktif = DummyDataService::getAdminPeminjamanAktif(); + + $groupedUsers = $allUsers + ->whereIn('role', ['siswa', 'guru']) + ->map(function ($user) use ($peminjamanAktif) { + + // Hitung berapa buku yang sedang dipinjam + $jumlahPinjam = $peminjamanAktif->where('peminjam', $user['nama_lengkap'])->count(); + + $user['jumlah_pinjam'] = $jumlahPinjam; + if (strtolower($user['role']) === 'siswa') { + $user['kena_limit'] = $jumlahPinjam >= 2; + } else { + $user['kena_limit'] = false; + } + + // Cek apakah user di-banned (Nonaktif Manual) + $user['is_banned'] = $user['is_banned'] ?? false; + $user['disabled'] = $user['kena_limit'] || $user['is_banned']; + + if ($user['is_banned']) { + $user['status_text'] = "(Akun Dibekukan)"; + } elseif ($user['kena_limit']) { + $user['status_text'] = "(Limit Penuh: 2/2)"; + } else { + $user['status_text'] = ""; + } + + $user['jabatan'] = $user['jabatan'] ?? 'Guru Mata Pelajaran'; + + return $user; + }) + ->groupBy('role'); + + $daftarBuku = DummyDataService::getAllBooks() + ->where('status', 'Tersedia') + ->filter(function ($buku) { + if (is_array($buku['tipe_akses'])) { + return in_array('offline', $buku['tipe_akses']); + } + return $buku['tipe_akses'] === 'offline'; + }); + + return view('admin.peminjaman.create', [ + 'pageTitle' => 'Buat Peminjaman Manual', + 'groupedUsers' => $groupedUsers, + 'daftarBuku' => $daftarBuku, + ]); + } + + /** + * Menampilkan halaman KHUSUS Manajemen Denda (Siswa & Guru Telat). + */ + public function dendaIndex() + { + $allData = DummyDataService::getAdminPeminjamanAktif(); + $allSiswaRaw = collect(DummyDataService::getAllSiswa()); + $now = \Carbon\Carbon::now(); + + // LOGIC AUTO-BAN + $allSiswa = $allSiswaRaw->map(function ($siswa) use ($allData, $now) { + $pinjamanUser = $allData->firstWhere('user_id', $siswa['id']); + $isTelat = false; + + if ($pinjamanUser) { + $isTelat = $pinjamanUser['tenggat_kembali']->startOfDay()->lt($now->startOfDay()); + } + + if ($siswa['role'] === 'siswa' && $isTelat) { + $siswa['is_banned'] = true; + } + + return $siswa; + }); + + $siswaTelat = $allData->filter(function ($item) use ($now, $allSiswa) { + $userData = $allSiswa->firstWhere('id', $item['user_id']); + + if (!$userData) return false; + + $isTelat = $item['tenggat_kembali']->startOfDay()->lt($now->startOfDay()); + $isBanned = $userData['is_banned']; + $isTargetRole = in_array($userData['role'], ['siswa', 'guru']); + + return ($isTelat || $isBanned) && $isTargetRole; + })->map(function ($item) use ($now, $allSiswa) { + + $tenggat = $item['tenggat_kembali']->startOfDay(); + $hariTelat = ($tenggat->lt($now->startOfDay())) ? $tenggat->diffInDays($now->startOfDay()) : 0; + + $dataSiswa = $allSiswa->firstWhere('id', $item['user_id']); + $role = $dataSiswa ? strtolower($dataSiswa['role']) : 'siswa'; + $item['role'] = $role; + + if ($role === 'guru') { + $item['total_denda'] = 0; + } else { + $item['total_denda'] = $hariTelat * $item['denda_per_hari']; + } + + $item['hari_terlambat'] = $hariTelat; + $item['is_banned'] = $dataSiswa['is_banned'] ?? false; + $item['kelas'] = $dataSiswa['kelas'] ?? 'Guru'; + + // Link WA + $hp = $item['nomor_hp']; + if (substr($hp, 0, 1) == '0') $hp = '62' . substr($hp, 1); + + if ($hariTelat > 0 && $role !== 'guru') { + $pesan = "Halo {$item['peminjam']}, anda terlambat pengembalian buku. Total Denda: Rp " . number_format($item['total_denda'], 0, ',', '.'); + } elseif ($hariTelat > 0 && $role === 'guru') { + $pesan = "Halo Bapak/Ibu {$item['peminjam']}, mohon berkenan untuk mengembalikan buku yang telah melewati tenggat waktu."; + } else { + $pesan = "Halo {$item['peminjam']}, akun anda sedang dinonaktifkan sementara. Mohon hubungi petugas."; + } + + $item['wa_link'] = "https://wa.me/{$hp}?text=" . urlencode($pesan); + + return $item; + }); + + $listKelas = $siswaTelat->pluck('kelas')->unique()->values(); + + return view('admin.denda.index', [ + 'pageTitle' => 'Manajemen Denda & Sanksi', + 'siswaTelat' => $siswaTelat, + 'listKelas' => $listKelas + ]); + } + + /** + * Dummy function untuk tombol Sanksi + */ + public function berikanSanksi(Request $request) + { + return response()->json(['status' => 'success']); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Admin/AdminRekomendasiController.php b/app/Http/Controllers/Admin/AdminRekomendasiController.php new file mode 100644 index 0000000..e06c688 --- /dev/null +++ b/app/Http/Controllers/Admin/AdminRekomendasiController.php @@ -0,0 +1,52 @@ +map(function ($item) { + $videoId = $this->extractYouTubeId($item['youtube_link']); + if ($videoId) { + $item['thumbnail'] = "https://img.youtube.com/vi/{$videoId}/hqdefault.jpg"; + } else { + $item['thumbnail'] = 'https://via.placeholder.com/150?text=No+Preview'; + } + return $item; + }); + + return view('admin.rekomendasi.index', [ + 'pageTitle' => 'Manajemen Rekomendasi', + 'semuaRekomendasi' => $semuaRekomendasi + ]); + } + + public function create() + { + return view('admin.rekomendasi.create', ['pageTitle' => 'Tambah Rekomendasi']); + } + + public function edit($id) + { + $rekomendasi = DummyDataService::getRekomendasiPembelajaran()->firstWhere('id', (int)$id); + abort_if(!$rekomendasi, 404); + return view('admin.rekomendasi.edit', ['pageTitle' => 'Edit Rekomendasi', 'rekomendasi' => $rekomendasi]); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Admin/BookController.php b/app/Http/Controllers/Admin/BookController.php new file mode 100644 index 0000000..e4a11d3 --- /dev/null +++ b/app/Http/Controllers/Admin/BookController.php @@ -0,0 +1,50 @@ +only(['search']); + $semuaBuku = DummyDataService::getKatalogBuku($filters); + + // Memisahkan buku menjadi dua koleksi: online dan offline + [$bukuOnline, $bukuOffline] = $semuaBuku->partition(function ($buku) { + $tipe = $buku['tipe_akses']; + return $tipe === 'online' || (is_array($tipe) && in_array('online', $tipe)); + }); + + return view('admin.buku.index', [ + 'pageTitle' => 'Manajemen Buku', + 'bukuOnline' => $bukuOnline, + 'bukuOffline' => $bukuOffline, + 'input' => $filters + ]); + } + + /** + * Menampilkan halaman form untuk menambah buku baru. + */ + public function create() + { + return view('admin.buku.create', [ + 'pageTitle' => 'Tambah Buku Baru' + ]); + } + + public function edit($id) +{ + $buku = DummyDataService::getKatalogBuku()->firstWhere('id', (int)$id); + abort_if(!$buku, 404); + + return view('admin.buku.edit', [ + 'pageTitle' => 'Edit Buku: ' . $buku['judul'], + 'buku' => $buku + ]); +} +} \ No newline at end of file diff --git a/app/Http/Controllers/Admin/DashboardController.php b/app/Http/Controllers/Admin/DashboardController.php new file mode 100644 index 0000000..73b4dd9 --- /dev/null +++ b/app/Http/Controllers/Admin/DashboardController.php @@ -0,0 +1,23 @@ + 'Beranda', + 'user' => auth()->user(), + 'greeting' => 'Selamat Datang', + 'stats' => DummyDataService::getAdminDashboardStats(), + 'statistikBulanan' => DummyDataService::getStatistikPeminjamanAdmin(), + 'komposisiBuku' => DummyDataService::getKomposisiBukuAdmin(), + 'pengumuman' => DummyDataService::getPengumuman(), + 'aktivitasTerakhir' => DummyDataService::getAktivitasTerakhir(), + ]); + } +} diff --git a/app/Http/Controllers/Admin/MasterIndukController.php b/app/Http/Controllers/Admin/MasterIndukController.php new file mode 100644 index 0000000..ad7c415 --- /dev/null +++ b/app/Http/Controllers/Admin/MasterIndukController.php @@ -0,0 +1,31 @@ +validate([ + 'nomor_induk' => 'required|unique:master_induks,nomor_induk', + 'role' => 'required|in:siswa,guru', + 'nama_pemilik' => 'required|string', + ]); + + MasterInduk::create($request->all()); + + return back()->with('success', 'Data Induk berhasil ditambahkan. User dengan NIP/NISN ini sekarang bisa mendaftar.'); + } + + // Menghapus Data + public function destroy($id) + { + MasterInduk::findOrFail($id)->delete(); + return back()->with('success', 'Data Induk dihapus.'); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Admin/PengumumanController.php b/app/Http/Controllers/Admin/PengumumanController.php new file mode 100644 index 0000000..e5e4ac9 --- /dev/null +++ b/app/Http/Controllers/Admin/PengumumanController.php @@ -0,0 +1,48 @@ + 'Manajemen Pengumuman', + 'semuaPengumuman' => $semuaPengumuman, + ]); + } + + /** + * Menampilkan form untuk membuat pengumuman baru. + */ + public function create() + { + return view('admin.pengumuman.create', [ + 'pageTitle' => 'Buat Pengumuman Baru', + ]); + } + + /** + * Menampilkan form untuk mengedit pengumuman yang ada. + */ + public function edit($id) + { + $pengumuman = collect(DummyDataService::getPengumuman())->firstWhere('id', (int)$id); + + // Hentikan jika pengumuman tidak ditemukan + abort_if(!$pengumuman, 404); + + return view('admin.pengumuman.edit', [ + 'pageTitle' => 'Edit Pengumuman', + 'pengumuman' => $pengumuman, + ]); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Admin/UserController.php b/app/Http/Controllers/Admin/UserController.php new file mode 100644 index 0000000..8b9e6d0 --- /dev/null +++ b/app/Http/Controllers/Admin/UserController.php @@ -0,0 +1,173 @@ +has('role') && request('role') != '') { + $query->where('role', request('role')); + } + + $users = $query->paginate(10)->appends(request()->query()); + + $whitelists = MasterInduk::orderBy('created_at', 'desc')->get(); + + return view('admin.pengguna.index', [ + 'pageTitle' => 'Daftar Pengguna', + 'users' => $users, + 'whitelists' => $whitelists + ]); + } + + public function create() + { + return view('admin.pengguna.create', ['pageTitle' => 'Tambah Pengguna Baru']); + } + + public function store(Request $request) + { + $request->validate([ + 'nama_lengkap' => 'required|string|max:255', + 'email' => 'required|email|unique:users,email', + 'role' => 'required|in:siswa,guru,penjaga perpus', + 'no_hp' => 'nullable|string|max:20', + 'password' => 'required|min:6|confirmed', + 'nomor_induk' => [ + 'required', + function ($attribute, $value, $fail) use ($request) { + $label = $request->role == 'siswa' ? 'NISN' : 'NIP/NIK'; + + // Cek Nisn/Nip sudah dipakai di tabel users + $sudahDipakai = User::where('nisn', $value)->orWhere('nip', $value)->exists(); + if ($sudahDipakai) { + $fail("{$label} ini sudah digunakan oleh akun lain."); + return; + } + + if (in_array($request->role, ['siswa', 'guru'])) { + $terdaftar = MasterInduk::where('nomor_induk', $value) + ->where('role', $request->role) + ->exists(); + if (!$terdaftar) { + $fail("{$label} tidak terdaftar di data sekolah. Hubungi admin."); + } + } + }, + ], + ], [ + 'role.in' => 'Pilih role yang valid.', + 'email.unique' => 'Email sudah terdaftar.', + 'password.confirmed' => 'Konfirmasi password tidak cocok.' + ]); + + $user = new User(); + $user->name = $request->nama_lengkap; + $user->email = $request->email; + $user->role = $request->role; + $user->password = Hash::make($request->password); + $user->no_hp = $request->no_hp; + + // Validasi NISN dan NIP berdasarkan Role + if ($request->role == 'siswa') { + $user->nisn = $request->nomor_induk; + $user->kelas = $request->kelas; + $user->golongan = $request->golongan; + } else { + $user->nip = $request->nomor_induk; + } + + $user->save(); + + return redirect()->route('admin.pengguna.index')->with('success', 'Pengguna berhasil ditambahkan.'); + } + + public function edit($id) + { + $pengguna = User::findOrFail($id); + return view('admin.pengguna.edit', [ + 'pageTitle' => 'Edit Pengguna', + 'pengguna' => $pengguna, + ]); + } + + public function update(Request $request, $id) + { + $request->validate([ + 'nama_lengkap' => 'required|string|max:255', + 'email' => 'required|email|unique:users,email,' . $id, + 'role' => 'required|in:siswa,guru,penjaga perpus', + 'no_hp' => 'nullable|string|max:20', + 'password' => 'nullable|min:6|confirmed', + 'nomor_induk' => [ + 'required', + function ($attribute, $value, $fail) use ($request, $id) { + $label = $request->role == 'siswa' ? 'NISN' : 'NIP/NIK'; + + // cek nisn/nip sudah dipakai di tabel users (kecuali oleh dirinya sendiri) + $sudahDipakai = User::where(function ($query) use ($value) { + $query->where('nisn', $value)->orWhere('nip', $value); + })->where('id', '!=', $id)->exists(); + + if ($sudahDipakai) { + $fail("{$label} ini sudah digunakan oleh akun lain."); + return; + } + + if (in_array($request->role, ['siswa', 'guru'])) { + $terdaftar = MasterInduk::where('nomor_induk', $value) + ->where('role', $request->role) + ->exists(); + if (!$terdaftar) { + $fail("{$label} tidak terdaftar di data sekolah. Hubungi admin."); + } + } + }, + ], + ]); + + $user = User::findOrFail($id); + $user->name = $request->nama_lengkap; + $user->email = $request->email; + $user->role = $request->role; + $user->no_hp = $request->no_hp; + + // Jika password diisi, maka update. Jika kosong, biarkan password lama. + if ($request->filled('password')) { + $user->password = \Illuminate\Support\Facades\Hash::make($request->password); + } + + $user->nisn = null; + $user->nip = null; + $user->kelas = null; + $user->golongan = null; + + // Masukkan kembali sesuai role + if ($request->role == 'siswa') { + $user->nisn = $request->nomor_induk; + $user->kelas = $request->kelas; + $user->golongan = $request->golongan; + } else { + $user->nip = $request->nomor_induk; + } + + $user->save(); + + return redirect()->route('admin.pengguna.index')->with('success', 'Data pengguna berhasil diperbarui.'); + } + + public function destroy($id) + { + User::findOrFail($id)->delete(); + return back()->with('success', 'Pengguna berhasil dihapus.'); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Auth/AdminLoginController.php b/app/Http/Controllers/Auth/AdminLoginController.php new file mode 100644 index 0000000..3d4e140 --- /dev/null +++ b/app/Http/Controllers/Auth/AdminLoginController.php @@ -0,0 +1,26 @@ +authenticate(); + $request->session()->regenerate(); + return redirect()->route('admin.dashboard'); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Auth/AuthenticatedSessionController.php b/app/Http/Controllers/Auth/AuthenticatedSessionController.php new file mode 100644 index 0000000..e791894 --- /dev/null +++ b/app/Http/Controllers/Auth/AuthenticatedSessionController.php @@ -0,0 +1,52 @@ +query('role', 'siswa'); + + return view('auth.login', [ + 'role' => $role + ]); + } + + /** + * Handle an incoming authentication request. + */ + public function store(LoginRequest $request): RedirectResponse + { + $request->authenticate(); // Menjalankan logika di LoginRequest + $request->session()->regenerate(); + + // Karena login sudah dijamin benar, cukup arahkan ke dashboard umum + return redirect()->intended(route('dashboard')); + } + /** + * Destroy an authenticated session. + */ + public function destroy(Request $request): RedirectResponse + { + Auth::guard('web')->logout(); + + $request->session()->forget('user_data'); + + $request->session()->invalidate(); + $request->session()->regenerateToken(); + + return redirect('/'); + } +} diff --git a/app/Http/Controllers/Auth/ConfirmablePasswordController.php b/app/Http/Controllers/Auth/ConfirmablePasswordController.php new file mode 100644 index 0000000..712394a --- /dev/null +++ b/app/Http/Controllers/Auth/ConfirmablePasswordController.php @@ -0,0 +1,40 @@ +validate([ + 'email' => $request->user()->email, + 'password' => $request->password, + ])) { + throw ValidationException::withMessages([ + 'password' => __('auth.password'), + ]); + } + + $request->session()->put('auth.password_confirmed_at', time()); + + return redirect()->intended(route('dashboard', absolute: false)); + } +} diff --git a/app/Http/Controllers/Auth/EmailVerificationNotificationController.php b/app/Http/Controllers/Auth/EmailVerificationNotificationController.php new file mode 100644 index 0000000..f64fa9b --- /dev/null +++ b/app/Http/Controllers/Auth/EmailVerificationNotificationController.php @@ -0,0 +1,24 @@ +user()->hasVerifiedEmail()) { + return redirect()->intended(route('dashboard', absolute: false)); + } + + $request->user()->sendEmailVerificationNotification(); + + return back()->with('status', 'verification-link-sent'); + } +} diff --git a/app/Http/Controllers/Auth/EmailVerificationPromptController.php b/app/Http/Controllers/Auth/EmailVerificationPromptController.php new file mode 100644 index 0000000..ee3cb6f --- /dev/null +++ b/app/Http/Controllers/Auth/EmailVerificationPromptController.php @@ -0,0 +1,21 @@ +user()->hasVerifiedEmail() + ? redirect()->intended(route('dashboard', absolute: false)) + : view('auth.verify-email'); + } +} diff --git a/app/Http/Controllers/Auth/NewPasswordController.php b/app/Http/Controllers/Auth/NewPasswordController.php new file mode 100644 index 0000000..e8368bd --- /dev/null +++ b/app/Http/Controllers/Auth/NewPasswordController.php @@ -0,0 +1,62 @@ + $request]); + } + + /** + * Handle an incoming new password request. + * + * @throws \Illuminate\Validation\ValidationException + */ + public function store(Request $request): RedirectResponse + { + $request->validate([ + 'token' => ['required'], + 'email' => ['required', 'email'], + 'password' => ['required', 'confirmed', Rules\Password::defaults()], + ]); + + // Here we will attempt to reset the user's password. If it is successful we + // will update the password on an actual user model and persist it to the + // database. Otherwise we will parse the error and return the response. + $status = Password::reset( + $request->only('email', 'password', 'password_confirmation', 'token'), + function (User $user) use ($request) { + $user->forceFill([ + 'password' => Hash::make($request->password), + 'remember_token' => Str::random(60), + ])->save(); + + event(new PasswordReset($user)); + } + ); + + // If the password was successfully reset, we will redirect the user back to + // the application's home authenticated view. If there is an error we can + // redirect them back to where they came from with their error message. + return $status == Password::PASSWORD_RESET + ? redirect()->route('login')->with('status', __($status)) + : back()->withInput($request->only('email')) + ->withErrors(['email' => __($status)]); + } +} diff --git a/app/Http/Controllers/Auth/PasswordController.php b/app/Http/Controllers/Auth/PasswordController.php new file mode 100644 index 0000000..6916409 --- /dev/null +++ b/app/Http/Controllers/Auth/PasswordController.php @@ -0,0 +1,29 @@ +validateWithBag('updatePassword', [ + 'current_password' => ['required', 'current_password'], + 'password' => ['required', Password::defaults(), 'confirmed'], + ]); + + $request->user()->update([ + 'password' => Hash::make($validated['password']), + ]); + + return back()->with('status', 'password-updated'); + } +} diff --git a/app/Http/Controllers/Auth/PasswordResetLinkController.php b/app/Http/Controllers/Auth/PasswordResetLinkController.php new file mode 100644 index 0000000..bf1ebfa --- /dev/null +++ b/app/Http/Controllers/Auth/PasswordResetLinkController.php @@ -0,0 +1,44 @@ +validate([ + 'email' => ['required', 'email'], + ]); + + // We will send the password reset link to this user. Once we have attempted + // to send the link, we will examine the response then see the message we + // need to show to the user. Finally, we'll send out a proper response. + $status = Password::sendResetLink( + $request->only('email') + ); + + return $status == Password::RESET_LINK_SENT + ? back()->with('status', __($status)) + : back()->withInput($request->only('email')) + ->withErrors(['email' => __($status)]); + } +} diff --git a/app/Http/Controllers/Auth/RegisteredUserController.php b/app/Http/Controllers/Auth/RegisteredUserController.php new file mode 100644 index 0000000..0ab087a --- /dev/null +++ b/app/Http/Controllers/Auth/RegisteredUserController.php @@ -0,0 +1,75 @@ +query('role', 'siswa'); + return view('auth.register', ['role' => $role]); + } + + public function store(Request $request): RedirectResponse + { + $role = $request->input('role'); + + + $rules = [ + 'name' => ['required', 'string', 'max:255'], + 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], + 'password' => ['required', 'confirmed', Rules\Password::defaults()], + 'role' => ['required', 'in:siswa,guru'], + ]; + + + if ($role === 'siswa') { + $rules['nisn'] = ['required', 'string', 'max:255', 'unique:users,nisn']; + } else { + $rules['nip'] = ['required', 'string', 'max:255', 'unique:users,nip']; + } + + $request->validate($rules); + + + $nomorInduk = ($role === 'siswa') ? $request->nisn : $request->nip; + + $isWhitelisted = MasterInduk::where('nomor_induk', $nomorInduk) + ->where('role', $role) + ->exists(); + + if (!$isWhitelisted) { + throw ValidationException::withMessages([ + ($role === 'siswa' ? 'nisn' : 'nip') => ['Nomor induk tidak terdaftar di Data Sekolah. Hubungi petugas.'], + ]); + } + + + $user = User::create([ + 'name' => $request->name, + 'email' => $request->email, + 'password' => Hash::make($request->password), + 'role' => $role, + 'nisn' => ($role === 'siswa') ? $nomorInduk : null, + 'nip' => ($role === 'guru') ? $nomorInduk : null, + ]); + + event(new Registered($user)); + + Auth::login($user); + + return redirect()->route('dashboard'); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Auth/VerifyEmailController.php b/app/Http/Controllers/Auth/VerifyEmailController.php new file mode 100644 index 0000000..784765e --- /dev/null +++ b/app/Http/Controllers/Auth/VerifyEmailController.php @@ -0,0 +1,27 @@ +user()->hasVerifiedEmail()) { + return redirect()->intended(route('dashboard', absolute: false).'?verified=1'); + } + + if ($request->user()->markEmailAsVerified()) { + event(new Verified($request->user())); + } + + return redirect()->intended(route('dashboard', absolute: false).'?verified=1'); + } +} diff --git a/app/Http/Controllers/BacaOnlineController.php b/app/Http/Controllers/BacaOnlineController.php new file mode 100644 index 0000000..1c79587 --- /dev/null +++ b/app/Http/Controllers/BacaOnlineController.php @@ -0,0 +1,113 @@ +only(['search', 'kategori', 'tahun', 'penulis']); + $filters['tipe_akses'] = 'online'; + $semuaBuku = DummyDataService::getKatalogBuku($filters); + $filterOptions = DummyDataService::getFilterOptions(); + + return view('katalog.index', [ + 'semuaBuku' => $semuaBuku, + 'filterOptions' => $filterOptions, + 'input' => $request->query(), + 'pageTitle' => 'Baca Buku Online', + 'mode' => 'online', + ]); + } + + public function ringkasan(int $id): View + { + $book = $this->getBookOrFail($id); + + return view('katalog.ringkasan', [ + 'buku' => $book, + 'pageTitle' => 'Baca Buku Online', + 'actionRoute' => 'baca.request_code', + 'previousRoute' => 'baca.index', + 'actionButtonText' => 'Baca Sekarang', + 'actionButtonIcon' => 'bi-book-half', + ]); + } + + public function showCodeRequestPage(int $id): View + { + $book = $this->getBookOrFail($id); + $sessionKey = 'access_code_for_book_' . $id; + + if (session()->has($sessionKey)) { + $accessCode = session($sessionKey); + } else { + $accessCode = 'BCO-' . date('Ymd') . '-' . $book['id'] . '-' . Str::upper(Str::random(4)); + session([$sessionKey => $accessCode]); + } + + session(['book_verified_' . $id => false]); + + return view('baca.request_code', [ + 'book' => $book, + 'accessCode' => $accessCode + ]); + } + + public function verifyCode(Request $request, int $id): RedirectResponse + { + $request->validate(['kode_akses' => 'required|string']); + $correctCode = session('access_code_for_book_' . $id); + + if ($request->input('kode_akses') === $correctCode) { + session(['book_verified_' . $id => true]); + session()->forget('access_code_for_book_' . $id); + return redirect()->route('baca.view_book', ['id' => $id]); + } + + return back()->with('error', 'Kode akses yang Anda masukkan salah!'); + } + + public function viewBook(int $id): View|RedirectResponse + { + if (!session('book_verified_' . $id, false)) { + return redirect()->route('baca.request_code', ['id' => $id]) + ->with('error', 'Silakan masukkan kode akses terlebih dahulu.'); + } + $book = $this->getBookOrFail($id); + return view('baca.view_book', ['book' => $book]); + } + + public function streamPdf(int $id): BinaryFileResponse|Response + { + if (!session('book_verified_' . $id, false)) { + abort(403, 'Akses Ditolak.'); + } + $book = $this->getBookOrFail($id); + $filePath = 'books/' . $book['file_pdf']; + $absolutePath = storage_path('app/' . $filePath); + + if (!file_exists($absolutePath)) { + abort(404, 'GAGAL - PHP tidak dapat menemukan file di: ' . $absolutePath); + } + + return response()->file($absolutePath); + } + + private function getBookOrFail(int $id): array + { + $book = DummyDataService::getKatalogBuku()->firstWhere('id', $id); + if (!$book) { + abort(404, 'Buku tidak ditemukan.'); + } + return $book; + } +} diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php new file mode 100644 index 0000000..8677cd5 --- /dev/null +++ b/app/Http/Controllers/Controller.php @@ -0,0 +1,8 @@ +contains(function ($buku) { + return $buku['sisa_hari'] < 0; + }); + + if ($isTelat && $user->role === 'siswa') { + $user->is_banned = true; + } + + $stats = DummyDataService::getDashboardStats(); + $pengumuman = DummyDataService::getPengumuman(); + $pemberitahuan = DummyDataService::getPemberitahuan(); + $progressMembaca = DummyDataService::getProgressMembaca(); + $statistikBulanan = DummyDataService::getStatistikBulanan(); + $bukuPinjamOffline = $bukuPinjam; + $bacaBukuOnline = DummyDataService::getBacaBukuOnline($user); + $rekomendasiPembelajaran = DummyDataService::getRekomendasiPembelajaran(); + $personalNotif = DummyDataService::getNotifikasiForUser($user); + + // Cek apakah ada notifikasi denda aktif + $dendaAlert = collect($personalNotif)->where('type', 'denda_active'); + + // Menambahkan thumbnail YouTube ke setiap rekomendasi + $rekomendasiPembelajaran = $rekomendasiPembelajaran->map(function ($item) { + $videoId = $this->extractYouTubeId($item['youtube_link']); + if ($videoId) { + $item['thumbnail'] = "https://img.youtube.com/vi/{$videoId}/hqdefault.jpg"; + } else { + $item['thumbnail'] = 'https://via.placeholder.com/150?text=No+Preview'; + } + return $item; + }); + + $dendaAlert = collect($personalNotif)->where('type', 'denda_active'); + + $hour = date('H'); + $greeting = "Selamat Pagi"; + if ($hour >= 12 && $hour < 15) + $greeting = "Selamat Siang"; + elseif ($hour >= 15 && $hour < 18) + $greeting = "Selamat Sore"; + elseif ($hour >= 18) + $greeting = "Selamat Malam"; + + return view('dashboard', compact( + 'user', + 'stats', + 'pengumuman', + 'pemberitahuan', + 'dendaAlert', + 'progressMembaca', + 'statistikBulanan', + 'bukuPinjamOffline', + 'bacaBukuOnline', + 'greeting', + 'rekomendasiPembelajaran' + ))->with('notifikasi', $personalNotif); + } + + /** + * Helper function untuk mengekstrak ID video dari URL YouTube. + */ + private function extractYouTubeId(string $url): ?string + { + preg_match('/(v=|vi=|youtu.be\/|embed\/|\/v\/|\?v=|\&v=)(.+?)\b/i', $url, $matches); + return $matches[2] ?? null; + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Guru/LaporanController.php b/app/Http/Controllers/Guru/LaporanController.php new file mode 100644 index 0000000..35d3f38 --- /dev/null +++ b/app/Http/Controllers/Guru/LaporanController.php @@ -0,0 +1,24 @@ + 'Laporan Minat Baca Siswa', + 'laporan' => $laporan, + 'siswaTeraktif' => $siswaTeraktif, + 'aktivitasMingguan' => $aktivitasMingguan, + ]); + } +} diff --git a/app/Http/Controllers/KatalogController.php b/app/Http/Controllers/KatalogController.php new file mode 100644 index 0000000..af3a3e4 --- /dev/null +++ b/app/Http/Controllers/KatalogController.php @@ -0,0 +1,36 @@ +role === 'siswa') { + $bukuPinjam = DummyDataService::getBukuPinjamOffline($user); + $isTelat = collect($bukuPinjam)->contains(fn($b) => $b['sisa_hari'] < 0); + $isBannedManual = $user->is_banned ?? false; + $isBanned = $isTelat || $isBannedManual; + } + + $filters = $request->only(['search', 'kategori', 'tahun', 'penulis']); + $semuaBuku = DummyDataService::getKatalogBuku($filters); + $filterOptions = DummyDataService::getFilterOptions(); + + return view('katalog.index', [ + 'semuaBuku' => $semuaBuku, + 'filterOptions' => $filterOptions, + 'input' => $filters, + 'pageTitle' => 'Katalog Buku', + 'mode' => 'umum', + 'isBanned' => $isBanned, + ]); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/PeminjamanController.php b/app/Http/Controllers/PeminjamanController.php new file mode 100644 index 0000000..54a833a --- /dev/null +++ b/app/Http/Controllers/PeminjamanController.php @@ -0,0 +1,89 @@ +contains(function ($buku) { + return $buku['sisa_hari'] < 0; + }); + + $isBannedManual = $user->is_banned ?? false; + + if (($isTelat || $isBannedManual) && $user->role === 'siswa') { + return redirect()->route('dashboard')->with('error', 'AKSES DITOLAK: Akun Anda sedang dibekukan karena ada buku terlambat!'); + } + + $filters = $request->only(['search', 'kategori', 'tahun', 'penulis']); + $filters['tipe_akses'] = 'offline'; + $semuaBuku = DummyDataService::getKatalogBuku($filters); + $filterOptions = DummyDataService::getFilterOptions(); + + return view('katalog.index', [ + 'semuaBuku' => $semuaBuku, + 'filterOptions' => $filterOptions, + 'input' => $request->query(), + 'pageTitle' => 'Peminjaman Buku Offline', + 'mode' => 'offline', + ]); + } + + public function ringkasan($id) + { + $user = Auth::user(); + $buku = DummyDataService::getKatalogBuku()->firstWhere('id', $id); + + return view('katalog.ringkasan', [ + 'user' => $user, + 'buku' => $buku, + 'pageTitle' => 'Peminjaman Buku Offline', + 'actionRoute' => 'peminjaman.form', + 'previousRoute' => 'peminjaman.index', + 'actionButtonText' => 'Lanjutkan ke Form Peminjaman', + 'actionButtonIcon' => 'bi-file-earmark-text-fill', + ]); + } + + + public function form($id) + { + $user = Auth::user(); + $buku = DummyDataService::getKatalogBuku()->firstWhere('id', $id); + $filters = ['tipe_akses' => 'offline']; + $semuaBuku = DummyDataService::getKatalogBuku($filters); + + return view('peminjaman.form', compact('user', 'buku', 'semuaBuku')); + } + + public function store(Request $request) + { + $request->validate([ + 'buku_ids' => 'required|array|min:1|max:3', + 'buku_ids.*' => 'integer' + ]); + + $bukuIds = $request->input('buku_ids'); + + foreach ($bukuIds as $bukuId) { + // Di backend nanti kayak gini + // Peminjaman::create([ + // 'user_id' => auth()->id(), + // 'book_id' => $bukuId, + // 'tanggal_pinjam' => now(), + // 'tanggal_kembali' => now()->addDays(7), + // 'status' => 'dipinjam' + // ]); + } + + return redirect()->route('dashboard') + ->with('success', 'Berhasil meminjam ' . count($bukuIds) . ' buku!'); + } +} diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php new file mode 100644 index 0000000..69654d5 --- /dev/null +++ b/app/Http/Controllers/ProfileController.php @@ -0,0 +1,98 @@ +user(); + + $viewData = ['user' => $user]; + + if ($user->role === 'penjaga perpus') { + $viewData['statistik'] = DummyDataService::getAdminDashboardStats(); + $viewData['aktivitasTerakhir'] = DummyDataService::getAktivitasTerakhir(); + + } elseif ($user->role === 'guru') { + $viewData['bukuOffline'] = DummyDataService::getBukuPinjamOffline($user); + $viewData['bukuOnline'] = DummyDataService::getBacaBukuOnline($user); + $viewData['laporan'] = DummyDataService::getLaporanMinatBaca(); + + } else { + $viewData['bukuOffline'] = DummyDataService::getBukuPinjamOffline($user); + $viewData['bukuOnline'] = DummyDataService::getBacaBukuOnline($user); + $viewData['statistik'] = DummyDataService::getDashboardStats(); + } + + return view('profile.index', $viewData); + } + + /** + * Tampilkan form edit profil. + */ + public function edit(Request $request): View + { + return view('profile.edit', [ + 'user' => $request->user(), + ]); + } + + /** + * Update data profil ke Database MySQL. + */ + public function update(Request $request): RedirectResponse + { + $request->validate([ + 'name' => ['required', 'string', 'max:255'], + 'email' => ['required', 'string', 'email', 'max:255', 'unique:users,email,'.Auth::id()], + 'no_hp' => ['nullable', 'string', 'max:15'], + ]); + + $user = $request->user(); + $user->name = $request->name; + $user->email = $request->email; + $user->no_hp = $request->no_hp; + + if ($user->isDirty('email')) { + $user->email_verified_at = null; + } + + $user->save(); + + return Redirect::route('profile.edit')->with('status', 'profile-updated'); + } + + /** + * Hapus akun user. + */ + public function destroy(Request $request): RedirectResponse + { + $request->validateWithBag('userDeletion', [ + 'password' => ['required', 'current_password'], + ]); + + $user = $request->user(); + + Auth::logout(); + + $user->delete(); + + $request->session()->invalidate(); + $request->session()->regenerateToken(); + + return Redirect::to('/'); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/RekomendasiController.php b/app/Http/Controllers/RekomendasiController.php new file mode 100644 index 0000000..6d91141 --- /dev/null +++ b/app/Http/Controllers/RekomendasiController.php @@ -0,0 +1,36 @@ +firstWhere('id', (int)$id); + abort_if(!$rekomendasi, 404); + + // Menambahkan thumbnail YouTube ke setiap rekomendasi + $embedLink = null; + $videoId = $this->extractYouTubeId($rekomendasi['youtube_link']); + if ($videoId) { + $embedLink = "https://www.youtube.com/embed/" . $videoId; + } + $rekomendasi['youtube_embed_link'] = $embedLink; + + return view('rekomendasiShow', [ + 'pageTitle' => $rekomendasi['judul'], + 'rekomendasi' => $rekomendasi, + ]); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/RiwayatController.php b/app/Http/Controllers/RiwayatController.php new file mode 100644 index 0000000..92fc019 --- /dev/null +++ b/app/Http/Controllers/RiwayatController.php @@ -0,0 +1,49 @@ + 1]; + + $dataOffline = DummyDataService::getRiwayatOffline($user); + + $riwayatOffline = collect($dataOffline) + ->sortBy([ + ['status', 'asc'], + ['tanggal_pinjam', 'desc'] + ]) + ->values() + ->all(); + + return view('riwayat.offline', [ + 'pageTitle' => 'Riwayat Peminjaman Offline', + 'riwayatOffline' => $riwayatOffline, + ]); + } + + public function onlineIndex() + { + $dataOnline = DummyDataService::getRiwayatOnline(); + + $riwayatOnline = collect($dataOnline) + ->sortBy([ + ['status', 'asc'], + ['tanggal_baca', 'desc'] + ]) + ->values() + ->all(); + + return view('riwayat.online', [ + 'pageTitle' => 'Riwayat Baca Online', + 'riwayatOnline' => $riwayatOnline, + ]); + } +} \ No newline at end of file diff --git a/app/Http/Middleware/CheckRole.php b/app/Http/Middleware/CheckRole.php new file mode 100644 index 0000000..c4953a6 --- /dev/null +++ b/app/Http/Middleware/CheckRole.php @@ -0,0 +1,21 @@ +role, $roles)) { + return redirect()->route('login') + ->with('error', 'Akses ditolak. Anda tidak memiliki izin untuk mengakses halaman tersebut.'); + } + + return $next($request); + } +} \ No newline at end of file diff --git a/app/Http/Requests/Auth/LoginRequest.php b/app/Http/Requests/Auth/LoginRequest.php new file mode 100644 index 0000000..b3bca95 --- /dev/null +++ b/app/Http/Requests/Auth/LoginRequest.php @@ -0,0 +1,86 @@ + ['required', 'string'], + ]; + } + + public function authenticate(): void + { + $this->ensureIsNotRateLimited(); + + $loginString = $this->input('email') ?? $this->input('nisn') ?? $this->input('nip'); + + $password = $this->input('password'); + + if (!$loginString) { + throw ValidationException::withMessages([ + 'email' => 'Mohon masukkan NISN, NIP, atau Email.', + ]); + } + + if (Auth::attempt(['nisn' => $loginString, 'password' => $password], $this->boolean('remember'))) { + RateLimiter::clear($this->throttleKey()); + return; + } + + if (Auth::attempt(['nip' => $loginString, 'password' => $password], $this->boolean('remember'))) { + RateLimiter::clear($this->throttleKey()); + return; + } + + if (Auth::attempt(['email' => $loginString, 'password' => $password], $this->boolean('remember'))) { + RateLimiter::clear($this->throttleKey()); + return; + } + + RateLimiter::hit($this->throttleKey()); + + $fieldError = $this->input('nisn') ? 'nisn' : ($this->input('nip') ? 'nip' : 'email'); + + throw ValidationException::withMessages([ + $fieldError => trans('auth.failed'), + ]); + } + + public function ensureIsNotRateLimited(): void + { + if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) { + return; + } + + event(new Lockout($this)); + $seconds = RateLimiter::availableIn($this->throttleKey()); + + throw ValidationException::withMessages([ + 'email' => trans('auth.throttle', [ + 'seconds' => $seconds, + 'minutes' => ceil($seconds / 60), + ]), + ]); + } + + public function throttleKey(): string + { + $field = $this->input('email') ?? $this->input('nisn') ?? $this->input('nip') ?? 'unknown'; + return Str::transliterate(Str::lower($field).'|'.$this->ip()); + } +} \ No newline at end of file diff --git a/app/Http/Requests/ProfileUpdateRequest.php b/app/Http/Requests/ProfileUpdateRequest.php new file mode 100644 index 0000000..3622a8f --- /dev/null +++ b/app/Http/Requests/ProfileUpdateRequest.php @@ -0,0 +1,30 @@ +|string> + */ + public function rules(): array + { + return [ + 'name' => ['required', 'string', 'max:255'], + 'email' => [ + 'required', + 'string', + 'lowercase', + 'email', + 'max:255', + Rule::unique(User::class)->ignore($this->user()->id), + ], + ]; + } +} diff --git a/app/Models/MasterInduk.php b/app/Models/MasterInduk.php new file mode 100644 index 0000000..316593b --- /dev/null +++ b/app/Models/MasterInduk.php @@ -0,0 +1,12 @@ + */ + use HasFactory, Notifiable; + + /** + * The attributes that are mass assignable. + * + * @var list + */ + protected $fillable = [ + 'name', + 'email', + 'password', + 'role', + 'nisn', + 'nip', + 'no_hp', + 'kelas', + 'nomor_induk' + ]; + + /** + * The attributes that should be hidden for serialization. + * + * @var list + */ + protected $hidden = [ + 'password', + 'remember_token', + ]; + + /** + * Get the attributes that should be cast. + * + * @return array + */ + protected function casts(): array + { + return [ + 'email_verified_at' => 'datetime', + 'password' => 'hashed', + ]; + } + + public function getNamaLengkapAttribute() + { + return $this->name; + } +} diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php new file mode 100644 index 0000000..a9e04f9 --- /dev/null +++ b/app/Providers/AppServiceProvider.php @@ -0,0 +1,44 @@ +app->environment('production')) { + URL::forceScheme('https'); + } + + // View Composer untuk semua view (*) + View::composer('*', function ($view) { + if (Auth::check()) { + $user = Auth::user(); + $notifikasi = collect(DummyDataService::getNotifikasiForUser($user)); + $unreadCount = $notifikasi->where('read', false)->count(); + $view->with('notifikasi', $notifikasi); + $view->with('unreadNotificationsCount', $unreadCount); + } else { + $view->with('notifikasi', collect([])); + $view->with('unreadNotificationsCount', 0); + } + }); + } +} diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php new file mode 100644 index 0000000..b41e66c --- /dev/null +++ b/app/Providers/AuthServiceProvider.php @@ -0,0 +1,32 @@ +registerPolicies(); // Laravel 10/11 biasanya auto-discovery + + // HAPUS atau KOMENTARI bagian ini: + /* + Auth::provider('dummy', function ($app, array $config) { + return new DummyUserProvider(); + }); + */ + } +} \ No newline at end of file diff --git a/app/Services/DummyDataService.php b/app/Services/DummyDataService.php new file mode 100644 index 0000000..4ead6c1 --- /dev/null +++ b/app/Services/DummyDataService.php @@ -0,0 +1,770 @@ + 1, + 'nisn' => '1234567890', + 'nama_lengkap' => 'Silvi Rahmawati', + 'email' => 'silvi.rahmawati@smkn1perpus.sch.id', + 'nomor_hp' => '08123456789', + 'password' => 'password', + 'role' => 'siswa', + 'kelas' => 'XII RPL', + 'golongan' => 'A', + 'is_banned' => false, + ], + [ + 'id' => 2, + 'nama_lengkap' => 'Budi Santoso', + 'nip' => '197812312005011', + 'email' => 'budi.santoso@smkn1perpus.sch.id', + 'password' => 'password', + 'role' => 'penjaga perpus', + ], + [ + 'id' => 3, + 'nisn' => '9988776655', + 'nama_lengkap' => 'Siti Nurhaliza', + 'email' => 'siti.nurhaliza@smkn1perpus.sch.id', + 'nomor_hp' => '081998877665', + 'password' => 'password', + 'role' => 'siswa', + 'kelas' => 'XII RPL A', + 'golongan' => 'A', + 'is_banned' => true, + ], + + [ + 'id' => 4, + 'nisn' => '5566778899', + 'nama_lengkap' => 'Andi Pratama', + 'email' => 'andi.pratama@smkn1perpus.sch.id', + 'nomor_hp' => '081556677889', + 'password' => 'password', + 'role' => 'siswa', + 'kelas' => 'XII RPL A', + 'golongan' => 'A', + 'is_banned' => false, + ], + [ + 'id' => 5, + 'nama_lengkap' => 'Rina Marlina', + 'nip' => '198506152010012', + 'email' => 'rina.marlina@smkn1perpus.sch.id', + 'password' => 'password', + 'role' => 'guru', + 'is_banned' => false, + ], + ]; + } + + /** + * Data dummy untuk grafik aktivitas membaca mingguan di laporan guru. + */ + public static function getAktivitasMingguan(): array + { + return [ + 'labels' => ['Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu', 'Minggu'], + 'data' => [15, 22, 18, 25, 20, 30, 28], + ]; + } + + /** + * Data dummy untuk tabel peminjaman aktif di dashboard admin. + */ + public static function getAdminPeminjamanAktif(): \Illuminate\Support\Collection + { + $allBooks = self::getAllBooks(); + $allSiswa = collect(self::getAllSiswa()); + $bukuDipinjam = $allBooks->whereIn('status', ['Dipinjam', 'Terlambat']); + $grouped = $bukuDipinjam->groupBy(function ($item) { + return is_array($item['user_id']) ? $item['user_id'][0] : $item['user_id']; + }); + + return $grouped->map(function ($books, $userId) use ($allSiswa) { + $siswa = $allSiswa->firstWhere('id', $userId); + $firstBook = $books->first(); + $tglKembali = Carbon::now()->addDays($firstBook['sisa_hari']); + + return [ + 'id_peminjaman' => 'PIN-ADM-' . sprintf('%03d', $userId), + 'user_id' => $userId, + 'role' => $siswa ? $siswa['role'] : 'siswa', + 'is_banned' => $siswa ? ($siswa['is_banned'] ?? false) : false, + + 'peminjam' => $siswa ? $siswa['nama_lengkap'] : 'User Tidak Dikenal', + 'nomor_hp' => $siswa ? ($siswa['nomor_hp'] ?? '-') : '-', + 'tanggal_pinjam' => Carbon::now()->subDays(7), + 'tenggat_kembali' => $tglKembali, + 'denda_per_hari' => 1000, + + 'books' => $books->map(function ($b) { + return [ + 'id' => $b['id'], + 'judul' => $b['judul'], + 'cover' => $b['cover'] + ]; + })->toArray() + ]; + })->values(); + } + + /** + *Data Dummy untuk fitur Rekomendasi Pembelajaran. + */ + public static function getRekomendasiPembelajaran(): \Illuminate\Support\Collection + { + return collect([ + [ + 'id' => 1, + 'judul' => 'Sistem Tata Surya - Rangkuman Materi IPA Terpadu', + 'kategori' => 'IPA', + 'youtube_link' => 'https://www.youtube.com/watch?v=libKVRa01L8', + 'deskripsi' => '

Video animasi seru yang menjelaskan tentang planet-planet di tata surya kita...

', + ], + [ + 'id' => 2, + 'judul' => 'Macam-macam Zat dan Perubahannya - IPA Kelas 7', + 'kategori' => 'IPA', + 'youtube_link' => 'https://www.youtube.com/watch?v=CfwPsKdC5w8', + 'deskripsi' => '

Zat (materi) adalah sesuatu yang menempati ruang dan mempunyai massa...

', + ], + [ + 'id' => 3, + 'judul' => 'Sejarah Kerajaan Majapahit, Kerajaan Terbesar di Nusantara', + 'kategori' => 'IPS', + 'youtube_link' => 'https://www.youtube.com/watch?v=2Z9hqVqPY_s', + 'deskripsi' => '

Pelajari sejarah salah satu kerajaan terbesar di Indonesia...

', + ], + [ + 'id' => 4, + 'judul' => 'Belajar HTML dari NOL untuk Pemula', + 'kategori' => 'Informatika', + 'youtube_link' => 'https://www.youtube.com/watch?v=NBZ9Ro6UKV8', + 'deskripsi' => '

Ingin belajar membuat website? Mulai dari sini!...

', + ], + [ + 'id' => 5, + 'judul' => 'Rumus Cepat Teorema Pythagoras', + 'kategori' => 'Matematika', + 'youtube_link' => 'https://youtu.be/JJaptwjRbxc?si=XRxkrAf5G76iJ5CG', + 'deskripsi' => '

Jangan takut lagi dengan soal Pythagoras!...

', + ], + [ + 'id' => 6, + 'judul' => 'Cara Menggambar Perspektif 1 Titik Hilang', + 'kategori' => 'Seni Budaya', + 'youtube_link' => 'https://youtu.be/SS7dLGDWUSs?si=lVw8jBkaWT---7ch', + 'deskripsi' => '

Buat gambarmu terlihat lebih hidup dan realistis!...

', + ], + [ + 'id' => 7, + 'judul' => 'Sistem Peredaran Darah pada Manusia', + 'kategori' => 'IPA', + 'youtube_link' => 'https://youtu.be/QLoqMruGbkc?si=KiP5VZ4ByKSdFJK9', + 'deskripsi' => '

Pahami bagaimana jantung memompa darah ke seluruh tubuh...

', + ], + [ + 'id' => 8, + 'judul' => 'Unsur-Unsur Intrinsik Cerpen', + 'kategori' => 'Bahasa Indonesia', + 'youtube_link' => 'https://youtu.be/PQNuvyQZYvI?si=Lr9AeTO_k6vY21ei', + 'deskripsi' => '

Analisis sebuah cerita pendek menjadi lebih mudah...

', + ], + [ + 'id' => 9, + 'judul' => 'Apa itu Pemanasan Global?', + 'kategori' => 'IPS', + 'youtube_link' => 'https://youtu.be/pVjXm340tbw?si=GeMhYK1FSOGtV86X', + 'deskripsi' => '

Mengapa suhu bumi semakin panas? Pelajari tentang penyebabnya...

', + ], + [ + 'id' => 10, + 'judul' => 'APA ITU LUBANG HITAM?', + 'kategori' => 'Sains', + 'youtube_link' => 'https://youtu.be/Tx87wEaDtxo?si=fNORkTYOeLiH9_xh', + 'deskripsi' => '

Jelajahi salah satu objek paling misterius di alam semesta...

', + ], + ]); + } + + /** + * Data dummy untuk menampilkan 10 siswa paling aktif di laporan guru. + */ + public static function getSiswaTeraktif(): array + { + return [ + ['nama' => 'Silvi Rahmawati', 'total_buku' => 45, 'kelas' => 'XII RPL'], + ['nama' => 'Siti Nurhaliza', 'total_buku' => 33, 'kelas' => 'XII RPL A'], + ['nama' => 'Andi Pratama', 'total_buku' => 30, 'kelas' => 'XII RPL B'], + ['nama' => 'John Wick', 'total_buku' => 28, 'kelas' => 'XI TKJ'], + ['nama' => 'Dewi Lestari', 'total_buku' => 25, 'kelas' => 'XII AKL'], + ['nama' => 'Eko Prasetyo', 'total_buku' => 22, 'kelas' => 'XI MM'], + ['nama' => 'Rina Marlina', 'total_buku' => 20, 'kelas' => 'XII TKJ A'], + ['nama' => 'Budi Santoso', 'total_buku' => 18, 'kelas' => 'X OTKP'], + ['nama' => 'Putri Amelia', 'total_buku' => 16, 'kelas' => 'XI RPL C'], + ['nama' => 'Ahmad Jono', 'total_buku' => 12, 'kelas' => 'X TKJ B'], + ]; + } + + /** + * Data dummy untuk halaman Laporan Minat Baca khusus Guru. + */ + public static function getLaporanMinatBaca(): array + { + return [ + 'buku_terpopuler' => [ + ['judul' => 'Modul Ajar IPAS', 'penulis' => 'Tim Kemdikbud Ristek', 'total_pembaca' => 125, 'cover' => 'images/covers/ipas.jpg'], + ['judul' => 'Ayah', 'penulis' => 'Andrea Hirata', 'total_pembaca' => 98, 'cover' => 'images/covers/ayah.png'], + ['judul' => 'Si Anak Pintar', 'penulis' => 'Tere Liye', 'total_pembaca' => 92, 'cover' => 'images/covers/sianakpintar.jpg'], + ], + 'kategori_populer' => [ + ['nama' => 'Sains', 'total_pembaca' => 230, 'trend' => 'naik', 'icon' => 'bi-arrow-up-right'], + ['nama' => 'Fiksi', 'total_pembaca' => 190, 'trend' => 'stabil', 'icon' => 'bi-arrow-right'], + ['nama' => 'Pendidikan', 'total_pembaca' => 150, 'trend' => 'turun', 'icon' => 'bi-arrow-down-right'], + ['nama' => 'Novel', 'total_pembaca' => 110, 'trend' => 'naik', 'icon' => 'bi-arrow-up-right'], + ], + 'insight' => 'Siswa menunjukkan minat baca tertinggi pada kategori Sains dan Fiksi. Buku-buku karangan Tere Liye dan Andrea Hirata masih menjadi favorit.', + ]; + } + + /** + * Data dummy untuk Halaman Dashboard Statistik Petugas Perpus + */ + public static function getAdminDashboardStats(): array + { + $allBooks = self::getAllBooks(); + $allUsers = self::getAllSiswa(); + $bukuDipinjam = $allBooks->filter(fn($buku) => $buku['status'] === 'Dipinjam')->count(); + return [ + ['label' => 'Total Buku', 'value' => $allBooks->count(), 'icon' => 'bi-journal-bookmark-fill', 'color' => 'primary'], + ['label' => 'Total Anggota', 'value' => count($allUsers), 'icon' => 'bi-people-fill', 'color' => 'success'], + ['label' => 'Buku Dipinjam', 'value' => $bukuDipinjam, 'icon' => 'bi-arrow-up-right-circle-fill', 'color' => 'warning'], + ['label' => 'Denda Menunggu', 'value' => 0, 'icon' => 'bi-cash-coin', 'color' => 'danger'], + ]; + } + + /** + * Data untuk bar chart di dashboard admin (total peminjaman per bulan). + */ + public static function getStatistikPeminjamanAdmin(): array + { + return [ + 'labels' => ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul'], + 'data' => [65, 59, 80, 81, 56, 55, 70], + ]; + } + + /** + * Data untuk donut chart di dashboard admin (komposisi buku). + */ + public static function getKomposisiBukuAdmin(): array + { + $allBooks = self::getAllBooks(); + return [ + 'tersedia' => $allBooks->where('status', 'Tersedia')->count(), + 'dipinjam' => $allBooks->where('status', 'Dipinjam')->count(), + ]; + } + + /** + * Data untuk tabel aktivitas terakhir di dashboard admin. + */ + public static function getAktivitasTerakhir(): array + { + return [ + ['nama' => 'Silvi Rahmawati', 'judul_buku' => 'Perahu Kertas', 'tipe' => 'Peminjaman', 'waktu' => '5 menit yang lalu', 'status' => 'Dipinjam'], + ['nama' => 'Andi Pratama', 'judul_buku' => 'The Last Spell Breather', 'tipe' => 'Pengembalian', 'waktu' => '1 jam yang lalu', 'status' => 'Dikembalikan'], + ['nama' => 'Siti Nurhaliza', 'judul_buku' => 'Ayah', 'tipe' => 'Baca Online', 'waktu' => '3 jam yang lalu', 'status' => 'Selesai'], + ['nama' => 'Rina Marlina', 'judul_buku' => 'Modul Ajar IPAS', 'tipe' => 'Peminjaman', 'waktu' => 'Kemarin', 'status' => 'Dipinjam'], + ]; + } + /** + * Data untuk halaman Dashboard Siswa dan Guru dengan warna spesifik. + */ + public static function getDashboardStats(): array + { + return [ + ['label' => 'Buku yang dipinjam', 'value' => 3, 'icon' => 'bi-book-half', 'color' => 'primary'], + + + ['label' => 'Tenggat Waktu', 'value' => '2', 'icon' => 'bi-clock-history', 'color' => 'danger'], + + + ['label' => 'Buku dikembalikan', 'value' => 12, 'icon' => 'bi-check-circle', 'color' => 'success'], + + + ['label' => 'History Baca', 'value' => 15, 'icon' => 'bi-hourglass-split', 'color' => 'warning'], + ]; + } + + /** + * Data untuk pengumuman + */ + public static function getPengumuman(): array + { + $pengumuman = [ + ['id' => 1, 'type' => 'warning', 'icon' => 'bi-exclamation-triangle-fill', 'title' => 'Perpustakaan Tutup', 'content' => 'Perpustakaan akan tutup pada tanggal 25 Desember untuk perayaan Natal.'], + ['id' => 2, 'type' => 'info', 'icon' => 'bi-info-circle-fill', 'title' => 'Buku Baru Tersedia', 'content' => 'Edisi baru telah ditambahkan ke koleksi perpustakaan digital.'], + ]; + + // Buat 30 data dummy tambahan dengan 'id' + for ($i = 3; $i <= 32; $i++) { + $pengumuman[] = ['id' => $i, 'type' => 'secondary', 'icon' => 'bi-megaphone-fill', 'title' => "Pengumuman Biasa #{$i}", 'content' => "Ini adalah isi dari pengumuman rutin nomor {$i}."]; + } + + return $pengumuman; + } + + /** + * Data untuk pemberitahuan + */ + public static function getPemberitahuan(): array + { + $pemberitahuan = [ + ['type' => 'danger', 'icon' => 'bi-exclamation-octagon', 'title' => 'Buku Akan Jatuh Tempo Besok', 'content' => 'Sejarah Indonesia Modern', 'badge' => 'Segera!'], + ['type' => 'success', 'icon' => 'bi-check2-circle', 'title' => 'Peminjaman Berhasil', 'content' => 'Buku Kimia Dasar Berhasil Dipinjam', 'badge' => 'Baru'], + ]; + + // Buat 20 data dummy tambahan + for ($i = 1; $i <= 20; $i++) { + $pemberitahuan[] = ['type' => 'info', 'icon' => 'bi-bell-fill', 'title' => "Notifikasi Sistem #{$i}", 'content' => "Pemberitahuan sistem terjadwal nomor {$i}.", 'badge' => 'Info']; + } + + return $pemberitahuan; + } + + /** + * Data untuk progress membaca (donut chart) + */ + public static function getProgressMembaca(): array + { + return ['selesai' => 70, 'sisa' => 30]; + } + + /** + * Data untuk statistik bulanan (bar chart) + */ + public static function getStatistikBulanan(): array + { + return [ + 'labels' => ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul'], + 'data' => [10, 15, 8, 20, 18, 25, 22], + ]; + } + + /** + * Master list untuk semua buku + * @return \Illuminate\Support\Collection + */ + public static function getAllBooks() + { + return collect([ + // --- BUKU MILIK USER 1 (SILVI) --- + [ + 'id' => 1, + 'judul' => 'Modul Ajar IPAS', + 'penulis' => 'Tim Kemdikbud Ristek', + 'cover' => 'images/covers/ipas.jpg', + 'kode_buku' => '510', + 'kategori' => 'Sains', + 'tahun' => 2022, + 'status' => 'Dipinjam', + 'is_new' => true, + 'tipe_akses' => ['online', 'offline'], + 'sisa_hari' => -5, + 'user_id' => 1, + ], + [ + 'id' => 2, + 'judul' => 'Perahu Kertas', + 'penulis' => 'Dewi Lestari', + 'cover' => 'images/covers/ayah.png', + 'kode_buku' => '844', + 'kategori' => 'Fiksi', + 'tahun' => 2012, + 'status' => 'Dipinjam', + 'is_new' => false, + 'tipe_akses' => 'offline', + 'sisa_hari' => 3, + 'user_id' => 1, + ], + + // --- BUKU TERSEDIA (UNTUK CEK PEMINJAMAN BARU) --- + [ + 'id' => 3, + 'judul' => 'Si Anak Pintar', + 'penulis' => 'Tere Liye', + 'cover' => 'images/covers/sianakpintar.jpg', + 'kode_buku' => '843', + 'kategori' => 'Fiksi', + 'tahun' => 2018, + 'status' => 'Tersedia', + 'is_new' => true, + 'tipe_akses' => 'offline', + 'sisa_hari' => 0, + 'user_id' => null, + ], + [ + 'id' => 4, + 'judul' => 'Laskar Pelangi', + 'penulis' => 'Andrea Hirata', + 'cover' => 'https://upload.wikimedia.org/wikipedia/id/8/8e/Laskar_pelangi_sampul.jpg', + 'kode_buku' => 'NOV-001', + 'kategori' => 'Novel', + 'tahun' => 2005, + 'status' => 'Tersedia', + 'is_new' => false, + 'tipe_akses' => 'offline', + 'sisa_hari' => 0, + 'user_id' => null, + ], + [ + 'id' => 5, + 'judul' => 'Filosofi Teras', + 'penulis' => 'Henry Manampiring', + 'cover' => 'https://upload.wikimedia.org/wikipedia/id/3/36/Filosofi_Teras.jpg', + 'kode_buku' => 'PSI-002', + 'kategori' => 'Psikologi', + 'tahun' => 2018, + 'status' => 'Tersedia', + 'is_new' => true, + 'tipe_akses' => 'offline', + 'sisa_hari' => 0, + 'user_id' => null, + ], + [ + 'id' => 6, + 'judul' => 'Atomic Habits', + 'penulis' => 'James Clear', + 'cover' => 'https://images-na.ssl-images-amazon.com/images/I/91bYsX41DVL.jpg', + 'kode_buku' => 'SELF-003', + 'kategori' => 'Refleksi Diri', + 'tahun' => 2018, + 'status' => 'Tersedia', + 'is_new' => true, + 'tipe_akses' => ['offline', 'online'], + 'sisa_hari' => 0, + 'user_id' => null, + ], + [ + 'id' => 7, + 'judul' => 'Bumi Manusia', + 'penulis' => 'Pramoedya Ananta Toer', + 'cover' => 'https://upload.wikimedia.org/wikipedia/id/4/44/Bumi_Manusia.jpg', + 'kode_buku' => 'SAS-004', + 'kategori' => 'Sastra', + 'tahun' => 1980, + 'status' => 'Tersedia', + 'is_new' => false, + 'tipe_akses' => 'offline', + 'sisa_hari' => 0, + 'user_id' => null, + ], + [ + 'id' => 8, + 'judul' => 'Laut Bercerita', + 'penulis' => 'Leila S. Chudori', + 'cover' => 'https://upload.wikimedia.org/wikipedia/id/6/6d/Laut_Bercerita.jpeg', + 'kode_buku' => 'NOV-005', + 'kategori' => 'Novel', + 'tahun' => 2017, + 'status' => 'Tersedia', + 'is_new' => true, + 'tipe_akses' => 'offline', + 'sisa_hari' => 0, + 'user_id' => null, + ], + // --- BUKU MILIK USER 3 (SITI) - TELAT --- + [ + 'id' => 99, + 'judul' => 'Seni Berbicara', + 'penulis' => 'Larry King', + 'cover' => 'https://via.placeholder.com/150', + 'kode_buku' => 'COM-001', + 'kategori' => 'Refleksi Diri', + 'tahun' => 2019, + 'status' => 'Dipinjam', + 'is_new' => false, + 'tipe_akses' => 'offline', + 'sisa_hari' => -2, + 'user_id' => 3, + ], + + // --- BUKU MILIK GURU (USER 5) - TESTING MANUAL BAN --- + [ + 'id' => 88, + 'judul' => 'Strategi Pembelajaran Abad 21', + 'penulis' => 'Prof. Dr. Pendidikan', + 'cover' => 'https://via.placeholder.com/150', + 'kode_buku' => 'GURU-001', + 'kategori' => 'Pendidikan', + 'tahun' => 2020, + 'status' => 'Dipinjam', + 'is_new' => false, + 'tipe_akses' => 'offline', + 'sisa_hari' => -3, + 'user_id' => 5, + ], + ]); + } + + + /** + * Data untuk buku pinjam offline + */ + public static function getBukuPinjamOffline($user): array + { + return self::getAllBooks() + ->filter(function ($buku) { + // Handle tipe akses string atau array + if (is_array($buku['tipe_akses'])) { + return in_array('offline', $buku['tipe_akses']); + } + return $buku['tipe_akses'] === 'offline'; + }) + ->filter(function ($buku) use ($user) { + if (!isset($buku['user_id']) || $buku['user_id'] === null) + return false; + + if (is_array($buku['user_id'])) { + return in_array($user->id, $buku['user_id']); + } + return $buku['user_id'] == $user->id; + }) + ->map(fn($buku) => [ + 'judul' => $buku['judul'], + 'penulis' => $buku['penulis'], + 'sisa_hari' => $buku['sisa_hari'], + 'cover' => $buku['cover'], + ]) + ->values() + ->all(); + } + + /** + * Data untuk baca buku online + */ + public static function getBacaBukuOnline($user): array + { + return self::getAllBooks() + ->where('tipe_akses', 'online') + ->filter(function ($buku) use ($user) { + if (!isset($buku['user_id'])) + return false; + + if (is_array($buku['user_id'])) { + return in_array($user->id, $buku['user_id']); + } + return $buku['user_id'] == $user->id; + }) + ->map(fn($buku) => [ + 'judul' => $buku['judul'], + 'penulis' => $buku['penulis'], + 'progress' => $buku['progress'], + 'cover' => $buku['cover'], + ]) + ->values() + ->all(); + } + + /** + * Mengambil daftar buku untuk katalog dengan filter. + */ + + public static function getKatalogBuku(array $filters = []): \Illuminate\Support\Collection + { + $buku = self::getAllBooks(); + + $buku = $buku->when($filters['search'] ?? null, function ($query, $search) { + return $query->filter(fn($item) => str_contains(strtolower($item['judul']), strtolower($search))); + })->when($filters['kategori'] ?? null, function ($query, $kategori) { + return $query->where('kategori', $kategori); + })->when($filters['tahun'] ?? null, function ($query, $tahun) { + return $query->where('tahun', $tahun); + })->when($filters['penulis'] ?? null, function ($query, $penulis) { + return $query->where('penulis', $penulis); + }) + ->when($filters['tipe_akses'] ?? null, function ($query, $tipe) { + if ($tipe === 'offline') { + return $query->filter(function ($buku) { + return $buku['tipe_akses'] === 'offline' || (is_array($buku['tipe_akses']) && in_array('offline', $buku['tipe_akses'])); + }); + } + if ($tipe === 'online') { + return $query->filter(function ($buku) { + return $buku['tipe_akses'] === 'online' || (is_array($buku['tipe_akses']) && in_array('online', $buku['tipe_akses'])); + }); + } + return $query; + }) + ->sortByDesc('status'); + + return $buku; + } + + /** + * Method baru untuk mengambil daftar unik untuk dropdown filter + */ + public static function getFilterOptions(): array + { + $buku = self::getAllBooks(); + return [ + 'kategori' => $buku->pluck('kategori')->unique()->sort()->values(), + 'tahun' => $buku->pluck('tahun')->unique()->sortDesc()->values(), + 'penulis' => $buku->pluck('penulis')->unique()->sort()->values(), + ]; + } + + /** + * Data untuk riwayat peminjaman offline. + * Setiap item mewakili satu transaksi peminjaman. + */ + public static function getRiwayatOffline($user): array + { + $allBooks = self::getAllBooks(); + $myBooks = $allBooks->filter(function ($buku) use ($user) { + if (is_array($buku['user_id'])) { + return in_array($user->id, $buku['user_id']); + } + return $buku['user_id'] == $user->id; + })->whereIn('status', ['Dipinjam', 'Dikembalikan', 'Terlambat']); + + // Mapping ke format tampilan View + return $myBooks->map(function ($buku, $index) { + + // Logika Tanggal Dummy + $tglPinjam = Carbon::now()->subDays(7); + + // Hitung tanggal kembali berdasarkan sisa hari di Master Data + $tglKembali = Carbon::now()->addDays($buku['sisa_hari']); + + return [ + 'id' => $index + 1, + 'id_peminjaman' => 'PIN-' . date('Ym') . '-' . sprintf('%03d', $buku['id']), + 'kode_buku' => $buku['kode_buku'], + 'judul_utama' => $buku['judul'], + 'tanggal_pinjam' => $tglPinjam->format('d/m/Y'), + 'tanggal_kembali' => $tglKembali->format('d/m/Y'), + 'status' => $buku['status'], + 'books' => [ + [ + 'id' => $buku['id'], + 'judul' => $buku['judul'], + 'kode_buku' => $buku['kode_buku'], + 'cover' => $buku['cover'], + 'deskripsi' => 'Deskripsi buku ' . $buku['judul'], + 'kategori' => $buku['kategori'], + 'tahun' => $buku['tahun'], + 'keterangan' => ($buku['sisa_hari'] < 0) ? 'Buku Terlambat' : null, + ] + ] + ]; + })->values()->toArray(); + } + + /** + * Data untuk riwayat baca buku online. + */ + public static function getRiwayatOnline(): array + { + return [ + [ + 'id' => 1, + 'id_baca' => 'BCO-20240527-002', + 'judul_buku' => 'Ayah', + 'tanggal_akses' => '27/05/2024', + 'status' => 'Selesai', + 'books' => [ + [ + 'id' => 9, + 'judul' => 'Ayah', + 'cover' => 'images/covers/ayah.png', + 'deskripsi' => 'Novel yang mengisahkan perjuangan dan kasih sayang seorang ayah.', + 'kategori' => 'Novel', + 'tahun' => 2015, + 'keterangan' => null + ] + ] + ], + ]; + } + + /** + * Data untuk notifikasi pengguna. + * @param \App\Models\User $user Pengguna yang sedang login. + * @return array Daftar notifikasi. + */ + public static function getNotifikasiForUser($user): array + { + $notifikasi = []; + $allBooks = self::getAllBooks(); + $myBooks = $allBooks->filter(function ($buku) use ($user) { + if (!isset($buku['user_id']) || $buku['user_id'] === null) { + return false; + } + + if (is_array($buku['user_id'])) { + return in_array($user->id, $buku['user_id']); + } + return $buku['user_id'] == $user->id; + }); + + foreach ($myBooks as $buku) { + // LOGIC TELAT + if ($buku['sisa_hari'] < 0 && $buku['status'] == 'Dipinjam') { + $hariTelat = abs($buku['sisa_hari']); + $denda = $hariTelat * 1000; + + $notifikasi[] = [ + 'icon' => 'bi-exclamation-octagon-fill', + 'color' => 'danger', + 'title' => 'TERLAMBAT: ' . $buku['judul'], + 'content' => "Telat {$hariTelat} hari. Denda: Rp " . number_format($denda, 0, ',', '.'), + 'time' => 'Sekarang', + 'read' => false, + 'type' => 'denda_active', + 'link_id' => null, + ]; + } + // LOGIC JATUH TEMPO + elseif ($buku['sisa_hari'] >= 0 && $buku['sisa_hari'] <= 3 && $buku['status'] == 'Dipinjam') { + $notifikasi[] = [ + 'icon' => 'bi-exclamation-triangle-fill', + 'color' => 'warning', + 'title' => 'Jatuh Tempo: ' . $buku['judul'], + 'content' => "Sisa waktu tinggal " . $buku['sisa_hari'] . " hari lagi.", + 'time' => 'Segera', + 'read' => false, + 'type' => 'warning_jatuh_tempo', + 'link_id' => null, + ]; + } + } + + // Notif Default + $notifikasi[] = [ + 'icon' => 'bi-info-circle-fill', + 'color' => 'primary', + 'title' => 'Selamat Datang di DigiPus!', + 'content' => 'Silakan jelajahi koleksi buku terbaru kami.', + 'time' => 'Baru saja', + 'read' => true, + 'type' => 'info', + 'link_id' => null, + ]; + + return $notifikasi; + } +} diff --git a/app/View/Components/AppLayout.php b/app/View/Components/AppLayout.php new file mode 100644 index 0000000..de0d46f --- /dev/null +++ b/app/View/Components/AppLayout.php @@ -0,0 +1,17 @@ +handleCommand(new ArgvInput); + +exit($status); diff --git a/bootstrap/app.php b/bootstrap/app.php new file mode 100644 index 0000000..4d99605 --- /dev/null +++ b/bootstrap/app.php @@ -0,0 +1,23 @@ +withRouting( + web: __DIR__ . '/../routes/web.php', + commands: __DIR__ . '/../routes/console.php', + health: '/up', + ) + ->withMiddleware(function (Middleware $middleware) { + $middleware->alias([ + 'role' => \App\Http\Middleware\CheckRole::class, + ]); +}) + ->withProviders([ + App\Providers\AuthServiceProvider::class, + ]) + ->withExceptions(function (Exceptions $exceptions): void { + // + })->create(); \ No newline at end of file diff --git a/bootstrap/cache/.gitignore b/bootstrap/cache/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/bootstrap/cache/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/bootstrap/providers.php b/bootstrap/providers.php new file mode 100644 index 0000000..8dc3a48 --- /dev/null +++ b/bootstrap/providers.php @@ -0,0 +1,6 @@ +=5.0.0" + }, + "require-dev": { + "doctrine/dbal": "^4.0.0", + "nesbot/carbon": "^2.71.0 || ^3.0.0", + "phpunit/phpunit": "^10.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Carbon\\Doctrine\\": "src/Carbon/Doctrine/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "KyleKatarn", + "email": "kylekatarnls@gmail.com" + } + ], + "description": "Types to use Carbon in Doctrine", + "keywords": [ + "carbon", + "date", + "datetime", + "doctrine", + "time" + ], + "support": { + "issues": "https://github.com/CarbonPHP/carbon-doctrine-types/issues", + "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/3.2.0" + }, + "funding": [ + { + "url": "https://github.com/kylekatarnls", + "type": "github" + }, + { + "url": "https://opencollective.com/Carbon", + "type": "open_collective" + }, + { + "url": "https://tidelift.com/funding/github/packagist/nesbot/carbon", + "type": "tidelift" + } + ], + "time": "2024-02-09T16:56:22+00:00" + }, + { + "name": "dflydev/dot-access-data", + "version": "v3.0.3", + "source": { + "type": "git", + "url": "https://github.com/dflydev/dflydev-dot-access-data.git", + "reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/a23a2bf4f31d3518f3ecb38660c95715dfead60f", + "reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.42", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.3", + "scrutinizer/ocular": "1.6.0", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Dflydev\\DotAccessData\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dragonfly Development Inc.", + "email": "info@dflydev.com", + "homepage": "http://dflydev.com" + }, + { + "name": "Beau Simensen", + "email": "beau@dflydev.com", + "homepage": "http://beausimensen.com" + }, + { + "name": "Carlos Frutos", + "email": "carlos@kiwing.it", + "homepage": "https://github.com/cfrutos" + }, + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com" + } + ], + "description": "Given a deep data structure, access data by dot notation.", + "homepage": "https://github.com/dflydev/dflydev-dot-access-data", + "keywords": [ + "access", + "data", + "dot", + "notation" + ], + "support": { + "issues": "https://github.com/dflydev/dflydev-dot-access-data/issues", + "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.3" + }, + "time": "2024-07-08T12:26:09+00:00" + }, + { + "name": "doctrine/inflector", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/6d6c96277ea252fc1304627204c3d5e6e15faa3b", + "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^12.0 || ^13.0", + "phpstan/phpstan": "^1.12 || ^2.0", + "phpstan/phpstan-phpunit": "^1.4 || ^2.0", + "phpstan/phpstan-strict-rules": "^1.6 || ^2.0", + "phpunit/phpunit": "^8.5 || ^12.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Inflector\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", + "homepage": "https://www.doctrine-project.org/projects/inflector.html", + "keywords": [ + "inflection", + "inflector", + "lowercase", + "manipulation", + "php", + "plural", + "singular", + "strings", + "uppercase", + "words" + ], + "support": { + "issues": "https://github.com/doctrine/inflector/issues", + "source": "https://github.com/doctrine/inflector/tree/2.1.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", + "type": "tidelift" + } + ], + "time": "2025-08-10T19:31:58+00:00" + }, + { + "name": "doctrine/lexer", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "doctrine/coding-standard": "^12", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.5", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^5.21" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "support": { + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/3.0.1" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", + "type": "tidelift" + } + ], + "time": "2024-02-05T11:56:58+00:00" + }, + { + "name": "dragonmantank/cron-expression", + "version": "v3.4.0", + "source": { + "type": "git", + "url": "https://github.com/dragonmantank/cron-expression.git", + "reference": "8c784d071debd117328803d86b2097615b457500" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/8c784d071debd117328803d86b2097615b457500", + "reference": "8c784d071debd117328803d86b2097615b457500", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0", + "webmozart/assert": "^1.0" + }, + "replace": { + "mtdowling/cron-expression": "^1.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.0", + "phpunit/phpunit": "^7.0|^8.0|^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Cron\\": "src/Cron/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Tankersley", + "email": "chris@ctankersley.com", + "homepage": "https://github.com/dragonmantank" + } + ], + "description": "CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due", + "keywords": [ + "cron", + "schedule" + ], + "support": { + "issues": "https://github.com/dragonmantank/cron-expression/issues", + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.4.0" + }, + "funding": [ + { + "url": "https://github.com/dragonmantank", + "type": "github" + } + ], + "time": "2024-10-09T13:47:03+00:00" + }, + { + "name": "egulias/email-validator", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/egulias/EmailValidator.git", + "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa", + "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa", + "shasum": "" + }, + "require": { + "doctrine/lexer": "^2.0 || ^3.0", + "php": ">=8.1", + "symfony/polyfill-intl-idn": "^1.26" + }, + "require-dev": { + "phpunit/phpunit": "^10.2", + "vimeo/psalm": "^5.12" + }, + "suggest": { + "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Egulias\\EmailValidator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eduardo Gulias Davis" + } + ], + "description": "A library for validating emails against several RFCs", + "homepage": "https://github.com/egulias/EmailValidator", + "keywords": [ + "email", + "emailvalidation", + "emailvalidator", + "validation", + "validator" + ], + "support": { + "issues": "https://github.com/egulias/EmailValidator/issues", + "source": "https://github.com/egulias/EmailValidator/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/egulias", + "type": "github" + } + ], + "time": "2025-03-06T22:45:56+00:00" + }, + { + "name": "fruitcake/php-cors", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/fruitcake/php-cors.git", + "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/3d158f36e7875e2f040f37bc0573956240a5a38b", + "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0", + "symfony/http-foundation": "^4.4|^5.4|^6|^7" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "phpunit/phpunit": "^9", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "Fruitcake\\Cors\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fruitcake", + "homepage": "https://fruitcake.nl" + }, + { + "name": "Barryvdh", + "email": "barryvdh@gmail.com" + } + ], + "description": "Cross-origin resource sharing library for the Symfony HttpFoundation", + "homepage": "https://github.com/fruitcake/php-cors", + "keywords": [ + "cors", + "laravel", + "symfony" + ], + "support": { + "issues": "https://github.com/fruitcake/php-cors/issues", + "source": "https://github.com/fruitcake/php-cors/tree/v1.3.0" + }, + "funding": [ + { + "url": "https://fruitcake.nl", + "type": "custom" + }, + { + "url": "https://github.com/barryvdh", + "type": "github" + } + ], + "time": "2023-10-12T05:21:21+00:00" + }, + { + "name": "graham-campbell/result-type", + "version": "v1.1.3", + "source": { + "type": "git", + "url": "https://github.com/GrahamCampbell/Result-Type.git", + "reference": "3ba905c11371512af9d9bdd27d99b782216b6945" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/3ba905c11371512af9d9bdd27d99b782216b6945", + "reference": "3ba905c11371512af9d9bdd27d99b782216b6945", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.3" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" + }, + "type": "library", + "autoload": { + "psr-4": { + "GrahamCampbell\\ResultType\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "An Implementation Of The Result Type", + "keywords": [ + "Graham Campbell", + "GrahamCampbell", + "Result Type", + "Result-Type", + "result" + ], + "support": { + "issues": "https://github.com/GrahamCampbell/Result-Type/issues", + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.3" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type", + "type": "tidelift" + } + ], + "time": "2024-07-20T21:45:45+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "7.10.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", + "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^2.3", + "guzzlehttp/psr7": "^2.8", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-curl": "*", + "guzzle/client-integration-tests": "3.0.2", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.39 || ^9.6.20", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.10.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2025-08-23T22:36:01+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "2.3.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "481557b130ef3790cf82b713667b43030dc9c957" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/481557b130ef3790cf82b713667b43030dc9c957", + "reference": "481557b130ef3790cf82b713667b43030dc9c957", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.44 || ^9.6.25" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/2.3.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2025-08-22T14:34:08+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.8.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "21dc724a0583619cd1652f673303492272778051" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051", + "reference": "21dc724a0583619cd1652f673303492272778051", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "http-interop/http-factory-tests": "0.9.0", + "phpunit/phpunit": "^8.5.44 || ^9.6.25" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.8.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2025-08-23T21:21:41+00:00" + }, + { + "name": "guzzlehttp/uri-template", + "version": "v1.0.5", + "source": { + "type": "git", + "url": "https://github.com/guzzle/uri-template.git", + "reference": "4f4bbd4e7172148801e76e3decc1e559bdee34e1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/uri-template/zipball/4f4bbd4e7172148801e76e3decc1e559bdee34e1", + "reference": "4f4bbd4e7172148801e76e3decc1e559bdee34e1", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "symfony/polyfill-php80": "^1.24" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.44 || ^9.6.25", + "uri-template/tests": "1.0.0" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\UriTemplate\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + } + ], + "description": "A polyfill class for uri_template of PHP", + "keywords": [ + "guzzlehttp", + "uri-template" + ], + "support": { + "issues": "https://github.com/guzzle/uri-template/issues", + "source": "https://github.com/guzzle/uri-template/tree/v1.0.5" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/uri-template", + "type": "tidelift" + } + ], + "time": "2025-08-22T14:27:06+00:00" + }, + { + "name": "laravel/framework", + "version": "v12.30.1", + "source": { + "type": "git", + "url": "https://github.com/laravel/framework.git", + "reference": "7f61e8679f9142f282a0184ac7ef9e3834bfd023" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/framework/zipball/7f61e8679f9142f282a0184ac7ef9e3834bfd023", + "reference": "7f61e8679f9142f282a0184ac7ef9e3834bfd023", + "shasum": "" + }, + "require": { + "brick/math": "^0.11|^0.12|^0.13|^0.14", + "composer-runtime-api": "^2.2", + "doctrine/inflector": "^2.0.5", + "dragonmantank/cron-expression": "^3.4", + "egulias/email-validator": "^3.2.1|^4.0", + "ext-ctype": "*", + "ext-filter": "*", + "ext-hash": "*", + "ext-mbstring": "*", + "ext-openssl": "*", + "ext-session": "*", + "ext-tokenizer": "*", + "fruitcake/php-cors": "^1.3", + "guzzlehttp/guzzle": "^7.8.2", + "guzzlehttp/uri-template": "^1.0", + "laravel/prompts": "^0.3.0", + "laravel/serializable-closure": "^1.3|^2.0", + "league/commonmark": "^2.7", + "league/flysystem": "^3.25.1", + "league/flysystem-local": "^3.25.1", + "league/uri": "^7.5.1", + "monolog/monolog": "^3.0", + "nesbot/carbon": "^3.8.4", + "nunomaduro/termwind": "^2.0", + "phiki/phiki": "^2.0.0", + "php": "^8.2", + "psr/container": "^1.1.1|^2.0.1", + "psr/log": "^1.0|^2.0|^3.0", + "psr/simple-cache": "^1.0|^2.0|^3.0", + "ramsey/uuid": "^4.7", + "symfony/console": "^7.2.0", + "symfony/error-handler": "^7.2.0", + "symfony/finder": "^7.2.0", + "symfony/http-foundation": "^7.2.0", + "symfony/http-kernel": "^7.2.0", + "symfony/mailer": "^7.2.0", + "symfony/mime": "^7.2.0", + "symfony/polyfill-php83": "^1.33", + "symfony/polyfill-php84": "^1.33", + "symfony/polyfill-php85": "^1.33", + "symfony/process": "^7.2.0", + "symfony/routing": "^7.2.0", + "symfony/uid": "^7.2.0", + "symfony/var-dumper": "^7.2.0", + "tijsverkoyen/css-to-inline-styles": "^2.2.5", + "vlucas/phpdotenv": "^5.6.1", + "voku/portable-ascii": "^2.0.2" + }, + "conflict": { + "tightenco/collect": "<5.5.33" + }, + "provide": { + "psr/container-implementation": "1.1|2.0", + "psr/log-implementation": "1.0|2.0|3.0", + "psr/simple-cache-implementation": "1.0|2.0|3.0" + }, + "replace": { + "illuminate/auth": "self.version", + "illuminate/broadcasting": "self.version", + "illuminate/bus": "self.version", + "illuminate/cache": "self.version", + "illuminate/collections": "self.version", + "illuminate/concurrency": "self.version", + "illuminate/conditionable": "self.version", + "illuminate/config": "self.version", + "illuminate/console": "self.version", + "illuminate/container": "self.version", + "illuminate/contracts": "self.version", + "illuminate/cookie": "self.version", + "illuminate/database": "self.version", + "illuminate/encryption": "self.version", + "illuminate/events": "self.version", + "illuminate/filesystem": "self.version", + "illuminate/hashing": "self.version", + "illuminate/http": "self.version", + "illuminate/json-schema": "self.version", + "illuminate/log": "self.version", + "illuminate/macroable": "self.version", + "illuminate/mail": "self.version", + "illuminate/notifications": "self.version", + "illuminate/pagination": "self.version", + "illuminate/pipeline": "self.version", + "illuminate/process": "self.version", + "illuminate/queue": "self.version", + "illuminate/redis": "self.version", + "illuminate/routing": "self.version", + "illuminate/session": "self.version", + "illuminate/support": "self.version", + "illuminate/testing": "self.version", + "illuminate/translation": "self.version", + "illuminate/validation": "self.version", + "illuminate/view": "self.version", + "spatie/once": "*" + }, + "require-dev": { + "ably/ably-php": "^1.0", + "aws/aws-sdk-php": "^3.322.9", + "ext-gmp": "*", + "fakerphp/faker": "^1.24", + "guzzlehttp/promises": "^2.0.3", + "guzzlehttp/psr7": "^2.4", + "laravel/pint": "^1.18", + "league/flysystem-aws-s3-v3": "^3.25.1", + "league/flysystem-ftp": "^3.25.1", + "league/flysystem-path-prefixing": "^3.25.1", + "league/flysystem-read-only": "^3.25.1", + "league/flysystem-sftp-v3": "^3.25.1", + "mockery/mockery": "^1.6.10", + "opis/json-schema": "^2.4.1", + "orchestra/testbench-core": "^10.6.5", + "pda/pheanstalk": "^5.0.6|^7.0.0", + "php-http/discovery": "^1.15", + "phpstan/phpstan": "^2.0", + "phpunit/phpunit": "^10.5.35|^11.5.3|^12.0.1", + "predis/predis": "^2.3|^3.0", + "resend/resend-php": "^0.10.0", + "symfony/cache": "^7.2.0", + "symfony/http-client": "^7.2.0", + "symfony/psr-http-message-bridge": "^7.2.0", + "symfony/translation": "^7.2.0" + }, + "suggest": { + "ably/ably-php": "Required to use the Ably broadcast driver (^1.0).", + "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage, and SES mail driver (^3.322.9).", + "brianium/paratest": "Required to run tests in parallel (^7.0|^8.0).", + "ext-apcu": "Required to use the APC cache driver.", + "ext-fileinfo": "Required to use the Filesystem class.", + "ext-ftp": "Required to use the Flysystem FTP driver.", + "ext-gd": "Required to use Illuminate\\Http\\Testing\\FileFactory::image().", + "ext-memcached": "Required to use the memcache cache driver.", + "ext-pcntl": "Required to use all features of the queue worker and console signal trapping.", + "ext-pdo": "Required to use all database features.", + "ext-posix": "Required to use all features of the queue worker.", + "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0|^6.0).", + "fakerphp/faker": "Required to generate fake data using the fake() helper (^1.23).", + "filp/whoops": "Required for friendly error pages in development (^2.14.3).", + "laravel/tinker": "Required to use the tinker console command (^2.0).", + "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.25.1).", + "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.25.1).", + "league/flysystem-path-prefixing": "Required to use the scoped driver (^3.25.1).", + "league/flysystem-read-only": "Required to use read-only disks (^3.25.1)", + "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.25.1).", + "mockery/mockery": "Required to use mocking (^1.6).", + "pda/pheanstalk": "Required to use the beanstalk queue driver (^5.0).", + "php-http/discovery": "Required to use PSR-7 bridging features (^1.15).", + "phpunit/phpunit": "Required to use assertions and run tests (^10.5.35|^11.5.3|^12.0.1).", + "predis/predis": "Required to use the predis connector (^2.3|^3.0).", + "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", + "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).", + "resend/resend-php": "Required to enable support for the Resend mail transport (^0.10.0).", + "symfony/cache": "Required to PSR-6 cache bridge (^7.2).", + "symfony/filesystem": "Required to enable support for relative symbolic links (^7.2).", + "symfony/http-client": "Required to enable support for the Symfony API mail transports (^7.2).", + "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^7.2).", + "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^7.2).", + "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^7.2)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "12.x-dev" + } + }, + "autoload": { + "files": [ + "src/Illuminate/Collections/functions.php", + "src/Illuminate/Collections/helpers.php", + "src/Illuminate/Events/functions.php", + "src/Illuminate/Filesystem/functions.php", + "src/Illuminate/Foundation/helpers.php", + "src/Illuminate/Log/functions.php", + "src/Illuminate/Support/functions.php", + "src/Illuminate/Support/helpers.php" + ], + "psr-4": { + "Illuminate\\": "src/Illuminate/", + "Illuminate\\Support\\": [ + "src/Illuminate/Macroable/", + "src/Illuminate/Collections/", + "src/Illuminate/Conditionable/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Laravel Framework.", + "homepage": "https://laravel.com", + "keywords": [ + "framework", + "laravel" + ], + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2025-09-18T21:07:07+00:00" + }, + { + "name": "laravel/prompts", + "version": "v0.3.6", + "source": { + "type": "git", + "url": "https://github.com/laravel/prompts.git", + "reference": "86a8b692e8661d0fb308cec64f3d176821323077" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/prompts/zipball/86a8b692e8661d0fb308cec64f3d176821323077", + "reference": "86a8b692e8661d0fb308cec64f3d176821323077", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.2", + "ext-mbstring": "*", + "php": "^8.1", + "symfony/console": "^6.2|^7.0" + }, + "conflict": { + "illuminate/console": ">=10.17.0 <10.25.0", + "laravel/framework": ">=10.17.0 <10.25.0" + }, + "require-dev": { + "illuminate/collections": "^10.0|^11.0|^12.0", + "mockery/mockery": "^1.5", + "pestphp/pest": "^2.3|^3.4", + "phpstan/phpstan": "^1.11", + "phpstan/phpstan-mockery": "^1.1" + }, + "suggest": { + "ext-pcntl": "Required for the spinner to be animated." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "0.3.x-dev" + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Laravel\\Prompts\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Add beautiful and user-friendly forms to your command-line applications.", + "support": { + "issues": "https://github.com/laravel/prompts/issues", + "source": "https://github.com/laravel/prompts/tree/v0.3.6" + }, + "time": "2025-07-07T14:17:42+00:00" + }, + { + "name": "laravel/serializable-closure", + "version": "v2.0.4", + "source": { + "type": "git", + "url": "https://github.com/laravel/serializable-closure.git", + "reference": "b352cf0534aa1ae6b4d825d1e762e35d43f8a841" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/b352cf0534aa1ae6b4d825d1e762e35d43f8a841", + "reference": "b352cf0534aa1ae6b4d825d1e762e35d43f8a841", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "illuminate/support": "^10.0|^11.0|^12.0", + "nesbot/carbon": "^2.67|^3.0", + "pestphp/pest": "^2.36|^3.0", + "phpstan/phpstan": "^2.0", + "symfony/var-dumper": "^6.2.0|^7.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\SerializableClosure\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Nuno Maduro", + "email": "nuno@laravel.com" + } + ], + "description": "Laravel Serializable Closure provides an easy and secure way to serialize closures in PHP.", + "keywords": [ + "closure", + "laravel", + "serializable" + ], + "support": { + "issues": "https://github.com/laravel/serializable-closure/issues", + "source": "https://github.com/laravel/serializable-closure" + }, + "time": "2025-03-19T13:51:03+00:00" + }, + { + "name": "laravel/tinker", + "version": "v2.10.1", + "source": { + "type": "git", + "url": "https://github.com/laravel/tinker.git", + "reference": "22177cc71807d38f2810c6204d8f7183d88a57d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/tinker/zipball/22177cc71807d38f2810c6204d8f7183d88a57d3", + "reference": "22177cc71807d38f2810c6204d8f7183d88a57d3", + "shasum": "" + }, + "require": { + "illuminate/console": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "php": "^7.2.5|^8.0", + "psy/psysh": "^0.11.1|^0.12.0", + "symfony/var-dumper": "^4.3.4|^5.0|^6.0|^7.0" + }, + "require-dev": { + "mockery/mockery": "~1.3.3|^1.4.2", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^8.5.8|^9.3.3|^10.0" + }, + "suggest": { + "illuminate/database": "The Illuminate Database package (^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0)." + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Tinker\\TinkerServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Tinker\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Powerful REPL for the Laravel framework.", + "keywords": [ + "REPL", + "Tinker", + "laravel", + "psysh" + ], + "support": { + "issues": "https://github.com/laravel/tinker/issues", + "source": "https://github.com/laravel/tinker/tree/v2.10.1" + }, + "time": "2025-01-27T14:24:01+00:00" + }, + { + "name": "league/commonmark", + "version": "2.7.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/commonmark.git", + "reference": "10732241927d3971d28e7ea7b5712721fa2296ca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/10732241927d3971d28e7ea7b5712721fa2296ca", + "reference": "10732241927d3971d28e7ea7b5712721fa2296ca", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "league/config": "^1.1.1", + "php": "^7.4 || ^8.0", + "psr/event-dispatcher": "^1.0", + "symfony/deprecation-contracts": "^2.1 || ^3.0", + "symfony/polyfill-php80": "^1.16" + }, + "require-dev": { + "cebe/markdown": "^1.0", + "commonmark/cmark": "0.31.1", + "commonmark/commonmark.js": "0.31.1", + "composer/package-versions-deprecated": "^1.8", + "embed/embed": "^4.4", + "erusev/parsedown": "^1.0", + "ext-json": "*", + "github/gfm": "0.29.0", + "michelf/php-markdown": "^1.4 || ^2.0", + "nyholm/psr7": "^1.5", + "phpstan/phpstan": "^1.8.2", + "phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0", + "scrutinizer/ocular": "^1.8.1", + "symfony/finder": "^5.3 | ^6.0 | ^7.0", + "symfony/process": "^5.4 | ^6.0 | ^7.0", + "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0", + "unleashedtech/php-coding-standard": "^3.1.1", + "vimeo/psalm": "^4.24.0 || ^5.0.0 || ^6.0.0" + }, + "suggest": { + "symfony/yaml": "v2.3+ required if using the Front Matter extension" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "League\\CommonMark\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" + } + ], + "description": "Highly-extensible PHP Markdown parser which fully supports the CommonMark spec and GitHub-Flavored Markdown (GFM)", + "homepage": "https://commonmark.thephpleague.com", + "keywords": [ + "commonmark", + "flavored", + "gfm", + "github", + "github-flavored", + "markdown", + "md", + "parser" + ], + "support": { + "docs": "https://commonmark.thephpleague.com/", + "forum": "https://github.com/thephpleague/commonmark/discussions", + "issues": "https://github.com/thephpleague/commonmark/issues", + "rss": "https://github.com/thephpleague/commonmark/releases.atom", + "source": "https://github.com/thephpleague/commonmark" + }, + "funding": [ + { + "url": "https://www.colinodell.com/sponsor", + "type": "custom" + }, + { + "url": "https://www.paypal.me/colinpodell/10.00", + "type": "custom" + }, + { + "url": "https://github.com/colinodell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/commonmark", + "type": "tidelift" + } + ], + "time": "2025-07-20T12:47:49+00:00" + }, + { + "name": "league/config", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/config.git", + "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/config/zipball/754b3604fb2984c71f4af4a9cbe7b57f346ec1f3", + "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3", + "shasum": "" + }, + "require": { + "dflydev/dot-access-data": "^3.0.1", + "nette/schema": "^1.2", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.8.2", + "phpunit/phpunit": "^9.5.5", + "scrutinizer/ocular": "^1.8.1", + "unleashedtech/php-coding-standard": "^3.1", + "vimeo/psalm": "^4.7.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Config\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" + } + ], + "description": "Define configuration arrays with strict schemas and access values with dot notation", + "homepage": "https://config.thephpleague.com", + "keywords": [ + "array", + "config", + "configuration", + "dot", + "dot-access", + "nested", + "schema" + ], + "support": { + "docs": "https://config.thephpleague.com/", + "issues": "https://github.com/thephpleague/config/issues", + "rss": "https://github.com/thephpleague/config/releases.atom", + "source": "https://github.com/thephpleague/config" + }, + "funding": [ + { + "url": "https://www.colinodell.com/sponsor", + "type": "custom" + }, + { + "url": "https://www.paypal.me/colinpodell/10.00", + "type": "custom" + }, + { + "url": "https://github.com/colinodell", + "type": "github" + } + ], + "time": "2022-12-11T20:36:23+00:00" + }, + { + "name": "league/flysystem", + "version": "3.30.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem.git", + "reference": "2203e3151755d874bb2943649dae1eb8533ac93e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/2203e3151755d874bb2943649dae1eb8533ac93e", + "reference": "2203e3151755d874bb2943649dae1eb8533ac93e", + "shasum": "" + }, + "require": { + "league/flysystem-local": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "conflict": { + "async-aws/core": "<1.19.0", + "async-aws/s3": "<1.14.0", + "aws/aws-sdk-php": "3.209.31 || 3.210.0", + "guzzlehttp/guzzle": "<7.0", + "guzzlehttp/ringphp": "<1.1.1", + "phpseclib/phpseclib": "3.0.15", + "symfony/http-client": "<5.2" + }, + "require-dev": { + "async-aws/s3": "^1.5 || ^2.0", + "async-aws/simple-s3": "^1.1 || ^2.0", + "aws/aws-sdk-php": "^3.295.10", + "composer/semver": "^3.0", + "ext-fileinfo": "*", + "ext-ftp": "*", + "ext-mongodb": "^1.3|^2", + "ext-zip": "*", + "friendsofphp/php-cs-fixer": "^3.5", + "google/cloud-storage": "^1.23", + "guzzlehttp/psr7": "^2.6", + "microsoft/azure-storage-blob": "^1.1", + "mongodb/mongodb": "^1.2|^2", + "phpseclib/phpseclib": "^3.0.36", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.5.11|^10.0", + "sabre/dav": "^4.6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "File storage abstraction for PHP", + "keywords": [ + "WebDAV", + "aws", + "cloud", + "file", + "files", + "filesystem", + "filesystems", + "ftp", + "s3", + "sftp", + "storage" + ], + "support": { + "issues": "https://github.com/thephpleague/flysystem/issues", + "source": "https://github.com/thephpleague/flysystem/tree/3.30.0" + }, + "time": "2025-06-25T13:29:59+00:00" + }, + { + "name": "league/flysystem-local", + "version": "3.30.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-local.git", + "reference": "6691915f77c7fb69adfb87dcd550052dc184ee10" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/6691915f77c7fb69adfb87dcd550052dc184ee10", + "reference": "6691915f77c7fb69adfb87dcd550052dc184ee10", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "league/flysystem": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\Local\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "Local filesystem adapter for Flysystem.", + "keywords": [ + "Flysystem", + "file", + "files", + "filesystem", + "local" + ], + "support": { + "source": "https://github.com/thephpleague/flysystem-local/tree/3.30.0" + }, + "time": "2025-05-21T10:34:19+00:00" + }, + { + "name": "league/mime-type-detection", + "version": "1.16.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/mime-type-detection.git", + "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/2d6702ff215bf922936ccc1ad31007edc76451b9", + "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.2", + "phpstan/phpstan": "^0.12.68", + "phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\MimeTypeDetection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "Mime-type detection for Flysystem", + "support": { + "issues": "https://github.com/thephpleague/mime-type-detection/issues", + "source": "https://github.com/thephpleague/mime-type-detection/tree/1.16.0" + }, + "funding": [ + { + "url": "https://github.com/frankdejonge", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/flysystem", + "type": "tidelift" + } + ], + "time": "2024-09-21T08:32:55+00:00" + }, + { + "name": "league/uri", + "version": "7.5.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/uri.git", + "reference": "81fb5145d2644324614cc532b28efd0215bda430" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/uri/zipball/81fb5145d2644324614cc532b28efd0215bda430", + "reference": "81fb5145d2644324614cc532b28efd0215bda430", + "shasum": "" + }, + "require": { + "league/uri-interfaces": "^7.5", + "php": "^8.1" + }, + "conflict": { + "league/uri-schemes": "^1.0" + }, + "suggest": { + "ext-bcmath": "to improve IPV4 host parsing", + "ext-fileinfo": "to create Data URI from file contennts", + "ext-gmp": "to improve IPV4 host parsing", + "ext-intl": "to handle IDN host with the best performance", + "jeremykendall/php-domain-parser": "to resolve Public Suffix and Top Level Domain", + "league/uri-components": "Needed to easily manipulate URI objects components", + "php-64bit": "to improve IPV4 host parsing", + "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Uri\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "URI manipulation library", + "homepage": "https://uri.thephpleague.com", + "keywords": [ + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "middleware", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", + "rfc3986", + "rfc3987", + "rfc6570", + "uri", + "uri-template", + "url", + "ws" + ], + "support": { + "docs": "https://uri.thephpleague.com", + "forum": "https://thephpleague.slack.com", + "issues": "https://github.com/thephpleague/uri-src/issues", + "source": "https://github.com/thephpleague/uri/tree/7.5.1" + }, + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2024-12-08T08:40:02+00:00" + }, + { + "name": "league/uri-interfaces", + "version": "7.5.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/uri-interfaces.git", + "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", + "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", + "shasum": "" + }, + "require": { + "ext-filter": "*", + "php": "^8.1", + "psr/http-factory": "^1", + "psr/http-message": "^1.1 || ^2.0" + }, + "suggest": { + "ext-bcmath": "to improve IPV4 host parsing", + "ext-gmp": "to improve IPV4 host parsing", + "ext-intl": "to handle IDN host with the best performance", + "php-64bit": "to improve IPV4 host parsing", + "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Uri\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "Common interfaces and classes for URI representation and interaction", + "homepage": "https://uri.thephpleague.com", + "keywords": [ + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", + "rfc3986", + "rfc3987", + "rfc6570", + "uri", + "url", + "ws" + ], + "support": { + "docs": "https://uri.thephpleague.com", + "forum": "https://thephpleague.slack.com", + "issues": "https://github.com/thephpleague/uri-src/issues", + "source": "https://github.com/thephpleague/uri-interfaces/tree/7.5.0" + }, + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2024-12-08T08:18:47+00:00" + }, + { + "name": "monolog/monolog", + "version": "3.9.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/10d85740180ecba7896c87e06a166e0c95a0e3b6", + "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^2.0 || ^3.0" + }, + "provide": { + "psr/log-implementation": "3.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "^3.0", + "doctrine/couchdb": "~1.0@dev", + "elasticsearch/elasticsearch": "^7 || ^8", + "ext-json": "*", + "graylog2/gelf-php": "^1.4.2 || ^2.0", + "guzzlehttp/guzzle": "^7.4.5", + "guzzlehttp/psr7": "^2.2", + "mongodb/mongodb": "^1.8", + "php-amqplib/php-amqplib": "~2.4 || ^3", + "php-console/php-console": "^3.1.8", + "phpstan/phpstan": "^2", + "phpstan/phpstan-deprecation-rules": "^2", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "^10.5.17 || ^11.0.7", + "predis/predis": "^1.1 || ^2", + "rollbar/rollbar": "^4.0", + "ruflin/elastica": "^7 || ^8", + "symfony/mailer": "^5.4 || ^6", + "symfony/mime": "^5.4 || ^6" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", + "ext-mbstring": "Allow to work properly with unicode symbols", + "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", + "ext-openssl": "Required to send log messages using SSL", + "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Monolog\\": "src/Monolog" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "https://github.com/Seldaek/monolog", + "keywords": [ + "log", + "logging", + "psr-3" + ], + "support": { + "issues": "https://github.com/Seldaek/monolog/issues", + "source": "https://github.com/Seldaek/monolog/tree/3.9.0" + }, + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", + "type": "tidelift" + } + ], + "time": "2025-03-24T10:02:05+00:00" + }, + { + "name": "nesbot/carbon", + "version": "3.10.3", + "source": { + "type": "git", + "url": "https://github.com/CarbonPHP/carbon.git", + "reference": "8e3643dcd149ae0fe1d2ff4f2c8e4bbfad7c165f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/8e3643dcd149ae0fe1d2ff4f2c8e4bbfad7c165f", + "reference": "8e3643dcd149ae0fe1d2ff4f2c8e4bbfad7c165f", + "shasum": "" + }, + "require": { + "carbonphp/carbon-doctrine-types": "<100.0", + "ext-json": "*", + "php": "^8.1", + "psr/clock": "^1.0", + "symfony/clock": "^6.3.12 || ^7.0", + "symfony/polyfill-mbstring": "^1.0", + "symfony/translation": "^4.4.18 || ^5.2.1 || ^6.0 || ^7.0" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "require-dev": { + "doctrine/dbal": "^3.6.3 || ^4.0", + "doctrine/orm": "^2.15.2 || ^3.0", + "friendsofphp/php-cs-fixer": "^v3.87.1", + "kylekatarnls/multi-tester": "^2.5.3", + "phpmd/phpmd": "^2.15.0", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^2.1.22", + "phpunit/phpunit": "^10.5.53", + "squizlabs/php_codesniffer": "^3.13.4" + }, + "bin": [ + "bin/carbon" + ], + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Carbon\\Laravel\\ServiceProvider" + ] + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + }, + "branch-alias": { + "dev-2.x": "2.x-dev", + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Carbon\\": "src/Carbon/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Nesbitt", + "email": "brian@nesbot.com", + "homepage": "https://markido.com" + }, + { + "name": "kylekatarnls", + "homepage": "https://github.com/kylekatarnls" + } + ], + "description": "An API extension for DateTime that supports 281 different languages.", + "homepage": "https://carbon.nesbot.com", + "keywords": [ + "date", + "datetime", + "time" + ], + "support": { + "docs": "https://carbon.nesbot.com/docs", + "issues": "https://github.com/CarbonPHP/carbon/issues", + "source": "https://github.com/CarbonPHP/carbon" + }, + "funding": [ + { + "url": "https://github.com/sponsors/kylekatarnls", + "type": "github" + }, + { + "url": "https://opencollective.com/Carbon#sponsor", + "type": "opencollective" + }, + { + "url": "https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme", + "type": "tidelift" + } + ], + "time": "2025-09-06T13:39:36+00:00" + }, + { + "name": "nette/schema", + "version": "v1.3.2", + "source": { + "type": "git", + "url": "https://github.com/nette/schema.git", + "reference": "da801d52f0354f70a638673c4a0f04e16529431d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/schema/zipball/da801d52f0354f70a638673c4a0f04e16529431d", + "reference": "da801d52f0354f70a638673c4a0f04e16529431d", + "shasum": "" + }, + "require": { + "nette/utils": "^4.0", + "php": "8.1 - 8.4" + }, + "require-dev": { + "nette/tester": "^2.5.2", + "phpstan/phpstan-nette": "^1.0", + "tracy/tracy": "^2.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "📐 Nette Schema: validating data structures against a given Schema.", + "homepage": "https://nette.org", + "keywords": [ + "config", + "nette" + ], + "support": { + "issues": "https://github.com/nette/schema/issues", + "source": "https://github.com/nette/schema/tree/v1.3.2" + }, + "time": "2024-10-06T23:10:23+00:00" + }, + { + "name": "nette/utils", + "version": "v4.0.8", + "source": { + "type": "git", + "url": "https://github.com/nette/utils.git", + "reference": "c930ca4e3cf4f17dcfb03037703679d2396d2ede" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/utils/zipball/c930ca4e3cf4f17dcfb03037703679d2396d2ede", + "reference": "c930ca4e3cf4f17dcfb03037703679d2396d2ede", + "shasum": "" + }, + "require": { + "php": "8.0 - 8.5" + }, + "conflict": { + "nette/finder": "<3", + "nette/schema": "<1.2.2" + }, + "require-dev": { + "jetbrains/phpstorm-attributes": "^1.2", + "nette/tester": "^2.5", + "phpstan/phpstan-nette": "^2.0@stable", + "tracy/tracy": "^2.9" + }, + "suggest": { + "ext-gd": "to use Image", + "ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()", + "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", + "ext-json": "to use Nette\\Utils\\Json", + "ext-mbstring": "to use Strings::lower() etc...", + "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Nette\\": "src" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", + "homepage": "https://nette.org", + "keywords": [ + "array", + "core", + "datetime", + "images", + "json", + "nette", + "paginator", + "password", + "slugify", + "string", + "unicode", + "utf-8", + "utility", + "validation" + ], + "support": { + "issues": "https://github.com/nette/utils/issues", + "source": "https://github.com/nette/utils/tree/v4.0.8" + }, + "time": "2025-08-06T21:43:34+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.6.1", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2", + "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.6.1" + }, + "time": "2025-08-13T20:13:15+00:00" + }, + { + "name": "nunomaduro/termwind", + "version": "v2.3.1", + "source": { + "type": "git", + "url": "https://github.com/nunomaduro/termwind.git", + "reference": "dfa08f390e509967a15c22493dc0bac5733d9123" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/dfa08f390e509967a15c22493dc0bac5733d9123", + "reference": "dfa08f390e509967a15c22493dc0bac5733d9123", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "^8.2", + "symfony/console": "^7.2.6" + }, + "require-dev": { + "illuminate/console": "^11.44.7", + "laravel/pint": "^1.22.0", + "mockery/mockery": "^1.6.12", + "pestphp/pest": "^2.36.0 || ^3.8.2", + "phpstan/phpstan": "^1.12.25", + "phpstan/phpstan-strict-rules": "^1.6.2", + "symfony/var-dumper": "^7.2.6", + "thecodingmachine/phpstan-strict-rules": "^1.0.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Termwind\\Laravel\\TermwindServiceProvider" + ] + }, + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "files": [ + "src/Functions.php" + ], + "psr-4": { + "Termwind\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Its like Tailwind CSS, but for the console.", + "keywords": [ + "cli", + "console", + "css", + "package", + "php", + "style" + ], + "support": { + "issues": "https://github.com/nunomaduro/termwind/issues", + "source": "https://github.com/nunomaduro/termwind/tree/v2.3.1" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://github.com/xiCO2k", + "type": "github" + } + ], + "time": "2025-05-08T08:14:37+00:00" + }, + { + "name": "phiki/phiki", + "version": "v2.0.3", + "source": { + "type": "git", + "url": "https://github.com/phikiphp/phiki.git", + "reference": "fe51fe6dc31856cd776fd1b04ee74053a4271644" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phikiphp/phiki/zipball/fe51fe6dc31856cd776fd1b04ee74053a4271644", + "reference": "fe51fe6dc31856cd776fd1b04ee74053a4271644", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "league/commonmark": "^2.5.3", + "php": "^8.2", + "psr/simple-cache": "^3.0" + }, + "require-dev": { + "illuminate/support": "^11.45", + "laravel/pint": "^1.18.1", + "orchestra/testbench": "^9.15", + "pestphp/pest": "^3.5.1", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^2.0", + "symfony/var-dumper": "^7.1.6" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Phiki\\Adapters\\Laravel\\PhikiServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Phiki\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ryan Chandler", + "email": "support@ryangjchandler.co.uk", + "homepage": "https://ryangjchandler.co.uk", + "role": "Developer" + } + ], + "description": "Syntax highlighting using TextMate grammars in PHP.", + "support": { + "issues": "https://github.com/phikiphp/phiki/issues", + "source": "https://github.com/phikiphp/phiki/tree/v2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sponsors/ryangjchandler", + "type": "github" + }, + { + "url": "https://buymeacoffee.com/ryangjchandler", + "type": "other" + } + ], + "time": "2025-09-19T11:50:41+00:00" + }, + { + "name": "phpoption/phpoption", + "version": "1.9.4", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/php-option.git", + "reference": "638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d", + "reference": "638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.44 || ^9.6.25 || ^10.5.53 || ^11.5.34" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + }, + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpOption\\": "src/PhpOption/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com", + "homepage": "https://github.com/schmittjoh" + }, + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "Option Type for PHP", + "keywords": [ + "language", + "option", + "php", + "type" + ], + "support": { + "issues": "https://github.com/schmittjoh/php-option/issues", + "source": "https://github.com/schmittjoh/php-option/tree/1.9.4" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption", + "type": "tidelift" + } + ], + "time": "2025-08-21T11:53:16+00:00" + }, + { + "name": "psr/clock", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/clock.git", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Clock\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for reading the clock.", + "homepage": "https://github.com/php-fig/clock", + "keywords": [ + "clock", + "now", + "psr", + "psr-20", + "time" + ], + "support": { + "issues": "https://github.com/php-fig/clock/issues", + "source": "https://github.com/php-fig/clock/tree/1.0.0" + }, + "time": "2022-11-25T14:36:26+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client" + }, + "time": "2023-09-23T14:17:50+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory" + }, + "time": "2024-04-15T12:06:14+00:00" + }, + { + "name": "psr/http-message", + "version": "2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/2.0" + }, + "time": "2023-04-04T09:54:51+00:00" + }, + { + "name": "psr/log", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.2" + }, + "time": "2024-09-11T13:17:53+00:00" + }, + { + "name": "psr/simple-cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "support": { + "source": "https://github.com/php-fig/simple-cache/tree/3.0.0" + }, + "time": "2021-10-29T13:26:27+00:00" + }, + { + "name": "psy/psysh", + "version": "v0.12.10", + "source": { + "type": "git", + "url": "https://github.com/bobthecow/psysh.git", + "reference": "6e80abe6f2257121f1eb9a4c55bf29d921025b22" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/6e80abe6f2257121f1eb9a4c55bf29d921025b22", + "reference": "6e80abe6f2257121f1eb9a4c55bf29d921025b22", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-tokenizer": "*", + "nikic/php-parser": "^5.0 || ^4.0", + "php": "^8.0 || ^7.4", + "symfony/console": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4", + "symfony/var-dumper": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4" + }, + "conflict": { + "symfony/console": "4.4.37 || 5.3.14 || 5.3.15 || 5.4.3 || 5.4.4 || 6.0.3 || 6.0.4" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.2" + }, + "suggest": { + "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", + "ext-pdo-sqlite": "The doc command requires SQLite to work.", + "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well." + }, + "bin": [ + "bin/psysh" + ], + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": false, + "forward-command": false + }, + "branch-alias": { + "dev-main": "0.12.x-dev" + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Psy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Justin Hileman", + "email": "justin@justinhileman.info" + } + ], + "description": "An interactive shell for modern PHP.", + "homepage": "https://psysh.org", + "keywords": [ + "REPL", + "console", + "interactive", + "shell" + ], + "support": { + "issues": "https://github.com/bobthecow/psysh/issues", + "source": "https://github.com/bobthecow/psysh/tree/v0.12.10" + }, + "time": "2025-08-04T12:39:37+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "ramsey/collection", + "version": "2.1.1", + "source": { + "type": "git", + "url": "https://github.com/ramsey/collection.git", + "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/collection/zipball/344572933ad0181accbf4ba763e85a0306a8c5e2", + "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "captainhook/plugin-composer": "^5.3", + "ergebnis/composer-normalize": "^2.45", + "fakerphp/faker": "^1.24", + "hamcrest/hamcrest-php": "^2.0", + "jangregor/phpstan-prophecy": "^2.1", + "mockery/mockery": "^1.6", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.4", + "phpspec/prophecy-phpunit": "^2.3", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-mockery": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^10.5", + "ramsey/coding-standard": "^2.3", + "ramsey/conventional-commits": "^1.6", + "roave/security-advisories": "dev-latest" + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + }, + "ramsey/conventional-commits": { + "configFile": "conventional-commits.json" + } + }, + "autoload": { + "psr-4": { + "Ramsey\\Collection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + } + ], + "description": "A PHP library for representing and manipulating collections.", + "keywords": [ + "array", + "collection", + "hash", + "map", + "queue", + "set" + ], + "support": { + "issues": "https://github.com/ramsey/collection/issues", + "source": "https://github.com/ramsey/collection/tree/2.1.1" + }, + "time": "2025-03-22T05:38:12+00:00" + }, + { + "name": "ramsey/uuid", + "version": "4.9.1", + "source": { + "type": "git", + "url": "https://github.com/ramsey/uuid.git", + "reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/81f941f6f729b1e3ceea61d9d014f8b6c6800440", + "reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440", + "shasum": "" + }, + "require": { + "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14", + "php": "^8.0", + "ramsey/collection": "^1.2 || ^2.0" + }, + "replace": { + "rhumsaa/uuid": "self.version" + }, + "require-dev": { + "captainhook/captainhook": "^5.25", + "captainhook/plugin-composer": "^5.3", + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "ergebnis/composer-normalize": "^2.47", + "mockery/mockery": "^1.6", + "paragonie/random-lib": "^2", + "php-mock/php-mock": "^2.6", + "php-mock/php-mock-mockery": "^1.5", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpbench/phpbench": "^1.2.14", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-mockery": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^9.6", + "slevomat/coding-standard": "^8.18", + "squizlabs/php_codesniffer": "^3.13" + }, + "suggest": { + "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", + "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.", + "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.", + "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter", + "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Ramsey\\Uuid\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).", + "keywords": [ + "guid", + "identifier", + "uuid" + ], + "support": { + "issues": "https://github.com/ramsey/uuid/issues", + "source": "https://github.com/ramsey/uuid/tree/4.9.1" + }, + "time": "2025-09-04T20:59:21+00:00" + }, + { + "name": "symfony/clock", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/clock.git", + "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/clock/zipball/b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/clock": "^1.0", + "symfony/polyfill-php83": "^1.28" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/now.php" + ], + "psr-4": { + "Symfony\\Component\\Clock\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Decouples applications from the system clock", + "homepage": "https://symfony.com", + "keywords": [ + "clock", + "psr20", + "time" + ], + "support": { + "source": "https://github.com/symfony/clock/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/console", + "version": "v7.3.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "cb0102a1c5ac3807cf3fdf8bea96007df7fdbea7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/cb0102a1c5ac3807cf3fdf8bea96007df7fdbea7", + "reference": "cb0102a1c5ac3807cf3fdf8bea96007df7fdbea7", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^7.2" + }, + "conflict": { + "symfony/dependency-injection": "<6.4", + "symfony/dotenv": "<6.4", + "symfony/event-dispatcher": "<6.4", + "symfony/lock": "<6.4", + "symfony/process": "<6.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v7.3.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-08-25T06:35:40+00:00" + }, + { + "name": "symfony/css-selector", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "601a5ce9aaad7bf10797e3663faefce9e26c24e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/601a5ce9aaad7bf10797e3663faefce9e26c24e2", + "reference": "601a5ce9aaad7bf10797e3663faefce9e26c24e2", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Converts CSS selectors to XPath expressions", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/css-selector/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/error-handler", + "version": "v7.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/error-handler.git", + "reference": "0b31a944fcd8759ae294da4d2808cbc53aebd0c3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/0b31a944fcd8759ae294da4d2808cbc53aebd0c3", + "reference": "0b31a944fcd8759ae294da4d2808cbc53aebd0c3", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/log": "^1|^2|^3", + "symfony/var-dumper": "^6.4|^7.0" + }, + "conflict": { + "symfony/deprecation-contracts": "<2.5", + "symfony/http-kernel": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/webpack-encore-bundle": "^1.0|^2.0" + }, + "bin": [ + "Resources/bin/patch-type-declarations" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\ErrorHandler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to manage errors and ease debugging PHP code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/error-handler/tree/v7.3.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-07-07T08:17:57+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v7.3.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b7dc69e71de420ac04bc9ab830cf3ffebba48191", + "reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/event-dispatcher-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/dependency-injection": "<6.4", + "symfony/service-contracts": "<2.5" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/error-handler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v7.3.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-08-13T11:49:31+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/event-dispatcher": "^1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/finder", + "version": "v7.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/2a6614966ba1074fa93dae0bc804227422df4dfe", + "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "symfony/filesystem": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v7.3.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-07-15T13:41:35+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v7.3.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "7475561ec27020196c49bb7c4f178d33d7d3dc00" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/7475561ec27020196c49bb7c4f178d33d7d3dc00", + "reference": "7475561ec27020196c49bb7c4f178d33d7d3dc00", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php83": "^1.27" + }, + "conflict": { + "doctrine/dbal": "<3.6", + "symfony/cache": "<6.4.12|>=7.0,<7.1.5" + }, + "require-dev": { + "doctrine/dbal": "^3.6|^4", + "predis/predis": "^1.1|^2.0", + "symfony/cache": "^6.4.12|^7.1.5", + "symfony/clock": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/mime": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Defines an object-oriented layer for the HTTP specification", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-foundation/tree/v7.3.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-08-20T08:04:18+00:00" + }, + { + "name": "symfony/http-kernel", + "version": "v7.3.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "72c304de37e1a1cec6d5d12b81187ebd4850a17b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/72c304de37e1a1cec6d5d12b81187ebd4850a17b", + "reference": "72c304de37e1a1cec6d5d12b81187ebd4850a17b", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/log": "^1|^2|^3", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/error-handler": "^6.4|^7.0", + "symfony/event-dispatcher": "^7.3", + "symfony/http-foundation": "^7.3", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/browser-kit": "<6.4", + "symfony/cache": "<6.4", + "symfony/config": "<6.4", + "symfony/console": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/doctrine-bridge": "<6.4", + "symfony/form": "<6.4", + "symfony/http-client": "<6.4", + "symfony/http-client-contracts": "<2.5", + "symfony/mailer": "<6.4", + "symfony/messenger": "<6.4", + "symfony/translation": "<6.4", + "symfony/translation-contracts": "<2.5", + "symfony/twig-bridge": "<6.4", + "symfony/validator": "<6.4", + "symfony/var-dumper": "<6.4", + "twig/twig": "<3.12" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/cache": "^1.0|^2.0|^3.0", + "symfony/browser-kit": "^6.4|^7.0", + "symfony/clock": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/css-selector": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/dom-crawler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/http-client-contracts": "^2.5|^3", + "symfony/process": "^6.4|^7.0", + "symfony/property-access": "^7.1", + "symfony/routing": "^6.4|^7.0", + "symfony/serializer": "^7.1", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/translation": "^6.4|^7.0", + "symfony/translation-contracts": "^2.5|^3", + "symfony/uid": "^6.4|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0", + "symfony/var-exporter": "^6.4|^7.0", + "twig/twig": "^3.12" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a structured process for converting a Request into a Response", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-kernel/tree/v7.3.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-08-29T08:23:45+00:00" + }, + { + "name": "symfony/mailer", + "version": "v7.3.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/mailer.git", + "reference": "a32f3f45f1990db8c4341d5122a7d3a381c7e575" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mailer/zipball/a32f3f45f1990db8c4341d5122a7d3a381c7e575", + "reference": "a32f3f45f1990db8c4341d5122a7d3a381c7e575", + "shasum": "" + }, + "require": { + "egulias/email-validator": "^2.1.10|^3|^4", + "php": ">=8.2", + "psr/event-dispatcher": "^1", + "psr/log": "^1|^2|^3", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/mime": "^7.2", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<6.4", + "symfony/messenger": "<6.4", + "symfony/mime": "<6.4", + "symfony/twig-bridge": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/twig-bridge": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mailer\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Helps sending emails", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/mailer/tree/v7.3.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-08-13T11:49:31+00:00" + }, + { + "name": "symfony/mime", + "version": "v7.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/mime.git", + "reference": "e0a0f859148daf1edf6c60b398eb40bfc96697d1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mime/zipball/e0a0f859148daf1edf6c60b398eb40bfc96697d1", + "reference": "e0a0f859148daf1edf6c60b398eb40bfc96697d1", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" + }, + "conflict": { + "egulias/email-validator": "~3.0.0", + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/mailer": "<6.4", + "symfony/serializer": "<6.4.3|>7.0,<7.0.3" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10|^3.1|^4", + "league/html-to-markdown": "^5.0", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/property-access": "^6.4|^7.0", + "symfony/property-info": "^6.4|^7.0", + "symfony/serializer": "^6.4.3|^7.0.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mime\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows manipulating MIME messages", + "homepage": "https://symfony.com", + "keywords": [ + "mime", + "mime-type" + ], + "support": { + "source": "https://github.com/symfony/mime/tree/v7.3.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-07-15T13:41:35+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70", + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-06-27T09:58:17+00:00" + }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "shasum": "" + }, + "require": { + "php": ">=7.2", + "symfony/polyfill-intl-normalizer": "^1.10" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Idn\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Trevor Rowbotham", + "email": "trevor.rowbotham@pm.me" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-10T14:38:51+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "3833d7255cc303546435cb650316bff708a1c75c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "php": ">=7.2" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-12-23T08:48:59+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-01-02T08:10:11+00:00" + }, + { + "name": "symfony/polyfill-php83", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php83.git", + "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/17f6f9a6b1735c0f163024d959f700cfbc5155e5", + "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php83\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php83/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-07-08T02:45:35+00:00" + }, + { + "name": "symfony/polyfill-php84", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php84.git", + "reference": "d8ced4d875142b6a7426000426b8abc631d6b191" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191", + "reference": "d8ced4d875142b6a7426000426b8abc631d6b191", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php84\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-06-24T13:30:11+00:00" + }, + { + "name": "symfony/polyfill-php85", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php85.git", + "reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91", + "reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php85\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.5+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php85/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-06-23T16:12:55+00:00" + }, + { + "name": "symfony/polyfill-uuid", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-uuid.git", + "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/21533be36c24be3f4b1669c4725c7d1d2bab4ae2", + "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-uuid": "*" + }, + "suggest": { + "ext-uuid": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Uuid\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for uuid functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "uuid" + ], + "support": { + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/process", + "version": "v7.3.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "32241012d521e2e8a9d713adb0812bb773b907f1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/32241012d521e2e8a9d713adb0812bb773b907f1", + "reference": "32241012d521e2e8a9d713adb0812bb773b907f1", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v7.3.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-08-18T09:42:54+00:00" + }, + { + "name": "symfony/routing", + "version": "v7.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/routing.git", + "reference": "7614b8ca5fa89b9cd233e21b627bfc5774f586e4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/routing/zipball/7614b8ca5fa89b9cd233e21b627bfc5774f586e4", + "reference": "7614b8ca5fa89b9cd233e21b627bfc5774f586e4", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/config": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/yaml": "<6.4" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Routing\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Maps an HTTP request to a set of configuration variables", + "homepage": "https://symfony.com", + "keywords": [ + "router", + "routing", + "uri", + "url" + ], + "support": { + "source": "https://github.com/symfony/routing/tree/v7.3.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-07-15T11:36:08+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-25T09:37:31+00:00" + }, + { + "name": "symfony/string", + "version": "v7.3.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "17a426cce5fd1f0901fefa9b2a490d0038fd3c9c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/17a426cce5fd1f0901fefa9b2a490d0038fd3c9c", + "reference": "17a426cce5fd1f0901fefa9b2a490d0038fd3c9c", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.5" + }, + "require-dev": { + "symfony/emoji": "^7.1", + "symfony/error-handler": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v7.3.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-08-25T06:35:40+00:00" + }, + { + "name": "symfony/translation", + "version": "v7.3.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "e0837b4cbcef63c754d89a4806575cada743a38d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/e0837b4cbcef63c754d89a4806575cada743a38d", + "reference": "e0837b4cbcef63c754d89a4806575cada743a38d", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^2.5|^3.0" + }, + "conflict": { + "nikic/php-parser": "<5.0", + "symfony/config": "<6.4", + "symfony/console": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<6.4", + "symfony/service-contracts": "<2.5", + "symfony/twig-bundle": "<6.4", + "symfony/yaml": "<6.4" + }, + "provide": { + "symfony/translation-implementation": "2.3|3.0" + }, + "require-dev": { + "nikic/php-parser": "^5.0", + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/http-client-contracts": "^2.5|^3.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", + "symfony/polyfill-intl-icu": "^1.21", + "symfony/routing": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to internationalize your application", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/translation/tree/v7.3.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-08-01T21:02:37+00:00" + }, + { + "name": "symfony/translation-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation-contracts.git", + "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/df210c7a2573f1913b2d17cc95f90f53a73d8f7d", + "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to translation", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/translation-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-27T08:32:26+00:00" + }, + { + "name": "symfony/uid", + "version": "v7.3.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/uid.git", + "reference": "a69f69f3159b852651a6bf45a9fdd149520525bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/uid/zipball/a69f69f3159b852651a6bf45a9fdd149520525bb", + "reference": "a69f69f3159b852651a6bf45a9fdd149520525bb", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-uuid": "^1.15" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Uid\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to generate and represent UIDs", + "homepage": "https://symfony.com", + "keywords": [ + "UID", + "ulid", + "uuid" + ], + "support": { + "source": "https://github.com/symfony/uid/tree/v7.3.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-06-27T19:55:54+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v7.3.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "34d8d4c4b9597347306d1ec8eb4e1319b1e6986f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/34d8d4c4b9597347306d1ec8eb4e1319b1e6986f", + "reference": "34d8d4c4b9597347306d1ec8eb4e1319b1e6986f", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/console": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/uid": "^6.4|^7.0", + "twig/twig": "^3.12" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides mechanisms for walking through any arbitrary PHP variable", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v7.3.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-08-13T11:49:31+00:00" + }, + { + "name": "tijsverkoyen/css-to-inline-styles", + "version": "v2.3.0", + "source": { + "type": "git", + "url": "https://github.com/tijsverkoyen/CssToInlineStyles.git", + "reference": "0d72ac1c00084279c1816675284073c5a337c20d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/0d72ac1c00084279c1816675284073c5a337c20d", + "reference": "0d72ac1c00084279c1816675284073c5a337c20d", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "php": "^7.4 || ^8.0", + "symfony/css-selector": "^5.4 || ^6.0 || ^7.0" + }, + "require-dev": { + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^8.5.21 || ^9.5.10" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "TijsVerkoyen\\CssToInlineStyles\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Tijs Verkoyen", + "email": "css_to_inline_styles@verkoyen.eu", + "role": "Developer" + } + ], + "description": "CssToInlineStyles is a class that enables you to convert HTML-pages/files into HTML-pages/files with inline styles. This is very useful when you're sending emails.", + "homepage": "https://github.com/tijsverkoyen/CssToInlineStyles", + "support": { + "issues": "https://github.com/tijsverkoyen/CssToInlineStyles/issues", + "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/v2.3.0" + }, + "time": "2024-12-21T16:25:41+00:00" + }, + { + "name": "vlucas/phpdotenv", + "version": "v5.6.2", + "source": { + "type": "git", + "url": "https://github.com/vlucas/phpdotenv.git", + "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/24ac4c74f91ee2c193fa1aaa5c249cb0822809af", + "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af", + "shasum": "" + }, + "require": { + "ext-pcre": "*", + "graham-campbell/result-type": "^1.1.3", + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.3", + "symfony/polyfill-ctype": "^1.24", + "symfony/polyfill-mbstring": "^1.24", + "symfony/polyfill-php80": "^1.24" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-filter": "*", + "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + }, + "suggest": { + "ext-filter": "Required to use the boolean validator." + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + }, + "branch-alias": { + "dev-master": "5.6-dev" + } + }, + "autoload": { + "psr-4": { + "Dotenv\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Vance Lucas", + "email": "vance@vancelucas.com", + "homepage": "https://github.com/vlucas" + } + ], + "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "support": { + "issues": "https://github.com/vlucas/phpdotenv/issues", + "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv", + "type": "tidelift" + } + ], + "time": "2025-04-30T23:37:27+00:00" + }, + { + "name": "voku/portable-ascii", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/voku/portable-ascii.git", + "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", + "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", + "shasum": "" + }, + "require": { + "php": ">=7.0.0" + }, + "require-dev": { + "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0" + }, + "suggest": { + "ext-intl": "Use Intl for transliterator_transliterate() support" + }, + "type": "library", + "autoload": { + "psr-4": { + "voku\\": "src/voku/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Lars Moelleken", + "homepage": "https://www.moelleken.org/" + } + ], + "description": "Portable ASCII library - performance optimized (ascii) string functions for php.", + "homepage": "https://github.com/voku/portable-ascii", + "keywords": [ + "ascii", + "clean", + "php" + ], + "support": { + "issues": "https://github.com/voku/portable-ascii/issues", + "source": "https://github.com/voku/portable-ascii/tree/2.0.3" + }, + "funding": [ + { + "url": "https://www.paypal.me/moelleken", + "type": "custom" + }, + { + "url": "https://github.com/voku", + "type": "github" + }, + { + "url": "https://opencollective.com/portable-ascii", + "type": "open_collective" + }, + { + "url": "https://www.patreon.com/voku", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii", + "type": "tidelift" + } + ], + "time": "2024-11-21T01:49:47+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" + } + ], + "packages-dev": [ + { + "name": "brianium/paratest", + "version": "v7.12.0", + "source": { + "type": "git", + "url": "https://github.com/paratestphp/paratest.git", + "reference": "6a34ddb12a3bd5bd07d831ce95f111087f3bcbd8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paratestphp/paratest/zipball/6a34ddb12a3bd5bd07d831ce95f111087f3bcbd8", + "reference": "6a34ddb12a3bd5bd07d831ce95f111087f3bcbd8", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-simplexml": "*", + "fidry/cpu-core-counter": "^1.3.0", + "jean85/pretty-package-versions": "^2.1.1", + "php": "~8.3.0 || ~8.4.0 || ~8.5.0", + "phpunit/php-code-coverage": "^12.3.2", + "phpunit/php-file-iterator": "^6", + "phpunit/php-timer": "^8", + "phpunit/phpunit": "^12.3.6", + "sebastian/environment": "^8.0.3", + "symfony/console": "^6.4.20 || ^7.3.2", + "symfony/process": "^6.4.20 || ^7.3.0" + }, + "require-dev": { + "doctrine/coding-standard": "^13.0.1", + "ext-pcntl": "*", + "ext-pcov": "*", + "ext-posix": "*", + "phpstan/phpstan": "^2.1.22", + "phpstan/phpstan-deprecation-rules": "^2.0.3", + "phpstan/phpstan-phpunit": "^2.0.7", + "phpstan/phpstan-strict-rules": "^2.0.6", + "squizlabs/php_codesniffer": "^3.13.2", + "symfony/filesystem": "^6.4.13 || ^7.3.2" + }, + "bin": [ + "bin/paratest", + "bin/paratest_for_phpstorm" + ], + "type": "library", + "autoload": { + "psr-4": { + "ParaTest\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Scaturro", + "email": "scaturrob@gmail.com", + "role": "Developer" + }, + { + "name": "Filippo Tessarotto", + "email": "zoeslam@gmail.com", + "role": "Developer" + } + ], + "description": "Parallel testing for PHP", + "homepage": "https://github.com/paratestphp/paratest", + "keywords": [ + "concurrent", + "parallel", + "phpunit", + "testing" + ], + "support": { + "issues": "https://github.com/paratestphp/paratest/issues", + "source": "https://github.com/paratestphp/paratest/tree/v7.12.0" + }, + "funding": [ + { + "url": "https://github.com/sponsors/Slamdunk", + "type": "github" + }, + { + "url": "https://paypal.me/filippotessarotto", + "type": "paypal" + } + ], + "time": "2025-08-29T05:28:31+00:00" + }, + { + "name": "doctrine/deprecations", + "version": "1.1.5", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", + "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "phpunit/phpunit": "<=7.5 || >=13" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^12 || ^13", + "phpstan/phpstan": "1.4.10 || 2.1.11", + "phpstan/phpstan-phpunit": "^1.0 || ^2", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12", + "psr/log": "^1 || ^2 || ^3" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/1.1.5" + }, + "time": "2025-04-07T20:06:18+00:00" + }, + { + "name": "fakerphp/faker", + "version": "v1.24.1", + "source": { + "type": "git", + "url": "https://github.com/FakerPHP/Faker.git", + "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5", + "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0", + "psr/container": "^1.0 || ^2.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "conflict": { + "fzaninotto/faker": "*" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "doctrine/persistence": "^1.3 || ^2.0", + "ext-intl": "*", + "phpunit/phpunit": "^9.5.26", + "symfony/phpunit-bridge": "^5.4.16" + }, + "suggest": { + "doctrine/orm": "Required to use Faker\\ORM\\Doctrine", + "ext-curl": "Required by Faker\\Provider\\Image to download images.", + "ext-dom": "Required by Faker\\Provider\\HtmlLorem for generating random HTML.", + "ext-iconv": "Required by Faker\\Provider\\ru_RU\\Text::realText() for generating real Russian text.", + "ext-mbstring": "Required for multibyte Unicode string functionality." + }, + "type": "library", + "autoload": { + "psr-4": { + "Faker\\": "src/Faker/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "François Zaninotto" + } + ], + "description": "Faker is a PHP library that generates fake data for you.", + "keywords": [ + "data", + "faker", + "fixtures" + ], + "support": { + "issues": "https://github.com/FakerPHP/Faker/issues", + "source": "https://github.com/FakerPHP/Faker/tree/v1.24.1" + }, + "time": "2024-11-21T13:46:39+00:00" + }, + { + "name": "fidry/cpu-core-counter", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/theofidry/cpu-core-counter.git", + "reference": "db9508f7b1474469d9d3c53b86f817e344732678" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/db9508f7b1474469d9d3c53b86f817e344732678", + "reference": "db9508f7b1474469d9d3c53b86f817e344732678", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "fidry/makefile": "^0.2.0", + "fidry/php-cs-fixer-config": "^1.1.2", + "phpstan/extension-installer": "^1.2.0", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-deprecation-rules": "^2.0.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^8.5.31 || ^9.5.26", + "webmozarts/strict-phpunit": "^7.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Fidry\\CpuCoreCounter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Théo FIDRY", + "email": "theo.fidry@gmail.com" + } + ], + "description": "Tiny utility to get the number of CPU cores.", + "keywords": [ + "CPU", + "core" + ], + "support": { + "issues": "https://github.com/theofidry/cpu-core-counter/issues", + "source": "https://github.com/theofidry/cpu-core-counter/tree/1.3.0" + }, + "funding": [ + { + "url": "https://github.com/theofidry", + "type": "github" + } + ], + "time": "2025-08-14T07:29:31+00:00" + }, + { + "name": "filp/whoops", + "version": "2.18.4", + "source": { + "type": "git", + "url": "https://github.com/filp/whoops.git", + "reference": "d2102955e48b9fd9ab24280a7ad12ed552752c4d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/filp/whoops/zipball/d2102955e48b9fd9ab24280a7ad12ed552752c4d", + "reference": "d2102955e48b9fd9ab24280a7ad12ed552752c4d", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0", + "psr/log": "^1.0.1 || ^2.0 || ^3.0" + }, + "require-dev": { + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^7.5.20 || ^8.5.8 || ^9.3.3", + "symfony/var-dumper": "^4.0 || ^5.0" + }, + "suggest": { + "symfony/var-dumper": "Pretty print complex values better with var-dumper available", + "whoops/soap": "Formats errors as SOAP responses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Whoops\\": "src/Whoops/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Filipe Dobreira", + "homepage": "https://github.com/filp", + "role": "Developer" + } + ], + "description": "php error handling for cool kids", + "homepage": "https://filp.github.io/whoops/", + "keywords": [ + "error", + "exception", + "handling", + "library", + "throwable", + "whoops" + ], + "support": { + "issues": "https://github.com/filp/whoops/issues", + "source": "https://github.com/filp/whoops/tree/2.18.4" + }, + "funding": [ + { + "url": "https://github.com/denis-sokolov", + "type": "github" + } + ], + "time": "2025-08-08T12:00:00+00:00" + }, + { + "name": "hamcrest/hamcrest-php", + "version": "v2.1.1", + "source": { + "type": "git", + "url": "https://github.com/hamcrest/hamcrest-php.git", + "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487", + "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0" + }, + "replace": { + "cordoval/hamcrest-php": "*", + "davedevelopment/hamcrest-php": "*", + "kodova/hamcrest-php": "*" + }, + "require-dev": { + "phpunit/php-file-iterator": "^1.4 || ^2.0 || ^3.0", + "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0 || ^8.0 || ^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "classmap": [ + "hamcrest" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "This is the PHP port of Hamcrest Matchers", + "keywords": [ + "test" + ], + "support": { + "issues": "https://github.com/hamcrest/hamcrest-php/issues", + "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.1.1" + }, + "time": "2025-04-30T06:54:44+00:00" + }, + { + "name": "jean85/pretty-package-versions", + "version": "2.1.1", + "source": { + "type": "git", + "url": "https://github.com/Jean85/pretty-package-versions.git", + "reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/4d7aa5dab42e2a76d99559706022885de0e18e1a", + "reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.1.0", + "php": "^7.4|^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.2", + "jean85/composer-provided-replaced-stub-package": "^1.0", + "phpstan/phpstan": "^2.0", + "phpunit/phpunit": "^7.5|^8.5|^9.6", + "rector/rector": "^2.0", + "vimeo/psalm": "^4.3 || ^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Jean85\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alessandro Lai", + "email": "alessandro.lai85@gmail.com" + } + ], + "description": "A library to get pretty versions strings of installed dependencies", + "keywords": [ + "composer", + "package", + "release", + "versions" + ], + "support": { + "issues": "https://github.com/Jean85/pretty-package-versions/issues", + "source": "https://github.com/Jean85/pretty-package-versions/tree/2.1.1" + }, + "time": "2025-03-19T14:43:43+00:00" + }, + { + "name": "laravel/breeze", + "version": "v2.3.8", + "source": { + "type": "git", + "url": "https://github.com/laravel/breeze.git", + "reference": "1a29c5792818bd4cddf70b5f743a227e02fbcfcd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/breeze/zipball/1a29c5792818bd4cddf70b5f743a227e02fbcfcd", + "reference": "1a29c5792818bd4cddf70b5f743a227e02fbcfcd", + "shasum": "" + }, + "require": { + "illuminate/console": "^11.0|^12.0", + "illuminate/filesystem": "^11.0|^12.0", + "illuminate/support": "^11.0|^12.0", + "illuminate/validation": "^11.0|^12.0", + "php": "^8.2.0", + "symfony/console": "^7.0" + }, + "require-dev": { + "laravel/framework": "^11.0|^12.0", + "orchestra/testbench-core": "^9.0|^10.0", + "phpstan/phpstan": "^2.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Breeze\\BreezeServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Breeze\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Minimal Laravel authentication scaffolding with Blade and Tailwind.", + "keywords": [ + "auth", + "laravel" + ], + "support": { + "issues": "https://github.com/laravel/breeze/issues", + "source": "https://github.com/laravel/breeze" + }, + "time": "2025-07-18T18:49:59+00:00" + }, + { + "name": "laravel/pail", + "version": "v1.2.3", + "source": { + "type": "git", + "url": "https://github.com/laravel/pail.git", + "reference": "8cc3d575c1f0e57eeb923f366a37528c50d2385a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/pail/zipball/8cc3d575c1f0e57eeb923f366a37528c50d2385a", + "reference": "8cc3d575c1f0e57eeb923f366a37528c50d2385a", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "illuminate/console": "^10.24|^11.0|^12.0", + "illuminate/contracts": "^10.24|^11.0|^12.0", + "illuminate/log": "^10.24|^11.0|^12.0", + "illuminate/process": "^10.24|^11.0|^12.0", + "illuminate/support": "^10.24|^11.0|^12.0", + "nunomaduro/termwind": "^1.15|^2.0", + "php": "^8.2", + "symfony/console": "^6.0|^7.0" + }, + "require-dev": { + "laravel/framework": "^10.24|^11.0|^12.0", + "laravel/pint": "^1.13", + "orchestra/testbench-core": "^8.13|^9.0|^10.0", + "pestphp/pest": "^2.20|^3.0", + "pestphp/pest-plugin-type-coverage": "^2.3|^3.0", + "phpstan/phpstan": "^1.12.27", + "symfony/var-dumper": "^6.3|^7.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Pail\\PailServiceProvider" + ] + }, + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\Pail\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Easily delve into your Laravel application's log files directly from the command line.", + "homepage": "https://github.com/laravel/pail", + "keywords": [ + "dev", + "laravel", + "logs", + "php", + "tail" + ], + "support": { + "issues": "https://github.com/laravel/pail/issues", + "source": "https://github.com/laravel/pail" + }, + "time": "2025-06-05T13:55:57+00:00" + }, + { + "name": "laravel/pint", + "version": "v1.25.1", + "source": { + "type": "git", + "url": "https://github.com/laravel/pint.git", + "reference": "5016e263f95d97670d71b9a987bd8996ade6d8d9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/pint/zipball/5016e263f95d97670d71b9a987bd8996ade6d8d9", + "reference": "5016e263f95d97670d71b9a987bd8996ade6d8d9", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "ext-tokenizer": "*", + "ext-xml": "*", + "php": "^8.2.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.87.2", + "illuminate/view": "^11.46.0", + "larastan/larastan": "^3.7.1", + "laravel-zero/framework": "^11.45.0", + "mockery/mockery": "^1.6.12", + "nunomaduro/termwind": "^2.3.1", + "pestphp/pest": "^2.36.0" + }, + "bin": [ + "builds/pint" + ], + "type": "project", + "autoload": { + "psr-4": { + "App\\": "app/", + "Database\\Seeders\\": "database/seeders/", + "Database\\Factories\\": "database/factories/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "An opinionated code formatter for PHP.", + "homepage": "https://laravel.com", + "keywords": [ + "format", + "formatter", + "lint", + "linter", + "php" + ], + "support": { + "issues": "https://github.com/laravel/pint/issues", + "source": "https://github.com/laravel/pint" + }, + "time": "2025-09-19T02:57:12+00:00" + }, + { + "name": "laravel/sail", + "version": "v1.45.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/sail.git", + "reference": "019a2933ff4a9199f098d4259713f9bc266a874e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/sail/zipball/019a2933ff4a9199f098d4259713f9bc266a874e", + "reference": "019a2933ff4a9199f098d4259713f9bc266a874e", + "shasum": "" + }, + "require": { + "illuminate/console": "^9.52.16|^10.0|^11.0|^12.0", + "illuminate/contracts": "^9.52.16|^10.0|^11.0|^12.0", + "illuminate/support": "^9.52.16|^10.0|^11.0|^12.0", + "php": "^8.0", + "symfony/console": "^6.0|^7.0", + "symfony/yaml": "^6.0|^7.0" + }, + "require-dev": { + "orchestra/testbench": "^7.0|^8.0|^9.0|^10.0", + "phpstan/phpstan": "^1.10" + }, + "bin": [ + "bin/sail" + ], + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Sail\\SailServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Sail\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Docker files for running a basic Laravel application.", + "keywords": [ + "docker", + "laravel" + ], + "support": { + "issues": "https://github.com/laravel/sail/issues", + "source": "https://github.com/laravel/sail" + }, + "time": "2025-08-25T19:28:31+00:00" + }, + { + "name": "mockery/mockery", + "version": "1.6.12", + "source": { + "type": "git", + "url": "https://github.com/mockery/mockery.git", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mockery/mockery/zipball/1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "shasum": "" + }, + "require": { + "hamcrest/hamcrest-php": "^2.0.1", + "lib-pcre": ">=7.0", + "php": ">=7.3" + }, + "conflict": { + "phpunit/phpunit": "<8.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.5 || ^9.6.17", + "symplify/easy-coding-standard": "^12.1.14" + }, + "type": "library", + "autoload": { + "files": [ + "library/helpers.php", + "library/Mockery.php" + ], + "psr-4": { + "Mockery\\": "library/Mockery" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "https://github.com/padraic", + "role": "Author" + }, + { + "name": "Dave Marshall", + "email": "dave.marshall@atstsolutions.co.uk", + "homepage": "https://davedevelopment.co.uk", + "role": "Developer" + }, + { + "name": "Nathanael Esayeas", + "email": "nathanael.esayeas@protonmail.com", + "homepage": "https://github.com/ghostwriter", + "role": "Lead Developer" + } + ], + "description": "Mockery is a simple yet flexible PHP mock object framework", + "homepage": "https://github.com/mockery/mockery", + "keywords": [ + "BDD", + "TDD", + "library", + "mock", + "mock objects", + "mockery", + "stub", + "test", + "test double", + "testing" + ], + "support": { + "docs": "https://docs.mockery.io/", + "issues": "https://github.com/mockery/mockery/issues", + "rss": "https://github.com/mockery/mockery/releases.atom", + "security": "https://github.com/mockery/mockery/security/advisories", + "source": "https://github.com/mockery/mockery" + }, + "time": "2024-05-16T03:13:13+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.13.4", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2025-08-01T08:46:24+00:00" + }, + { + "name": "nunomaduro/collision", + "version": "v8.8.2", + "source": { + "type": "git", + "url": "https://github.com/nunomaduro/collision.git", + "reference": "60207965f9b7b7a4ce15a0f75d57f9dadb105bdb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/60207965f9b7b7a4ce15a0f75d57f9dadb105bdb", + "reference": "60207965f9b7b7a4ce15a0f75d57f9dadb105bdb", + "shasum": "" + }, + "require": { + "filp/whoops": "^2.18.1", + "nunomaduro/termwind": "^2.3.1", + "php": "^8.2.0", + "symfony/console": "^7.3.0" + }, + "conflict": { + "laravel/framework": "<11.44.2 || >=13.0.0", + "phpunit/phpunit": "<11.5.15 || >=13.0.0" + }, + "require-dev": { + "brianium/paratest": "^7.8.3", + "larastan/larastan": "^3.4.2", + "laravel/framework": "^11.44.2 || ^12.18", + "laravel/pint": "^1.22.1", + "laravel/sail": "^1.43.1", + "laravel/sanctum": "^4.1.1", + "laravel/tinker": "^2.10.1", + "orchestra/testbench-core": "^9.12.0 || ^10.4", + "pestphp/pest": "^3.8.2", + "sebastian/environment": "^7.2.1 || ^8.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider" + ] + }, + "branch-alias": { + "dev-8.x": "8.x-dev" + } + }, + "autoload": { + "files": [ + "./src/Adapters/Phpunit/Autoload.php" + ], + "psr-4": { + "NunoMaduro\\Collision\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Cli error handling for console/command-line PHP applications.", + "keywords": [ + "artisan", + "cli", + "command-line", + "console", + "dev", + "error", + "handling", + "laravel", + "laravel-zero", + "php", + "symfony" + ], + "support": { + "issues": "https://github.com/nunomaduro/collision/issues", + "source": "https://github.com/nunomaduro/collision" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://www.patreon.com/nunomaduro", + "type": "patreon" + } + ], + "time": "2025-06-25T02:12:12+00:00" + }, + { + "name": "pestphp/pest", + "version": "v4.1.0", + "source": { + "type": "git", + "url": "https://github.com/pestphp/pest.git", + "reference": "b7406938ac9e8d08cf96f031922b0502a8523268" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pestphp/pest/zipball/b7406938ac9e8d08cf96f031922b0502a8523268", + "reference": "b7406938ac9e8d08cf96f031922b0502a8523268", + "shasum": "" + }, + "require": { + "brianium/paratest": "^7.12.0", + "nunomaduro/collision": "^8.8.2", + "nunomaduro/termwind": "^2.3.1", + "pestphp/pest-plugin": "^4.0.0", + "pestphp/pest-plugin-arch": "^4.0.0", + "pestphp/pest-plugin-mutate": "^4.0.1", + "pestphp/pest-plugin-profanity": "^4.1.0", + "php": "^8.3.0", + "phpunit/phpunit": "^12.3.8", + "symfony/process": "^7.3.3" + }, + "conflict": { + "filp/whoops": "<2.18.3", + "phpunit/phpunit": ">12.3.8", + "sebastian/exporter": "<7.0.0", + "webmozart/assert": "<1.11.0" + }, + "require-dev": { + "pestphp/pest-dev-tools": "^4.0.0", + "pestphp/pest-plugin-browser": "^4.1.0", + "pestphp/pest-plugin-type-coverage": "^4.0.2", + "psy/psysh": "^0.12.10" + }, + "bin": [ + "bin/pest" + ], + "type": "library", + "extra": { + "pest": { + "plugins": [ + "Pest\\Mutate\\Plugins\\Mutate", + "Pest\\Plugins\\Configuration", + "Pest\\Plugins\\Bail", + "Pest\\Plugins\\Cache", + "Pest\\Plugins\\Coverage", + "Pest\\Plugins\\Init", + "Pest\\Plugins\\Environment", + "Pest\\Plugins\\Help", + "Pest\\Plugins\\Memory", + "Pest\\Plugins\\Only", + "Pest\\Plugins\\Printer", + "Pest\\Plugins\\ProcessIsolation", + "Pest\\Plugins\\Profile", + "Pest\\Plugins\\Retry", + "Pest\\Plugins\\Snapshot", + "Pest\\Plugins\\Verbose", + "Pest\\Plugins\\Version", + "Pest\\Plugins\\Shard", + "Pest\\Plugins\\Parallel" + ] + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "files": [ + "src/Functions.php", + "src/Pest.php" + ], + "psr-4": { + "Pest\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "The elegant PHP Testing Framework.", + "keywords": [ + "framework", + "pest", + "php", + "test", + "testing", + "unit" + ], + "support": { + "issues": "https://github.com/pestphp/pest/issues", + "source": "https://github.com/pestphp/pest/tree/v4.1.0" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + } + ], + "time": "2025-09-10T13:41:09+00:00" + }, + { + "name": "pestphp/pest-plugin", + "version": "v4.0.0", + "source": { + "type": "git", + "url": "https://github.com/pestphp/pest-plugin.git", + "reference": "9d4b93d7f73d3f9c3189bb22c220fef271cdf568" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pestphp/pest-plugin/zipball/9d4b93d7f73d3f9c3189bb22c220fef271cdf568", + "reference": "9d4b93d7f73d3f9c3189bb22c220fef271cdf568", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^2.0.0", + "composer-runtime-api": "^2.2.2", + "php": "^8.3" + }, + "conflict": { + "pestphp/pest": "<4.0.0" + }, + "require-dev": { + "composer/composer": "^2.8.10", + "pestphp/pest": "^4.0.0", + "pestphp/pest-dev-tools": "^4.0.0" + }, + "type": "composer-plugin", + "extra": { + "class": "Pest\\Plugin\\Manager" + }, + "autoload": { + "psr-4": { + "Pest\\Plugin\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "The Pest plugin manager", + "keywords": [ + "framework", + "manager", + "pest", + "php", + "plugin", + "test", + "testing", + "unit" + ], + "support": { + "source": "https://github.com/pestphp/pest-plugin/tree/v4.0.0" + }, + "funding": [ + { + "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=66BYDWAT92N6L", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://www.patreon.com/nunomaduro", + "type": "patreon" + } + ], + "time": "2025-08-20T12:35:58+00:00" + }, + { + "name": "pestphp/pest-plugin-arch", + "version": "v4.0.0", + "source": { + "type": "git", + "url": "https://github.com/pestphp/pest-plugin-arch.git", + "reference": "25bb17e37920ccc35cbbcda3b00d596aadf3e58d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pestphp/pest-plugin-arch/zipball/25bb17e37920ccc35cbbcda3b00d596aadf3e58d", + "reference": "25bb17e37920ccc35cbbcda3b00d596aadf3e58d", + "shasum": "" + }, + "require": { + "pestphp/pest-plugin": "^4.0.0", + "php": "^8.3", + "ta-tikoma/phpunit-architecture-test": "^0.8.5" + }, + "require-dev": { + "pestphp/pest": "^4.0.0", + "pestphp/pest-dev-tools": "^4.0.0" + }, + "type": "library", + "extra": { + "pest": { + "plugins": [ + "Pest\\Arch\\Plugin" + ] + } + }, + "autoload": { + "files": [ + "src/Autoload.php" + ], + "psr-4": { + "Pest\\Arch\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "The Arch plugin for Pest PHP.", + "keywords": [ + "arch", + "architecture", + "framework", + "pest", + "php", + "plugin", + "test", + "testing", + "unit" + ], + "support": { + "source": "https://github.com/pestphp/pest-plugin-arch/tree/v4.0.0" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + } + ], + "time": "2025-08-20T13:10:51+00:00" + }, + { + "name": "pestphp/pest-plugin-laravel", + "version": "v4.0.0", + "source": { + "type": "git", + "url": "https://github.com/pestphp/pest-plugin-laravel.git", + "reference": "e12a07046b826a40b1c8632fd7b80d6b8d7b628e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pestphp/pest-plugin-laravel/zipball/e12a07046b826a40b1c8632fd7b80d6b8d7b628e", + "reference": "e12a07046b826a40b1c8632fd7b80d6b8d7b628e", + "shasum": "" + }, + "require": { + "laravel/framework": "^11.45.2|^12.25.0", + "pestphp/pest": "^4.0.0", + "php": "^8.3.0" + }, + "require-dev": { + "laravel/dusk": "^8.3.3", + "orchestra/testbench": "^9.13.0|^10.5.0", + "pestphp/pest-dev-tools": "^4.0.0" + }, + "type": "library", + "extra": { + "pest": { + "plugins": [ + "Pest\\Laravel\\Plugin" + ] + }, + "laravel": { + "providers": [ + "Pest\\Laravel\\PestServiceProvider" + ] + } + }, + "autoload": { + "files": [ + "src/Autoload.php" + ], + "psr-4": { + "Pest\\Laravel\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "The Pest Laravel Plugin", + "keywords": [ + "framework", + "laravel", + "pest", + "php", + "test", + "testing", + "unit" + ], + "support": { + "source": "https://github.com/pestphp/pest-plugin-laravel/tree/v4.0.0" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + } + ], + "time": "2025-08-20T12:46:37+00:00" + }, + { + "name": "pestphp/pest-plugin-mutate", + "version": "v4.0.1", + "source": { + "type": "git", + "url": "https://github.com/pestphp/pest-plugin-mutate.git", + "reference": "d9b32b60b2385e1688a68cc227594738ec26d96c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pestphp/pest-plugin-mutate/zipball/d9b32b60b2385e1688a68cc227594738ec26d96c", + "reference": "d9b32b60b2385e1688a68cc227594738ec26d96c", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.6.1", + "pestphp/pest-plugin": "^4.0.0", + "php": "^8.3", + "psr/simple-cache": "^3.0.0" + }, + "require-dev": { + "pestphp/pest": "^4.0.0", + "pestphp/pest-dev-tools": "^4.0.0", + "pestphp/pest-plugin-type-coverage": "^4.0.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Pest\\Mutate\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + }, + { + "name": "Sandro Gehri", + "email": "sandrogehri@gmail.com" + } + ], + "description": "Mutates your code to find untested cases", + "keywords": [ + "framework", + "mutate", + "mutation", + "pest", + "php", + "plugin", + "test", + "testing", + "unit" + ], + "support": { + "source": "https://github.com/pestphp/pest-plugin-mutate/tree/v4.0.1" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/gehrisandro", + "type": "github" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + } + ], + "time": "2025-08-21T20:19:25+00:00" + }, + { + "name": "pestphp/pest-plugin-profanity", + "version": "v4.1.0", + "source": { + "type": "git", + "url": "https://github.com/pestphp/pest-plugin-profanity.git", + "reference": "e279c844b6868da92052be27b5202c2ad7216e80" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pestphp/pest-plugin-profanity/zipball/e279c844b6868da92052be27b5202c2ad7216e80", + "reference": "e279c844b6868da92052be27b5202c2ad7216e80", + "shasum": "" + }, + "require": { + "pestphp/pest-plugin": "^4.0.0", + "php": "^8.3" + }, + "require-dev": { + "faissaloux/pest-plugin-inside": "^1.9", + "pestphp/pest": "^4.0.0", + "pestphp/pest-dev-tools": "^4.0.0" + }, + "type": "library", + "extra": { + "pest": { + "plugins": [ + "Pest\\Profanity\\Plugin" + ] + } + }, + "autoload": { + "psr-4": { + "Pest\\Profanity\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "The Pest Profanity Plugin", + "keywords": [ + "framework", + "pest", + "php", + "plugin", + "profanity", + "test", + "testing", + "unit" + ], + "support": { + "source": "https://github.com/pestphp/pest-plugin-profanity/tree/v4.1.0" + }, + "time": "2025-09-10T06:17:03+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, + "time": "2020-06-27T09:03:43+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "5.6.3", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "94f8051919d1b0369a6bcc7931d679a511c03fe9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94f8051919d1b0369a6bcc7931d679a511c03fe9", + "reference": "94f8051919d1b0369a6bcc7931d679a511c03fe9", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.1", + "ext-filter": "*", + "php": "^7.4 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^1.7", + "phpstan/phpdoc-parser": "^1.7|^2.0", + "webmozart/assert": "^1.9.1" + }, + "require-dev": { + "mockery/mockery": "~1.3.5 || ~1.6.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-webmozart-assert": "^1.2", + "phpunit/phpunit": "^9.5", + "psalm/phar": "^5.26" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.3" + }, + "time": "2025-08-01T19:43:32+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.10.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/679e3ce485b99e84c775d28e2e96fade9a7fb50a", + "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.0", + "php": "^7.3 || ^8.0", + "phpdocumentor/reflection-common": "^2.0", + "phpstan/phpdoc-parser": "^1.18|^2.0" + }, + "require-dev": { + "ext-tokenizer": "*", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^9.5", + "rector/rector": "^0.13.9", + "vimeo/psalm": "^4.25" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.10.0" + }, + "time": "2024-11-09T15:12:26+00:00" + }, + { + "name": "phpstan/phpdoc-parser", + "version": "2.3.0", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "1e0cd5370df5dd2e556a36b9c62f62e555870495" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/1e0cd5370df5dd2e556a36b9c62f62e555870495", + "reference": "1e0cd5370df5dd2e556a36b9c62f62e555870495", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^5.3.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6", + "symfony/process": "^5.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.0" + }, + "time": "2025-08-30T15:50:23+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "12.3.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "99e692c6a84708211f7536ba322bbbaef57ac7fc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/99e692c6a84708211f7536ba322bbbaef57ac7fc", + "reference": "99e692c6a84708211f7536ba322bbbaef57ac7fc", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^5.6.1", + "php": ">=8.3", + "phpunit/php-file-iterator": "^6.0", + "phpunit/php-text-template": "^5.0", + "sebastian/complexity": "^5.0", + "sebastian/environment": "^8.0.3", + "sebastian/lines-of-code": "^4.0", + "sebastian/version": "^6.0", + "theseer/tokenizer": "^1.2.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.3.7" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "12.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.3.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-code-coverage", + "type": "tidelift" + } + ], + "time": "2025-09-17T11:31:43+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "961bc913d42fe24a257bfff826a5068079ac7782" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/961bc913d42fe24a257bfff826a5068079ac7782", + "reference": "961bc913d42fe24a257bfff826a5068079ac7782", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:58:37+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "12b54e689b07a25a9b41e57736dfab6ec9ae5406" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/12b54e689b07a25a9b41e57736dfab6ec9ae5406", + "reference": "12b54e689b07a25a9b41e57736dfab6ec9ae5406", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^12.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:58:58+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "e1367a453f0eda562eedb4f659e13aa900d66c53" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/e1367a453f0eda562eedb4f659e13aa900d66c53", + "reference": "e1367a453f0eda562eedb4f659e13aa900d66c53", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:59:16+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "8.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "f258ce36aa457f3aa3339f9ed4c81fc66dc8c2cc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/f258ce36aa457f3aa3339f9ed4c81fc66dc8c2cc", + "reference": "f258ce36aa457f3aa3339f9ed4c81fc66dc8c2cc", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "8.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "security": "https://github.com/sebastianbergmann/php-timer/security/policy", + "source": "https://github.com/sebastianbergmann/php-timer/tree/8.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:59:38+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "12.3.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "9d68c1b41fc21aac106c71cde4669fe7b99fca10" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9d68c1b41fc21aac106c71cde4669fe7b99fca10", + "reference": "9d68c1b41fc21aac106c71cde4669fe7b99fca10", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.13.4", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=8.3", + "phpunit/php-code-coverage": "^12.3.6", + "phpunit/php-file-iterator": "^6.0.0", + "phpunit/php-invoker": "^6.0.0", + "phpunit/php-text-template": "^5.0.0", + "phpunit/php-timer": "^8.0.0", + "sebastian/cli-parser": "^4.0.0", + "sebastian/comparator": "^7.1.3", + "sebastian/diff": "^7.0.0", + "sebastian/environment": "^8.0.3", + "sebastian/exporter": "^7.0.0", + "sebastian/global-state": "^8.0.2", + "sebastian/object-enumerator": "^7.0.0", + "sebastian/type": "^6.0.3", + "sebastian/version": "^6.0.0", + "staabm/side-effects-detector": "^1.0.5" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "12.3-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/12.3.8" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2025-09-03T06:25:17+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "4.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "90f41072d220e5c40df6e8635f5dafba2d9d4d04" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/90f41072d220e5c40df6e8635f5dafba2d9d4d04", + "reference": "90f41072d220e5c40df6e8635f5dafba2d9d4d04", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/4.2.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/cli-parser", + "type": "tidelift" + } + ], + "time": "2025-09-14T09:36:45+00:00" + }, + { + "name": "sebastian/comparator", + "version": "7.1.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "dc904b4bb3ab070865fa4068cd84f3da8b945148" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/dc904b4bb3ab070865fa4068cd84f3da8b945148", + "reference": "dc904b4bb3ab070865fa4068cd84f3da8b945148", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.3", + "sebastian/diff": "^7.0", + "sebastian/exporter": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^12.2" + }, + "suggest": { + "ext-bcmath": "For comparing BcMath\\Number objects" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/7.1.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", + "type": "tidelift" + } + ], + "time": "2025-08-20T11:27:00+00:00" + }, + { + "name": "sebastian/complexity", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "bad4316aba5303d0221f43f8cee37eb58d384bbb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/bad4316aba5303d0221f43f8cee37eb58d384bbb", + "reference": "bad4316aba5303d0221f43f8cee37eb58d384bbb", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:55:25+00:00" + }, + { + "name": "sebastian/diff", + "version": "7.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "7ab1ea946c012266ca32390913653d844ecd085f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7ab1ea946c012266ca32390913653d844ecd085f", + "reference": "7ab1ea946c012266ca32390913653d844ecd085f", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0", + "symfony/process": "^7.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/7.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:55:46+00:00" + }, + { + "name": "sebastian/environment", + "version": "8.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "24a711b5c916efc6d6e62aa65aa2ec98fef77f68" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/24a711b5c916efc6d6e62aa65aa2ec98fef77f68", + "reference": "24a711b5c916efc6d6e62aa65aa2ec98fef77f68", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "8.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "https://github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/8.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/environment", + "type": "tidelift" + } + ], + "time": "2025-08-12T14:11:56+00:00" + }, + { + "name": "sebastian/exporter", + "version": "7.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "76432aafc58d50691a00d86d0632f1217a47b688" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/76432aafc58d50691a00d86d0632f1217a47b688", + "reference": "76432aafc58d50691a00d86d0632f1217a47b688", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=8.3", + "sebastian/recursion-context": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/7.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:56:42+00:00" + }, + { + "name": "sebastian/global-state", + "version": "8.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "ef1377171613d09edd25b7816f05be8313f9115d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/ef1377171613d09edd25b7816f05be8313f9115d", + "reference": "ef1377171613d09edd25b7816f05be8313f9115d", + "shasum": "" + }, + "require": { + "php": ">=8.3", + "sebastian/object-reflector": "^5.0", + "sebastian/recursion-context": "^7.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "8.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/8.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/global-state", + "type": "tidelift" + } + ], + "time": "2025-08-29T11:29:25+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "97ffee3bcfb5805568d6af7f0f893678fc076d2f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/97ffee3bcfb5805568d6af7f0f893678fc076d2f", + "reference": "97ffee3bcfb5805568d6af7f0f893678fc076d2f", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/4.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:57:28+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "7.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "1effe8e9b8e068e9ae228e542d5d11b5d16db894" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1effe8e9b8e068e9ae228e542d5d11b5d16db894", + "reference": "1effe8e9b8e068e9ae228e542d5d11b5d16db894", + "shasum": "" + }, + "require": { + "php": ">=8.3", + "sebastian/object-reflector": "^5.0", + "sebastian/recursion-context": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/7.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:57:48+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "4bfa827c969c98be1e527abd576533293c634f6a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/4bfa827c969c98be1e527abd576533293c634f6a", + "reference": "4bfa827c969c98be1e527abd576533293c634f6a", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:58:17+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "7.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "0b01998a7d5b1f122911a66bebcb8d46f0c82d8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/0b01998a7d5b1f122911a66bebcb8d46f0c82d8c", + "reference": "0b01998a7d5b1f122911a66bebcb8d46f0c82d8c", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/7.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", + "type": "tidelift" + } + ], + "time": "2025-08-13T04:44:59+00:00" + }, + { + "name": "sebastian/type", + "version": "6.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "e549163b9760b8f71f191651d22acf32d56d6d4d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/e549163b9760b8f71f191651d22acf32d56d6d4d", + "reference": "e549163b9760b8f71f191651d22acf32d56d6d4d", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/6.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/type", + "type": "tidelift" + } + ], + "time": "2025-08-09T06:57:12+00:00" + }, + { + "name": "sebastian/version", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "3e6ccf7657d4f0a59200564b08cead899313b53c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/3e6ccf7657d4f0a59200564b08cead899313b53c", + "reference": "3e6ccf7657d4f0a59200564b08cead899313b53c", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T05:00:38+00:00" + }, + { + "name": "staabm/side-effects-detector", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/staabm/side-effects-detector.git", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.6", + "phpunit/phpunit": "^9.6.21", + "symfony/var-dumper": "^5.4.43", + "tomasvotruba/type-coverage": "1.0.0", + "tomasvotruba/unused-public": "1.0.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A static analysis tool to detect side effects in PHP code", + "keywords": [ + "static analysis" + ], + "support": { + "issues": "https://github.com/staabm/side-effects-detector/issues", + "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" + }, + "funding": [ + { + "url": "https://github.com/staabm", + "type": "github" + } + ], + "time": "2024-10-20T05:08:20+00:00" + }, + { + "name": "symfony/yaml", + "version": "v7.3.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "d4f4a66866fe2451f61296924767280ab5732d9d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/d4f4a66866fe2451f61296924767280ab5732d9d", + "reference": "d4f4a66866fe2451f61296924767280ab5732d9d", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/console": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0" + }, + "bin": [ + "Resources/bin/yaml-lint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Loads and dumps YAML files", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/yaml/tree/v7.3.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-08-27T11:34:33+00:00" + }, + { + "name": "ta-tikoma/phpunit-architecture-test", + "version": "0.8.5", + "source": { + "type": "git", + "url": "https://github.com/ta-tikoma/phpunit-architecture-test.git", + "reference": "cf6fb197b676ba716837c886baca842e4db29005" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ta-tikoma/phpunit-architecture-test/zipball/cf6fb197b676ba716837c886baca842e4db29005", + "reference": "cf6fb197b676ba716837c886baca842e4db29005", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18.0 || ^5.0.0", + "php": "^8.1.0", + "phpdocumentor/reflection-docblock": "^5.3.0", + "phpunit/phpunit": "^10.5.5 || ^11.0.0 || ^12.0.0", + "symfony/finder": "^6.4.0 || ^7.0.0" + }, + "require-dev": { + "laravel/pint": "^1.13.7", + "phpstan/phpstan": "^1.10.52" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPUnit\\Architecture\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ni Shi", + "email": "futik0ma011@gmail.com" + }, + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Methods for testing application architecture", + "keywords": [ + "architecture", + "phpunit", + "stucture", + "test", + "testing" + ], + "support": { + "issues": "https://github.com/ta-tikoma/phpunit-architecture-test/issues", + "source": "https://github.com/ta-tikoma/phpunit-architecture-test/tree/0.8.5" + }, + "time": "2025-04-20T20:23:40+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:36:25+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": {}, + "prefer-stable": true, + "prefer-lowest": false, + "platform": { + "php": "^8.3" + }, + "platform-dev": {}, + "plugin-api-version": "2.6.0" +} diff --git a/config/app.php b/config/app.php new file mode 100644 index 0000000..423eed5 --- /dev/null +++ b/config/app.php @@ -0,0 +1,126 @@ + env('APP_NAME', 'Laravel'), + + /* + |-------------------------------------------------------------------------- + | Application Environment + |-------------------------------------------------------------------------- + | + | This value determines the "environment" your application is currently + | running in. This may determine how you prefer to configure various + | services the application utilizes. Set this in your ".env" file. + | + */ + + 'env' => env('APP_ENV', 'production'), + + /* + |-------------------------------------------------------------------------- + | Application Debug Mode + |-------------------------------------------------------------------------- + | + | When your application is in debug mode, detailed error messages with + | stack traces will be shown on every error that occurs within your + | application. If disabled, a simple generic error page is shown. + | + */ + + 'debug' => (bool) env('APP_DEBUG', false), + + /* + |-------------------------------------------------------------------------- + | Application URL + |-------------------------------------------------------------------------- + | + | This URL is used by the console to properly generate URLs when using + | the Artisan command line tool. You should set this to the root of + | the application so that it's available within Artisan commands. + | + */ + + 'url' => env('APP_URL', 'http://localhost'), + + /* + |-------------------------------------------------------------------------- + | Application Timezone + |-------------------------------------------------------------------------- + | + | Here you may specify the default timezone for your application, which + | will be used by the PHP date and date-time functions. The timezone + | is set to "UTC" by default as it is suitable for most use cases. + | + */ + + 'timezone' => 'UTC', + + /* + |-------------------------------------------------------------------------- + | Application Locale Configuration + |-------------------------------------------------------------------------- + | + | The application locale determines the default locale that will be used + | by Laravel's translation / localization methods. This option can be + | set to any locale for which you plan to have translation strings. + | + */ + + 'locale' => env('APP_LOCALE', 'en'), + + 'fallback_locale' => env('APP_FALLBACK_LOCALE', 'en'), + + 'faker_locale' => env('APP_FAKER_LOCALE', 'en_US'), + + /* + |-------------------------------------------------------------------------- + | Encryption Key + |-------------------------------------------------------------------------- + | + | This key is utilized by Laravel's encryption services and should be set + | to a random, 32 character string to ensure that all encrypted values + | are secure. You should do this prior to deploying the application. + | + */ + + 'cipher' => 'AES-256-CBC', + + 'key' => env('APP_KEY'), + + 'previous_keys' => [ + ...array_filter( + explode(',', (string) env('APP_PREVIOUS_KEYS', '')) + ), + ], + + /* + |-------------------------------------------------------------------------- + | Maintenance Mode Driver + |-------------------------------------------------------------------------- + | + | These configuration options determine the driver used to determine and + | manage Laravel's "maintenance mode" status. The "cache" driver will + | allow maintenance mode to be controlled across multiple machines. + | + | Supported drivers: "file", "cache" + | + */ + + 'maintenance' => [ + 'driver' => env('APP_MAINTENANCE_DRIVER', 'file'), + 'store' => env('APP_MAINTENANCE_STORE', 'database'), + ], + +]; diff --git a/config/auth.php b/config/auth.php new file mode 100644 index 0000000..48e4d3f --- /dev/null +++ b/config/auth.php @@ -0,0 +1,110 @@ + [ + 'guard' => env('AUTH_GUARD', 'web'), + 'passwords' => env('AUTH_PASSWORD_BROKER', 'users'), + ], + + /* + |-------------------------------------------------------------------------- + | Authentication Guards + |-------------------------------------------------------------------------- + | + | Next, you may define every authentication guard for your application. + | Of course, a great default configuration has been defined for you + | which utilizes session storage plus the Eloquent user provider. + | + | All authentication guards have a user provider, which defines how the + | users are actually retrieved out of your database or other storage + | system used by the application. Typically, Eloquent is utilized. + | + | Supported: "session" + | + */ + + 'guards' => [ + 'web' => [ + 'driver' => 'session', + 'provider' => 'users', + ], + ], + + /* + |-------------------------------------------------------------------------- + | User Providers + |-------------------------------------------------------------------------- + | + | All authentication guards have a user provider, which defines how the + | users are actually retrieved out of your database or other storage + | system used by the application. Typically, Eloquent is utilized. + | + | If you have multiple user tables or models you may configure multiple + | providers to represent the model / table. These providers may then + | be assigned to any extra authentication guards you have defined. + | + | Supported: "database", "eloquent" + | + */ + + 'providers' => [ + 'users' => [ + 'driver' => 'eloquent', + 'model' => env('AUTH_MODEL', App\Models\User::class), + ], + ], + + /* + |-------------------------------------------------------------------------- + | Resetting Passwords + |-------------------------------------------------------------------------- + | + | These configuration options specify the behavior of Laravel's password + | reset functionality, including the table utilized for token storage + | and the user provider that is invoked to actually retrieve users. + | + | The expiry time is the number of minutes that each reset token will be + | considered valid. This security feature keeps tokens short-lived so + | they have less time to be guessed. You may change this as needed. + | + | The throttle setting is the number of seconds a user must wait before + | generating more password reset tokens. This prevents the user from + | quickly generating a very large amount of password reset tokens. + | + */ + + 'passwords' => [ + 'users' => [ + 'provider' => 'users', + 'table' => env('AUTH_PASSWORD_RESET_TOKEN_TABLE', 'password_reset_tokens'), + 'expire' => 60, + 'throttle' => 60, + ], + ], + + /* + |-------------------------------------------------------------------------- + | Password Confirmation Timeout + |-------------------------------------------------------------------------- + | + | Here you may define the number of seconds before a password confirmation + | window expires and users are asked to re-enter their password via the + | confirmation screen. By default, the timeout lasts for three hours. + | + */ + + 'password_timeout' => env('AUTH_PASSWORD_TIMEOUT', 10800), + +]; diff --git a/config/cache.php b/config/cache.php new file mode 100644 index 0000000..c2d927d --- /dev/null +++ b/config/cache.php @@ -0,0 +1,108 @@ + env('CACHE_STORE', 'database'), + + /* + |-------------------------------------------------------------------------- + | Cache Stores + |-------------------------------------------------------------------------- + | + | Here you may define all of the cache "stores" for your application as + | well as their drivers. You may even define multiple stores for the + | same cache driver to group types of items stored in your caches. + | + | Supported drivers: "array", "database", "file", "memcached", + | "redis", "dynamodb", "octane", "null" + | + */ + + 'stores' => [ + + 'array' => [ + 'driver' => 'array', + 'serialize' => false, + ], + + 'database' => [ + 'driver' => 'database', + 'connection' => env('DB_CACHE_CONNECTION'), + 'table' => env('DB_CACHE_TABLE', 'cache'), + 'lock_connection' => env('DB_CACHE_LOCK_CONNECTION'), + 'lock_table' => env('DB_CACHE_LOCK_TABLE'), + ], + + 'file' => [ + 'driver' => 'file', + 'path' => storage_path('framework/cache/data'), + 'lock_path' => storage_path('framework/cache/data'), + ], + + 'memcached' => [ + 'driver' => 'memcached', + 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'), + 'sasl' => [ + env('MEMCACHED_USERNAME'), + env('MEMCACHED_PASSWORD'), + ], + 'options' => [ + // Memcached::OPT_CONNECT_TIMEOUT => 2000, + ], + 'servers' => [ + [ + 'host' => env('MEMCACHED_HOST', '127.0.0.1'), + 'port' => env('MEMCACHED_PORT', 11211), + 'weight' => 100, + ], + ], + ], + + 'redis' => [ + 'driver' => 'redis', + 'connection' => env('REDIS_CACHE_CONNECTION', 'cache'), + 'lock_connection' => env('REDIS_CACHE_LOCK_CONNECTION', 'default'), + ], + + 'dynamodb' => [ + 'driver' => 'dynamodb', + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + 'table' => env('DYNAMODB_CACHE_TABLE', 'cache'), + 'endpoint' => env('DYNAMODB_ENDPOINT'), + ], + + 'octane' => [ + 'driver' => 'octane', + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Cache Key Prefix + |-------------------------------------------------------------------------- + | + | When utilizing the APC, database, memcached, Redis, and DynamoDB cache + | stores, there might be other applications using the same cache. For + | that reason, you may prefix every cache key to avoid collisions. + | + */ + + 'prefix' => env('CACHE_PREFIX', Str::slug((string) env('APP_NAME', 'laravel')).'-cache-'), + +]; diff --git a/config/database.php b/config/database.php new file mode 100644 index 0000000..53dcae0 --- /dev/null +++ b/config/database.php @@ -0,0 +1,183 @@ + env('DB_CONNECTION', 'sqlite'), + + /* + |-------------------------------------------------------------------------- + | Database Connections + |-------------------------------------------------------------------------- + | + | Below are all of the database connections defined for your application. + | An example configuration is provided for each database system which + | is supported by Laravel. You're free to add / remove connections. + | + */ + + 'connections' => [ + + 'sqlite' => [ + 'driver' => 'sqlite', + 'url' => env('DB_URL'), + 'database' => env('DB_DATABASE', database_path('database.sqlite')), + 'prefix' => '', + 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true), + 'busy_timeout' => null, + 'journal_mode' => null, + 'synchronous' => null, + 'transaction_mode' => 'DEFERRED', + ], + + 'mysql' => [ + 'driver' => 'mysql', + 'url' => env('DB_URL'), + 'host' => env('DB_HOST', '127.0.0.1'), + 'port' => env('DB_PORT', '3306'), + 'database' => env('DB_DATABASE', 'laravel'), + 'username' => env('DB_USERNAME', 'root'), + 'password' => env('DB_PASSWORD', ''), + 'unix_socket' => env('DB_SOCKET', ''), + 'charset' => env('DB_CHARSET', 'utf8mb4'), + 'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'), + 'prefix' => '', + 'prefix_indexes' => true, + 'strict' => true, + 'engine' => null, + 'options' => extension_loaded('pdo_mysql') ? array_filter([ + PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), + ]) : [], + ], + + 'mariadb' => [ + 'driver' => 'mariadb', + 'url' => env('DB_URL'), + 'host' => env('DB_HOST', '127.0.0.1'), + 'port' => env('DB_PORT', '3306'), + 'database' => env('DB_DATABASE', 'laravel'), + 'username' => env('DB_USERNAME', 'root'), + 'password' => env('DB_PASSWORD', ''), + 'unix_socket' => env('DB_SOCKET', ''), + 'charset' => env('DB_CHARSET', 'utf8mb4'), + 'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'), + 'prefix' => '', + 'prefix_indexes' => true, + 'strict' => true, + 'engine' => null, + 'options' => extension_loaded('pdo_mysql') ? array_filter([ + PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), + ]) : [], + ], + + 'pgsql' => [ + 'driver' => 'pgsql', + 'url' => env('DB_URL'), + 'host' => env('DB_HOST', '127.0.0.1'), + 'port' => env('DB_PORT', '5432'), + 'database' => env('DB_DATABASE', 'laravel'), + 'username' => env('DB_USERNAME', 'root'), + 'password' => env('DB_PASSWORD', ''), + 'charset' => env('DB_CHARSET', 'utf8'), + 'prefix' => '', + 'prefix_indexes' => true, + 'search_path' => 'public', + 'sslmode' => 'prefer', + ], + + 'sqlsrv' => [ + 'driver' => 'sqlsrv', + 'url' => env('DB_URL'), + 'host' => env('DB_HOST', 'localhost'), + 'port' => env('DB_PORT', '1433'), + 'database' => env('DB_DATABASE', 'laravel'), + 'username' => env('DB_USERNAME', 'root'), + 'password' => env('DB_PASSWORD', ''), + 'charset' => env('DB_CHARSET', 'utf8'), + 'prefix' => '', + 'prefix_indexes' => true, + // 'encrypt' => env('DB_ENCRYPT', 'yes'), + // 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'false'), + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Migration Repository Table + |-------------------------------------------------------------------------- + | + | This table keeps track of all the migrations that have already run for + | your application. Using this information, we can determine which of + | the migrations on disk haven't actually been run on the database. + | + */ + + 'migrations' => [ + 'table' => 'migrations', + 'update_date_on_publish' => true, + ], + + /* + |-------------------------------------------------------------------------- + | Redis Databases + |-------------------------------------------------------------------------- + | + | Redis is an open source, fast, and advanced key-value store that also + | provides a richer body of commands than a typical key-value system + | such as Memcached. You may define your connection settings here. + | + */ + + 'redis' => [ + + 'client' => env('REDIS_CLIENT', 'phpredis'), + + 'options' => [ + 'cluster' => env('REDIS_CLUSTER', 'redis'), + 'prefix' => env('REDIS_PREFIX', Str::slug((string) env('APP_NAME', 'laravel')).'-database-'), + 'persistent' => env('REDIS_PERSISTENT', false), + ], + + 'default' => [ + 'url' => env('REDIS_URL'), + 'host' => env('REDIS_HOST', '127.0.0.1'), + 'username' => env('REDIS_USERNAME'), + 'password' => env('REDIS_PASSWORD'), + 'port' => env('REDIS_PORT', '6379'), + 'database' => env('REDIS_DB', '0'), + 'max_retries' => env('REDIS_MAX_RETRIES', 3), + 'backoff_algorithm' => env('REDIS_BACKOFF_ALGORITHM', 'decorrelated_jitter'), + 'backoff_base' => env('REDIS_BACKOFF_BASE', 100), + 'backoff_cap' => env('REDIS_BACKOFF_CAP', 1000), + ], + + 'cache' => [ + 'url' => env('REDIS_URL'), + 'host' => env('REDIS_HOST', '127.0.0.1'), + 'username' => env('REDIS_USERNAME'), + 'password' => env('REDIS_PASSWORD'), + 'port' => env('REDIS_PORT', '6379'), + 'database' => env('REDIS_CACHE_DB', '1'), + 'max_retries' => env('REDIS_MAX_RETRIES', 3), + 'backoff_algorithm' => env('REDIS_BACKOFF_ALGORITHM', 'decorrelated_jitter'), + 'backoff_base' => env('REDIS_BACKOFF_BASE', 100), + 'backoff_cap' => env('REDIS_BACKOFF_CAP', 1000), + ], + + ], + +]; diff --git a/config/filesystems.php b/config/filesystems.php new file mode 100644 index 0000000..3d671bd --- /dev/null +++ b/config/filesystems.php @@ -0,0 +1,80 @@ + env('FILESYSTEM_DISK', 'local'), + + /* + |-------------------------------------------------------------------------- + | Filesystem Disks + |-------------------------------------------------------------------------- + | + | Below you may configure as many filesystem disks as necessary, and you + | may even configure multiple disks for the same driver. Examples for + | most supported storage drivers are configured here for reference. + | + | Supported drivers: "local", "ftp", "sftp", "s3" + | + */ + + 'disks' => [ + + 'local' => [ + 'driver' => 'local', + 'root' => storage_path('app/private'), + 'serve' => true, + 'throw' => false, + 'report' => false, + ], + + 'public' => [ + 'driver' => 'local', + 'root' => storage_path('app/public'), + 'url' => env('APP_URL').'/storage', + 'visibility' => 'public', + 'throw' => false, + 'report' => false, + ], + + 's3' => [ + 'driver' => 's3', + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION'), + 'bucket' => env('AWS_BUCKET'), + 'url' => env('AWS_URL'), + 'endpoint' => env('AWS_ENDPOINT'), + 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), + 'throw' => false, + 'report' => false, + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Symbolic Links + |-------------------------------------------------------------------------- + | + | Here you may configure the symbolic links that will be created when the + | `storage:link` Artisan command is executed. The array keys should be + | the locations of the links and the values should be their targets. + | + */ + + 'links' => [ + public_path('storage') => storage_path('app/public'), + ], + +]; diff --git a/config/logging.php b/config/logging.php new file mode 100644 index 0000000..9e998a4 --- /dev/null +++ b/config/logging.php @@ -0,0 +1,132 @@ + env('LOG_CHANNEL', 'stack'), + + /* + |-------------------------------------------------------------------------- + | Deprecations Log Channel + |-------------------------------------------------------------------------- + | + | This option controls the log channel that should be used to log warnings + | regarding deprecated PHP and library features. This allows you to get + | your application ready for upcoming major versions of dependencies. + | + */ + + 'deprecations' => [ + 'channel' => env('LOG_DEPRECATIONS_CHANNEL', 'null'), + 'trace' => env('LOG_DEPRECATIONS_TRACE', false), + ], + + /* + |-------------------------------------------------------------------------- + | Log Channels + |-------------------------------------------------------------------------- + | + | Here you may configure the log channels for your application. Laravel + | utilizes the Monolog PHP logging library, which includes a variety + | of powerful log handlers and formatters that you're free to use. + | + | Available drivers: "single", "daily", "slack", "syslog", + | "errorlog", "monolog", "custom", "stack" + | + */ + + 'channels' => [ + + 'stack' => [ + 'driver' => 'stack', + 'channels' => explode(',', (string) env('LOG_STACK', 'single')), + 'ignore_exceptions' => false, + ], + + 'single' => [ + 'driver' => 'single', + 'path' => storage_path('logs/laravel.log'), + 'level' => env('LOG_LEVEL', 'debug'), + 'replace_placeholders' => true, + ], + + 'daily' => [ + 'driver' => 'daily', + 'path' => storage_path('logs/laravel.log'), + 'level' => env('LOG_LEVEL', 'debug'), + 'days' => env('LOG_DAILY_DAYS', 14), + 'replace_placeholders' => true, + ], + + 'slack' => [ + 'driver' => 'slack', + 'url' => env('LOG_SLACK_WEBHOOK_URL'), + 'username' => env('LOG_SLACK_USERNAME', 'Laravel Log'), + 'emoji' => env('LOG_SLACK_EMOJI', ':boom:'), + 'level' => env('LOG_LEVEL', 'critical'), + 'replace_placeholders' => true, + ], + + 'papertrail' => [ + 'driver' => 'monolog', + 'level' => env('LOG_LEVEL', 'debug'), + 'handler' => env('LOG_PAPERTRAIL_HANDLER', SyslogUdpHandler::class), + 'handler_with' => [ + 'host' => env('PAPERTRAIL_URL'), + 'port' => env('PAPERTRAIL_PORT'), + 'connectionString' => 'tls://'.env('PAPERTRAIL_URL').':'.env('PAPERTRAIL_PORT'), + ], + 'processors' => [PsrLogMessageProcessor::class], + ], + + 'stderr' => [ + 'driver' => 'monolog', + 'level' => env('LOG_LEVEL', 'debug'), + 'handler' => StreamHandler::class, + 'handler_with' => [ + 'stream' => 'php://stderr', + ], + 'formatter' => env('LOG_STDERR_FORMATTER'), + 'processors' => [PsrLogMessageProcessor::class], + ], + + 'syslog' => [ + 'driver' => 'syslog', + 'level' => env('LOG_LEVEL', 'debug'), + 'facility' => env('LOG_SYSLOG_FACILITY', LOG_USER), + 'replace_placeholders' => true, + ], + + 'errorlog' => [ + 'driver' => 'errorlog', + 'level' => env('LOG_LEVEL', 'debug'), + 'replace_placeholders' => true, + ], + + 'null' => [ + 'driver' => 'monolog', + 'handler' => NullHandler::class, + ], + + 'emergency' => [ + 'path' => storage_path('logs/laravel.log'), + ], + + ], + +]; diff --git a/config/mail.php b/config/mail.php new file mode 100644 index 0000000..522b284 --- /dev/null +++ b/config/mail.php @@ -0,0 +1,118 @@ + env('MAIL_MAILER', 'log'), + + /* + |-------------------------------------------------------------------------- + | Mailer Configurations + |-------------------------------------------------------------------------- + | + | Here you may configure all of the mailers used by your application plus + | their respective settings. Several examples have been configured for + | you and you are free to add your own as your application requires. + | + | Laravel supports a variety of mail "transport" drivers that can be used + | when delivering an email. You may specify which one you're using for + | your mailers below. You may also add additional mailers if needed. + | + | Supported: "smtp", "sendmail", "mailgun", "ses", "ses-v2", + | "postmark", "resend", "log", "array", + | "failover", "roundrobin" + | + */ + + 'mailers' => [ + + 'smtp' => [ + 'transport' => 'smtp', + 'scheme' => env('MAIL_SCHEME'), + 'url' => env('MAIL_URL'), + 'host' => env('MAIL_HOST', '127.0.0.1'), + 'port' => env('MAIL_PORT', 2525), + 'username' => env('MAIL_USERNAME'), + 'password' => env('MAIL_PASSWORD'), + 'timeout' => null, + 'local_domain' => env('MAIL_EHLO_DOMAIN', parse_url((string) env('APP_URL', 'http://localhost'), PHP_URL_HOST)), + ], + + 'ses' => [ + 'transport' => 'ses', + ], + + 'postmark' => [ + 'transport' => 'postmark', + // 'message_stream_id' => env('POSTMARK_MESSAGE_STREAM_ID'), + // 'client' => [ + // 'timeout' => 5, + // ], + ], + + 'resend' => [ + 'transport' => 'resend', + ], + + 'sendmail' => [ + 'transport' => 'sendmail', + 'path' => env('MAIL_SENDMAIL_PATH', '/usr/sbin/sendmail -bs -i'), + ], + + 'log' => [ + 'transport' => 'log', + 'channel' => env('MAIL_LOG_CHANNEL'), + ], + + 'array' => [ + 'transport' => 'array', + ], + + 'failover' => [ + 'transport' => 'failover', + 'mailers' => [ + 'smtp', + 'log', + ], + 'retry_after' => 60, + ], + + 'roundrobin' => [ + 'transport' => 'roundrobin', + 'mailers' => [ + 'ses', + 'postmark', + ], + 'retry_after' => 60, + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Global "From" Address + |-------------------------------------------------------------------------- + | + | You may wish for all emails sent by your application to be sent from + | the same address. Here you may specify a name and address that is + | used globally for all emails that are sent by your application. + | + */ + + 'from' => [ + 'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'), + 'name' => env('MAIL_FROM_NAME', 'Example'), + ], + +]; diff --git a/config/queue.php b/config/queue.php new file mode 100644 index 0000000..116bd8d --- /dev/null +++ b/config/queue.php @@ -0,0 +1,112 @@ + env('QUEUE_CONNECTION', 'database'), + + /* + |-------------------------------------------------------------------------- + | Queue Connections + |-------------------------------------------------------------------------- + | + | Here you may configure the connection options for every queue backend + | used by your application. An example configuration is provided for + | each backend supported by Laravel. You're also free to add more. + | + | Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null" + | + */ + + 'connections' => [ + + 'sync' => [ + 'driver' => 'sync', + ], + + 'database' => [ + 'driver' => 'database', + 'connection' => env('DB_QUEUE_CONNECTION'), + 'table' => env('DB_QUEUE_TABLE', 'jobs'), + 'queue' => env('DB_QUEUE', 'default'), + 'retry_after' => (int) env('DB_QUEUE_RETRY_AFTER', 90), + 'after_commit' => false, + ], + + 'beanstalkd' => [ + 'driver' => 'beanstalkd', + 'host' => env('BEANSTALKD_QUEUE_HOST', 'localhost'), + 'queue' => env('BEANSTALKD_QUEUE', 'default'), + 'retry_after' => (int) env('BEANSTALKD_QUEUE_RETRY_AFTER', 90), + 'block_for' => 0, + 'after_commit' => false, + ], + + 'sqs' => [ + 'driver' => 'sqs', + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'), + 'queue' => env('SQS_QUEUE', 'default'), + 'suffix' => env('SQS_SUFFIX'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + 'after_commit' => false, + ], + + 'redis' => [ + 'driver' => 'redis', + 'connection' => env('REDIS_QUEUE_CONNECTION', 'default'), + 'queue' => env('REDIS_QUEUE', 'default'), + 'retry_after' => (int) env('REDIS_QUEUE_RETRY_AFTER', 90), + 'block_for' => null, + 'after_commit' => false, + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Job Batching + |-------------------------------------------------------------------------- + | + | The following options configure the database and table that store job + | batching information. These options can be updated to any database + | connection and table which has been defined by your application. + | + */ + + 'batching' => [ + 'database' => env('DB_CONNECTION', 'sqlite'), + 'table' => 'job_batches', + ], + + /* + |-------------------------------------------------------------------------- + | Failed Queue Jobs + |-------------------------------------------------------------------------- + | + | These options configure the behavior of failed queue job logging so you + | can control how and where failed jobs are stored. Laravel ships with + | support for storing failed jobs in a simple file or in a database. + | + | Supported drivers: "database-uuids", "dynamodb", "file", "null" + | + */ + + 'failed' => [ + 'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'), + 'database' => env('DB_CONNECTION', 'sqlite'), + 'table' => 'failed_jobs', + ], + +]; diff --git a/config/services.php b/config/services.php new file mode 100644 index 0000000..6182e4b --- /dev/null +++ b/config/services.php @@ -0,0 +1,38 @@ + [ + 'token' => env('POSTMARK_TOKEN'), + ], + + 'resend' => [ + 'key' => env('RESEND_KEY'), + ], + + 'ses' => [ + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + ], + + 'slack' => [ + 'notifications' => [ + 'bot_user_oauth_token' => env('SLACK_BOT_USER_OAUTH_TOKEN'), + 'channel' => env('SLACK_BOT_USER_DEFAULT_CHANNEL'), + ], + ], + +]; diff --git a/config/session.php b/config/session.php new file mode 100644 index 0000000..f715097 --- /dev/null +++ b/config/session.php @@ -0,0 +1,217 @@ + env('SESSION_DRIVER', 'database'), + + /* + |-------------------------------------------------------------------------- + | Session Lifetime + |-------------------------------------------------------------------------- + | + | Here you may specify the number of minutes that you wish the session + | to be allowed to remain idle before it expires. If you want them + | to expire immediately when the browser is closed then you may + | indicate that via the expire_on_close configuration option. + | + */ + + 'lifetime' => (int) env('SESSION_LIFETIME', 120), + + 'expire_on_close' => env('SESSION_EXPIRE_ON_CLOSE', false), + + /* + |-------------------------------------------------------------------------- + | Session Encryption + |-------------------------------------------------------------------------- + | + | This option allows you to easily specify that all of your session data + | should be encrypted before it's stored. All encryption is performed + | automatically by Laravel and you may use the session like normal. + | + */ + + 'encrypt' => env('SESSION_ENCRYPT', false), + + /* + |-------------------------------------------------------------------------- + | Session File Location + |-------------------------------------------------------------------------- + | + | When utilizing the "file" session driver, the session files are placed + | on disk. The default storage location is defined here; however, you + | are free to provide another location where they should be stored. + | + */ + + 'files' => storage_path('framework/sessions'), + + /* + |-------------------------------------------------------------------------- + | Session Database Connection + |-------------------------------------------------------------------------- + | + | When using the "database" or "redis" session drivers, you may specify a + | connection that should be used to manage these sessions. This should + | correspond to a connection in your database configuration options. + | + */ + + 'connection' => env('SESSION_CONNECTION'), + + /* + |-------------------------------------------------------------------------- + | Session Database Table + |-------------------------------------------------------------------------- + | + | When using the "database" session driver, you may specify the table to + | be used to store sessions. Of course, a sensible default is defined + | for you; however, you're welcome to change this to another table. + | + */ + + 'table' => env('SESSION_TABLE', 'sessions'), + + /* + |-------------------------------------------------------------------------- + | Session Cache Store + |-------------------------------------------------------------------------- + | + | When using one of the framework's cache driven session backends, you may + | define the cache store which should be used to store the session data + | between requests. This must match one of your defined cache stores. + | + | Affects: "dynamodb", "memcached", "redis" + | + */ + + 'store' => env('SESSION_STORE'), + + /* + |-------------------------------------------------------------------------- + | Session Sweeping Lottery + |-------------------------------------------------------------------------- + | + | Some session drivers must manually sweep their storage location to get + | rid of old sessions from storage. Here are the chances that it will + | happen on a given request. By default, the odds are 2 out of 100. + | + */ + + 'lottery' => [2, 100], + + /* + |-------------------------------------------------------------------------- + | Session Cookie Name + |-------------------------------------------------------------------------- + | + | Here you may change the name of the session cookie that is created by + | the framework. Typically, you should not need to change this value + | since doing so does not grant a meaningful security improvement. + | + */ + + 'cookie' => env( + 'SESSION_COOKIE', + Str::slug(env('APP_NAME', 'laravel')).'-session' + ), + + /* + |-------------------------------------------------------------------------- + | Session Cookie Path + |-------------------------------------------------------------------------- + | + | The session cookie path determines the path for which the cookie will + | be regarded as available. Typically, this will be the root path of + | your application, but you're free to change this when necessary. + | + */ + + 'path' => env('SESSION_PATH', '/'), + + /* + |-------------------------------------------------------------------------- + | Session Cookie Domain + |-------------------------------------------------------------------------- + | + | This value determines the domain and subdomains the session cookie is + | available to. By default, the cookie will be available to the root + | domain and all subdomains. Typically, this shouldn't be changed. + | + */ + + 'domain' => env('SESSION_DOMAIN'), + + /* + |-------------------------------------------------------------------------- + | HTTPS Only Cookies + |-------------------------------------------------------------------------- + | + | By setting this option to true, session cookies will only be sent back + | to the server if the browser has a HTTPS connection. This will keep + | the cookie from being sent to you when it can't be done securely. + | + */ + + 'secure' => env('SESSION_SECURE_COOKIE'), + + /* + |-------------------------------------------------------------------------- + | HTTP Access Only + |-------------------------------------------------------------------------- + | + | Setting this value to true will prevent JavaScript from accessing the + | value of the cookie and the cookie will only be accessible through + | the HTTP protocol. It's unlikely you should disable this option. + | + */ + + 'http_only' => env('SESSION_HTTP_ONLY', true), + + /* + |-------------------------------------------------------------------------- + | Same-Site Cookies + |-------------------------------------------------------------------------- + | + | This option determines how your cookies behave when cross-site requests + | take place, and can be used to mitigate CSRF attacks. By default, we + | will set this value to "lax" to permit secure cross-site requests. + | + | See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#samesitesamesite-value + | + | Supported: "lax", "strict", "none", null + | + */ + + 'same_site' => env('SESSION_SAME_SITE', 'lax'), + + /* + |-------------------------------------------------------------------------- + | Partitioned Cookies + |-------------------------------------------------------------------------- + | + | Setting this value to true will tie the cookie to the top-level site for + | a cross-site context. Partitioned cookies are accepted by the browser + | when flagged "secure" and the Same-Site attribute is set to "none". + | + */ + + 'partitioned' => env('SESSION_PARTITIONED_COOKIE', false), + +]; diff --git a/database/.gitignore b/database/.gitignore new file mode 100644 index 0000000..9b19b93 --- /dev/null +++ b/database/.gitignore @@ -0,0 +1 @@ +*.sqlite* diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php new file mode 100644 index 0000000..584104c --- /dev/null +++ b/database/factories/UserFactory.php @@ -0,0 +1,44 @@ + + */ +class UserFactory extends Factory +{ + /** + * The current password being used by the factory. + */ + protected static ?string $password; + + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + 'name' => fake()->name(), + 'email' => fake()->unique()->safeEmail(), + 'email_verified_at' => now(), + 'password' => static::$password ??= Hash::make('password'), + 'remember_token' => Str::random(10), + ]; + } + + /** + * Indicate that the model's email address should be unverified. + */ + public function unverified(): static + { + return $this->state(fn (array $attributes) => [ + 'email_verified_at' => null, + ]); + } +} diff --git a/database/migrations/0001_01_01_000000_create_users_table.php b/database/migrations/0001_01_01_000000_create_users_table.php new file mode 100644 index 0000000..2e24fd0 --- /dev/null +++ b/database/migrations/0001_01_01_000000_create_users_table.php @@ -0,0 +1,55 @@ +id(); + $table->string('name'); + $table->string('email')->unique(); + $table->timestamp('email_verified_at')->nullable(); + $table->string('password'); + $table->string('role')->default('siswa'); + $table->string('nisn')->nullable(); + $table->string('nip')->nullable(); + $table->string('no_hp')->nullable(); + $table->string('golongan')->nullable(); + $table->string('kelas')->nullable(); + $table->rememberToken(); + $table->timestamps(); + }); + + Schema::create('password_reset_tokens', function (Blueprint $table) { + $table->string('email')->primary(); + $table->string('token'); + $table->timestamp('created_at')->nullable(); + }); + + Schema::create('sessions', function (Blueprint $table) { + $table->string('id')->primary(); + $table->foreignId('user_id')->nullable()->index(); + $table->string('ip_address', 45)->nullable(); + $table->text('user_agent')->nullable(); + $table->longText('payload'); + $table->integer('last_activity')->index(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('users'); + Schema::dropIfExists('password_reset_tokens'); + Schema::dropIfExists('sessions'); + } +}; diff --git a/database/migrations/0001_01_01_000001_create_cache_table.php b/database/migrations/0001_01_01_000001_create_cache_table.php new file mode 100644 index 0000000..b9c106b --- /dev/null +++ b/database/migrations/0001_01_01_000001_create_cache_table.php @@ -0,0 +1,35 @@ +string('key')->primary(); + $table->mediumText('value'); + $table->integer('expiration'); + }); + + Schema::create('cache_locks', function (Blueprint $table) { + $table->string('key')->primary(); + $table->string('owner'); + $table->integer('expiration'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('cache'); + Schema::dropIfExists('cache_locks'); + } +}; diff --git a/database/migrations/0001_01_01_000002_create_jobs_table.php b/database/migrations/0001_01_01_000002_create_jobs_table.php new file mode 100644 index 0000000..425e705 --- /dev/null +++ b/database/migrations/0001_01_01_000002_create_jobs_table.php @@ -0,0 +1,57 @@ +id(); + $table->string('queue')->index(); + $table->longText('payload'); + $table->unsignedTinyInteger('attempts'); + $table->unsignedInteger('reserved_at')->nullable(); + $table->unsignedInteger('available_at'); + $table->unsignedInteger('created_at'); + }); + + Schema::create('job_batches', function (Blueprint $table) { + $table->string('id')->primary(); + $table->string('name'); + $table->integer('total_jobs'); + $table->integer('pending_jobs'); + $table->integer('failed_jobs'); + $table->longText('failed_job_ids'); + $table->mediumText('options')->nullable(); + $table->integer('cancelled_at')->nullable(); + $table->integer('created_at'); + $table->integer('finished_at')->nullable(); + }); + + Schema::create('failed_jobs', function (Blueprint $table) { + $table->id(); + $table->string('uuid')->unique(); + $table->text('connection'); + $table->text('queue'); + $table->longText('payload'); + $table->longText('exception'); + $table->timestamp('failed_at')->useCurrent(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('jobs'); + Schema::dropIfExists('job_batches'); + Schema::dropIfExists('failed_jobs'); + } +}; diff --git a/database/migrations/2026_02_05_064036_create_master_induks_table.php b/database/migrations/2026_02_05_064036_create_master_induks_table.php new file mode 100644 index 0000000..bd1f62a --- /dev/null +++ b/database/migrations/2026_02_05_064036_create_master_induks_table.php @@ -0,0 +1,29 @@ +id(); + $table->string('nomor_induk')->unique(); + $table->enum('role', ['siswa', 'guru']); + $table->string('nama_pemilik')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('master_induks'); + } +}; diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php new file mode 100644 index 0000000..71f06f8 --- /dev/null +++ b/database/seeders/DatabaseSeeder.php @@ -0,0 +1,93 @@ + '1234567890', 'role' => 'siswa', 'nama_pemilik' => 'Silvi Rahmawati'], + ['nomor_induk' => '9988776655', 'role' => 'siswa', 'nama_pemilik' => 'Siti Nurhaliza'], + ['nomor_induk' => '5566778899', 'role' => 'siswa', 'nama_pemilik' => 'Andi Pratama'], + ['nomor_induk' => '198506152010012', 'role' => 'guru', 'nama_pemilik' => 'Rina Marlina'], + ]; + + foreach ($whitelist as $w) { + MasterInduk::create($w); + } + + // ISI USER ASLI + + // ID 1: Silvi (Siswa) + User::create([ + 'id' => 1, + 'name' => 'Silvi Rahmawati', + 'email' => 'silvi.rahmawati@smkn1perpus.sch.id', + 'password' => Hash::make('password'), + 'role' => 'siswa', + 'nisn' => '1234567890', + 'no_hp' => '08123456789', + 'kelas' => 'XII RPL', + 'golongan' => 'A' + ]); + + // ID 2: Budi (Admin/Penjaga) + User::create([ + 'id' => 2, + 'name' => 'Budi Santoso', + 'email' => 'budi.santoso@smkn1perpus.sch.id', + 'password' => Hash::make('password'), + 'role' => 'penjaga perpus', + 'nip' => '197812312005011', + ]); + + // ID 3: Siti (Siswa) + User::create([ + 'id' => 3, + 'name' => 'Siti Nurhaliza', + 'email' => 'siti.nurhaliza@smkn1perpus.sch.id', + 'password' => Hash::make('password'), + 'role' => 'siswa', + 'nisn' => '9988776655', + 'no_hp' => '081998877665', + 'kelas' => 'XII RPL', + 'golongan' => 'B' + ]); + + // ID 4: Andi (Siswa) + User::create([ + 'id' => 4, + 'name' => 'Andi Pratama', + 'email' => 'andi.pratama@smkn1perpus.sch.id', + 'password' => Hash::make('password'), + 'role' => 'siswa', + 'nisn' => '5566778899', + 'no_hp' => '081556677889', + 'kelas' => 'XII RPL', + 'golongan' => 'C' + ]); + + // ID 5: Rina (Guru) + User::create([ + 'id' => 5, + 'name' => 'Rina Marlina', + 'email' => 'rina.marlina@smkn1perpus.sch.id', + 'password' => Hash::make('password'), + 'role' => 'guru', + 'nip' => '198506152010012', + ]); + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..7f9dbbf --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2947 @@ +{ + "name": "skripsi-perpus-fe", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "@popperjs/core": "^2.11.8", + "bootstrap": "^5.3.8", + "sass": "^1.92.1" + }, + "devDependencies": { + "@tailwindcss/forms": "^0.5.2", + "@tailwindcss/vite": "^4.0.0", + "alpinejs": "^3.4.2", + "axios": "^1.11.0", + "concurrently": "^9.0.1", + "laravel-vite-plugin": "^2.0.0", + "vite": "^7.0.4" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.11.tgz", + "integrity": "sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.11.tgz", + "integrity": "sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.11.tgz", + "integrity": "sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.11.tgz", + "integrity": "sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.11.tgz", + "integrity": "sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.11.tgz", + "integrity": "sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.11.tgz", + "integrity": "sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.11.tgz", + "integrity": "sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.11.tgz", + "integrity": "sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.11.tgz", + "integrity": "sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.11.tgz", + "integrity": "sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.11.tgz", + "integrity": "sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.11.tgz", + "integrity": "sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.11.tgz", + "integrity": "sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.11.tgz", + "integrity": "sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.11.tgz", + "integrity": "sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.11.tgz", + "integrity": "sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.11.tgz", + "integrity": "sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.11.tgz", + "integrity": "sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.11.tgz", + "integrity": "sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.11.tgz", + "integrity": "sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.11.tgz", + "integrity": "sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.11.tgz", + "integrity": "sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.11.tgz", + "integrity": "sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.11.tgz", + "integrity": "sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.11.tgz", + "integrity": "sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", + "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.1", + "@parcel/watcher-darwin-arm64": "2.5.1", + "@parcel/watcher-darwin-x64": "2.5.1", + "@parcel/watcher-freebsd-x64": "2.5.1", + "@parcel/watcher-linux-arm-glibc": "2.5.1", + "@parcel/watcher-linux-arm-musl": "2.5.1", + "@parcel/watcher-linux-arm64-glibc": "2.5.1", + "@parcel/watcher-linux-arm64-musl": "2.5.1", + "@parcel/watcher-linux-x64-glibc": "2.5.1", + "@parcel/watcher-linux-x64-musl": "2.5.1", + "@parcel/watcher-win32-arm64": "2.5.1", + "@parcel/watcher-win32-ia32": "2.5.1", + "@parcel/watcher-win32-x64": "2.5.1" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz", + "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz", + "integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz", + "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz", + "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz", + "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz", + "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz", + "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz", + "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz", + "integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz", + "integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz", + "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz", + "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz", + "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher/node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "license": "Apache-2.0", + "optional": true, + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.5.tgz", + "integrity": "sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.5.tgz", + "integrity": "sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.5.tgz", + "integrity": "sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.5.tgz", + "integrity": "sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.5.tgz", + "integrity": "sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.5.tgz", + "integrity": "sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.5.tgz", + "integrity": "sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.5.tgz", + "integrity": "sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.5.tgz", + "integrity": "sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.5.tgz", + "integrity": "sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.5.tgz", + "integrity": "sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.5.tgz", + "integrity": "sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.5.tgz", + "integrity": "sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.5.tgz", + "integrity": "sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.5.tgz", + "integrity": "sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.5.tgz", + "integrity": "sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.5.tgz", + "integrity": "sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.5.tgz", + "integrity": "sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.5.tgz", + "integrity": "sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.5.tgz", + "integrity": "sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.5.tgz", + "integrity": "sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.5.tgz", + "integrity": "sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@tailwindcss/forms": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.10.tgz", + "integrity": "sha512-utI1ONF6uf/pPNO68kmN1b8rEwNXv3czukalo8VtJH8ksIkZXr3Q3VYudZLkCsDd4Wku120uF02hYK25XGPorw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mini-svg-data-uri": "^1.2.3" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20 || >= 4.0.0-beta.1" + } + }, + "node_modules/@tailwindcss/node": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.16.tgz", + "integrity": "sha512-BX5iaSsloNuvKNHRN3k2RcCuTEgASTo77mofW0vmeHkfrDWaoFAFvNHpEgtu0eqyypcyiBkDWzSMxJhp3AUVcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.4", + "enhanced-resolve": "^5.18.3", + "jiti": "^2.6.1", + "lightningcss": "1.30.2", + "magic-string": "^0.30.19", + "source-map-js": "^1.2.1", + "tailwindcss": "4.1.16" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.16.tgz", + "integrity": "sha512-2OSv52FRuhdlgyOQqgtQHuCgXnS8nFSYRp2tJ+4WZXKgTxqPy7SMSls8c3mPT5pkZ17SBToGM5LHEJBO7miEdg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.1.16", + "@tailwindcss/oxide-darwin-arm64": "4.1.16", + "@tailwindcss/oxide-darwin-x64": "4.1.16", + "@tailwindcss/oxide-freebsd-x64": "4.1.16", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.16", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.16", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.16", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.16", + "@tailwindcss/oxide-linux-x64-musl": "4.1.16", + "@tailwindcss/oxide-wasm32-wasi": "4.1.16", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.16", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.16" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.16.tgz", + "integrity": "sha512-8+ctzkjHgwDJ5caq9IqRSgsP70xhdhJvm+oueS/yhD5ixLhqTw9fSL1OurzMUhBwE5zK26FXLCz2f/RtkISqHA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.16.tgz", + "integrity": "sha512-C3oZy5042v2FOALBZtY0JTDnGNdS6w7DxL/odvSny17ORUnaRKhyTse8xYi3yKGyfnTUOdavRCdmc8QqJYwFKA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.16.tgz", + "integrity": "sha512-vjrl/1Ub9+JwU6BP0emgipGjowzYZMjbWCDqwA2Z4vCa+HBSpP4v6U2ddejcHsolsYxwL5r4bPNoamlV0xDdLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.16.tgz", + "integrity": "sha512-TSMpPYpQLm+aR1wW5rKuUuEruc/oOX3C7H0BTnPDn7W/eMw8W+MRMpiypKMkXZfwH8wqPIRKppuZoedTtNj2tg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.16.tgz", + "integrity": "sha512-p0GGfRg/w0sdsFKBjMYvvKIiKy/LNWLWgV/plR4lUgrsxFAoQBFrXkZ4C0w8IOXfslB9vHK/JGASWD2IefIpvw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.16.tgz", + "integrity": "sha512-DoixyMmTNO19rwRPdqviTrG1rYzpxgyYJl8RgQvdAQUzxC1ToLRqtNJpU/ATURSKgIg6uerPw2feW0aS8SNr/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.16.tgz", + "integrity": "sha512-H81UXMa9hJhWhaAUca6bU2wm5RRFpuHImrwXBUvPbYb+3jo32I9VIwpOX6hms0fPmA6f2pGVlybO6qU8pF4fzQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.16.tgz", + "integrity": "sha512-ZGHQxDtFC2/ruo7t99Qo2TTIvOERULPl5l0K1g0oK6b5PGqjYMga+FcY1wIUnrUxY56h28FxybtDEla+ICOyew==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.16.tgz", + "integrity": "sha512-Oi1tAaa0rcKf1Og9MzKeINZzMLPbhxvm7rno5/zuP1WYmpiG0bEHq4AcRUiG2165/WUzvxkW4XDYCscZWbTLZw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.16.tgz", + "integrity": "sha512-B01u/b8LteGRwucIBmCQ07FVXLzImWESAIMcUU6nvFt/tYsQ6IHz8DmZ5KtvmwxD+iTYBtM1xwoGXswnlu9v0Q==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.5.0", + "@emnapi/runtime": "^1.5.0", + "@emnapi/wasi-threads": "^1.1.0", + "@napi-rs/wasm-runtime": "^1.0.7", + "@tybys/wasm-util": "^0.10.1", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.16.tgz", + "integrity": "sha512-zX+Q8sSkGj6HKRTMJXuPvOcP8XfYON24zJBRPlszcH1Np7xuHXhWn8qfFjIujVzvH3BHU+16jBXwgpl20i+v9A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.16.tgz", + "integrity": "sha512-m5dDFJUEejbFqP+UXVstd4W/wnxA4F61q8SoL+mqTypId2T2ZpuxosNSgowiCnLp2+Z+rivdU0AqpfgiD7yCBg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/vite": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.16.tgz", + "integrity": "sha512-bbguNBcDxsRmi9nnlWJxhfDWamY3lmcyACHcdO1crxfzuLpOhHLLtEIN/nCbbAtj5rchUgQD17QVAKi1f7IsKg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tailwindcss/node": "4.1.16", + "@tailwindcss/oxide": "4.1.16", + "tailwindcss": "4.1.16" + }, + "peerDependencies": { + "vite": "^5.2.0 || ^6 || ^7" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vue/reactivity": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.1.5.tgz", + "integrity": "sha512-1tdfLmNjWG6t/CsPldh+foumYFo3cpyCHgBYQ34ylaMsJ+SNHQ1kApMIa8jN+i593zQuaw3AdWH0nJTARzCFhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/shared": "3.1.5" + } + }, + "node_modules/@vue/shared": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.1.5.tgz", + "integrity": "sha512-oJ4F3TnvpXaQwZJNF3ZK+kLPHKarDmJjJ6jyzVNDKH9md1dptjC7lWR//jrGuLdek/U6iltWxqAnYOu8gCiOvA==", + "dev": true, + "license": "MIT" + }, + "node_modules/alpinejs": { + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.15.1.tgz", + "integrity": "sha512-HLO1TtiE92VajFHtLLPK8BWaK1YepV/uj31UrfoGnQ00lyFOJZ+oVY3F0DghPAwvg8sLU79pmjGQSytERa2gEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/reactivity": "~3.1.1" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.1.tgz", + "integrity": "sha512-hU4EGxxt+j7TQijx1oYdAjw4xuIp1wRQSsbMFwSthCWeBQur1eF+qJ5iQ5sN3Tw8YRzQNKb8jszgBdMDVqwJcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/bootstrap": { + "version": "5.3.8", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.8.tgz", + "integrity": "sha512-HP1SZDqaLDPwsNiqRqi5NcP0SSXciX2s9E+RyqJIIqGo+vJeN5AJVM98CXmW/Wux0nQ5L7jeWUdplCEf0Ee+tg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "license": "MIT", + "peerDependencies": { + "@popperjs/core": "^2.11.8" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "optional": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/concurrently": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.1.tgz", + "integrity": "sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "4.1.2", + "rxjs": "7.8.2", + "shell-quote": "1.8.3", + "supports-color": "8.1.1", + "tree-kill": "1.2.2", + "yargs": "17.7.2" + }, + "bin": { + "conc": "dist/bin/concurrently.js", + "concurrently": "dist/bin/concurrently.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/enhanced-resolve": { + "version": "5.18.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", + "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.11.tgz", + "integrity": "sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.11", + "@esbuild/android-arm": "0.25.11", + "@esbuild/android-arm64": "0.25.11", + "@esbuild/android-x64": "0.25.11", + "@esbuild/darwin-arm64": "0.25.11", + "@esbuild/darwin-x64": "0.25.11", + "@esbuild/freebsd-arm64": "0.25.11", + "@esbuild/freebsd-x64": "0.25.11", + "@esbuild/linux-arm": "0.25.11", + "@esbuild/linux-arm64": "0.25.11", + "@esbuild/linux-ia32": "0.25.11", + "@esbuild/linux-loong64": "0.25.11", + "@esbuild/linux-mips64el": "0.25.11", + "@esbuild/linux-ppc64": "0.25.11", + "@esbuild/linux-riscv64": "0.25.11", + "@esbuild/linux-s390x": "0.25.11", + "@esbuild/linux-x64": "0.25.11", + "@esbuild/netbsd-arm64": "0.25.11", + "@esbuild/netbsd-x64": "0.25.11", + "@esbuild/openbsd-arm64": "0.25.11", + "@esbuild/openbsd-x64": "0.25.11", + "@esbuild/openharmony-arm64": "0.25.11", + "@esbuild/sunos-x64": "0.25.11", + "@esbuild/win32-arm64": "0.25.11", + "@esbuild/win32-ia32": "0.25.11", + "@esbuild/win32-x64": "0.25.11" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "optional": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/immutable": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.4.tgz", + "integrity": "sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA==", + "license": "MIT" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "optional": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/laravel-vite-plugin": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-2.0.1.tgz", + "integrity": "sha512-zQuvzWfUKQu9oNVi1o0RZAJCwhGsdhx4NEOyrVQwJHaWDseGP9tl7XUPLY2T8Cj6+IrZ6lmyxlR1KC8unf3RLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picocolors": "^1.0.0", + "vite-plugin-full-reload": "^1.1.0" + }, + "bin": { + "clean-orphaned-assets": "bin/clean.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^7.0.0" + } + }, + "node_modules/lightningcss": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz", + "integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.30.2", + "lightningcss-darwin-arm64": "1.30.2", + "lightningcss-darwin-x64": "1.30.2", + "lightningcss-freebsd-x64": "1.30.2", + "lightningcss-linux-arm-gnueabihf": "1.30.2", + "lightningcss-linux-arm64-gnu": "1.30.2", + "lightningcss-linux-arm64-musl": "1.30.2", + "lightningcss-linux-x64-gnu": "1.30.2", + "lightningcss-linux-x64-musl": "1.30.2", + "lightningcss-win32-arm64-msvc": "1.30.2", + "lightningcss-win32-x64-msvc": "1.30.2" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz", + "integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz", + "integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz", + "integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz", + "integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz", + "integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz", + "integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz", + "integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz", + "integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz", + "integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz", + "integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz", + "integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "optional": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mini-svg-data-uri": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", + "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==", + "dev": true, + "license": "MIT", + "bin": { + "mini-svg-data-uri": "cli.js" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT", + "optional": true + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true, + "license": "MIT" + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.5.tgz", + "integrity": "sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.52.5", + "@rollup/rollup-android-arm64": "4.52.5", + "@rollup/rollup-darwin-arm64": "4.52.5", + "@rollup/rollup-darwin-x64": "4.52.5", + "@rollup/rollup-freebsd-arm64": "4.52.5", + "@rollup/rollup-freebsd-x64": "4.52.5", + "@rollup/rollup-linux-arm-gnueabihf": "4.52.5", + "@rollup/rollup-linux-arm-musleabihf": "4.52.5", + "@rollup/rollup-linux-arm64-gnu": "4.52.5", + "@rollup/rollup-linux-arm64-musl": "4.52.5", + "@rollup/rollup-linux-loong64-gnu": "4.52.5", + "@rollup/rollup-linux-ppc64-gnu": "4.52.5", + "@rollup/rollup-linux-riscv64-gnu": "4.52.5", + "@rollup/rollup-linux-riscv64-musl": "4.52.5", + "@rollup/rollup-linux-s390x-gnu": "4.52.5", + "@rollup/rollup-linux-x64-gnu": "4.52.5", + "@rollup/rollup-linux-x64-musl": "4.52.5", + "@rollup/rollup-openharmony-arm64": "4.52.5", + "@rollup/rollup-win32-arm64-msvc": "4.52.5", + "@rollup/rollup-win32-ia32-msvc": "4.52.5", + "@rollup/rollup-win32-x64-gnu": "4.52.5", + "@rollup/rollup-win32-x64-msvc": "4.52.5", + "fsevents": "~2.3.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/sass": { + "version": "1.93.2", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.93.2.tgz", + "integrity": "sha512-t+YPtOQHpGW1QWsh1CHQ5cPIr9lbbGZLZnbihP/D/qZj/yuV68m8qarcV17nvkOX81BCrvzAlq2klCQFZghyTg==", + "license": "MIT", + "dependencies": { + "chokidar": "^4.0.0", + "immutable": "^5.0.2", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, + "node_modules/shell-quote": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/tailwindcss": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.16.tgz", + "integrity": "sha512-pONL5awpaQX4LN5eiv7moSiSPd/DLDzKVRJz8Q9PgzmAdd1R4307GQS2ZpfiN7ZmekdQrfhZZiSE5jkLR4WNaA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/vite": { + "version": "7.1.12", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.12.tgz", + "integrity": "sha512-ZWyE8YXEXqJrrSLvYgrRP7p62OziLW7xI5HYGWFzOvupfAlrLvURSzv/FyGyy0eidogEM3ujU+kUG1zuHgb6Ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite-plugin-full-reload": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vite-plugin-full-reload/-/vite-plugin-full-reload-1.2.0.tgz", + "integrity": "sha512-kz18NW79x0IHbxRSHm0jttP4zoO9P9gXh+n6UTwlNKnviTTEpOlum6oS9SmecrTtSr+muHEn5TUuC75UovQzcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picocolors": "^1.0.0", + "picomatch": "^2.3.1" + } + }, + "node_modules/vite/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..478a5b2 --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://json.schemastore.org/package.json", + "private": true, + "type": "module", + "scripts": { + "build": "vite build", + "dev": "vite" + }, + "devDependencies": { + "@tailwindcss/forms": "^0.5.2", + "@tailwindcss/vite": "^4.0.0", + "alpinejs": "^3.4.2", + "axios": "^1.11.0", + "concurrently": "^9.0.1", + "laravel-vite-plugin": "^2.0.0", + "vite": "^7.0.4" + }, + "dependencies": { + "@popperjs/core": "^2.11.8", + "bootstrap": "^5.3.8", + "sass": "^1.92.1" + } +} diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..5fd5bcf --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,34 @@ + + + + + tests/Unit + + + tests/Feature + + + + + app + + + + + + + + + + + + + + + + + diff --git a/public/.htaccess b/public/.htaccess new file mode 100644 index 0000000..b574a59 --- /dev/null +++ b/public/.htaccess @@ -0,0 +1,25 @@ + + + Options -MultiViews -Indexes + + + RewriteEngine On + + # Handle Authorization Header + RewriteCond %{HTTP:Authorization} . + RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] + + # Handle X-XSRF-Token Header + RewriteCond %{HTTP:x-xsrf-token} . + RewriteRule .* - [E=HTTP_X_XSRF_TOKEN:%{HTTP:X-XSRF-Token}] + + # Redirect Trailing Slashes If Not A Folder... + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_URI} (.+)/$ + RewriteRule ^ %1 [L,R=301] + + # Send Requests To Front Controller... + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule ^ index.php [L] + diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..e69de29 diff --git a/public/images/assets/bg-login.svg b/public/images/assets/bg-login.svg new file mode 100644 index 0000000..5758f99 --- /dev/null +++ b/public/images/assets/bg-login.svg @@ -0,0 +1,457 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/assets/hero-image.svg b/public/images/assets/hero-image.svg new file mode 100644 index 0000000..c121c44 --- /dev/null +++ b/public/images/assets/hero-image.svg @@ -0,0 +1,455 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/assets/logo-smp.png b/public/images/assets/logo-smp.png new file mode 100644 index 0000000..af26c5d Binary files /dev/null and b/public/images/assets/logo-smp.png differ diff --git a/public/images/assets/vector-dashboard.svg b/public/images/assets/vector-dashboard.svg new file mode 100644 index 0000000..a465e4b --- /dev/null +++ b/public/images/assets/vector-dashboard.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/covers/ayah.png b/public/images/covers/ayah.png new file mode 100644 index 0000000..5d672c9 Binary files /dev/null and b/public/images/covers/ayah.png differ diff --git a/public/images/covers/hijrah.png b/public/images/covers/hijrah.png new file mode 100644 index 0000000..6b903f4 Binary files /dev/null and b/public/images/covers/hijrah.png differ diff --git a/public/images/covers/ipas.jpg b/public/images/covers/ipas.jpg new file mode 100644 index 0000000..97c185e Binary files /dev/null and b/public/images/covers/ipas.jpg differ diff --git a/public/images/covers/mtk.jpg b/public/images/covers/mtk.jpg new file mode 100644 index 0000000..9530d2a Binary files /dev/null and b/public/images/covers/mtk.jpg differ diff --git a/public/images/covers/pancasila.jpg b/public/images/covers/pancasila.jpg new file mode 100644 index 0000000..1d22e1a Binary files /dev/null and b/public/images/covers/pancasila.jpg differ diff --git a/public/images/covers/senbud.jpg b/public/images/covers/senbud.jpg new file mode 100644 index 0000000..d5d2b68 Binary files /dev/null and b/public/images/covers/senbud.jpg differ diff --git a/public/images/covers/senja.png b/public/images/covers/senja.png new file mode 100644 index 0000000..c1063f4 Binary files /dev/null and b/public/images/covers/senja.png differ diff --git a/public/images/covers/sianakpintar.jpg b/public/images/covers/sianakpintar.jpg new file mode 100644 index 0000000..bc3b541 Binary files /dev/null and b/public/images/covers/sianakpintar.jpg differ diff --git a/public/images/covers/sosiologi.jpg b/public/images/covers/sosiologi.jpg new file mode 100644 index 0000000..e55931c Binary files /dev/null and b/public/images/covers/sosiologi.jpg differ diff --git a/public/images/covers/thelastspellbreather.jpg b/public/images/covers/thelastspellbreather.jpg new file mode 100644 index 0000000..c64a34e Binary files /dev/null and b/public/images/covers/thelastspellbreather.jpg differ diff --git a/public/images/logo/icon.svg b/public/images/logo/icon.svg new file mode 100644 index 0000000..530d69d --- /dev/null +++ b/public/images/logo/icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/logo/name.svg b/public/images/logo/name.svg new file mode 100644 index 0000000..f4b6a2f --- /dev/null +++ b/public/images/logo/name.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/index.php b/public/index.php new file mode 100644 index 0000000..ee8f07e --- /dev/null +++ b/public/index.php @@ -0,0 +1,20 @@ +handleRequest(Request::capture()); diff --git a/public/js/dashboard-charts.js b/public/js/dashboard-charts.js new file mode 100644 index 0000000..767e7bb --- /dev/null +++ b/public/js/dashboard-charts.js @@ -0,0 +1,83 @@ +// public/js/dashboard-charts.js +document.addEventListener('DOMContentLoaded', function () { + // Ambil elemen canvas Bar Chart + const barChartEl = document.getElementById('barChart'); + if (barChartEl) { + const statistikData = JSON.parse(barChartEl.dataset.stats); + + new Chart(barChartEl.getContext('2d'), { + type: 'bar', + data: { + labels: statistikData.labels, + datasets: [{ + label: 'Buku Dibaca', + backgroundColor: '#0C5495', + data: statistikData.data, + borderRadius: 8 + }] + }, + options: { + responsive: true, + maintainAspectRatio: false, + scales: { + y: { + beginAtZero: true, + grid: { + color: 'rgba(0,0,0,0.05)', + }, + ticks: { + color: '#6c757d', + font: { + size: 12 + } + } + }, + x: { + grid: { + display: false, + }, + ticks: { + color: '#6c757d', + font: { + size: 12 + } + } + } + }, + plugins: { + legend: { + display: false + } + } + } + }); + } + + const donutChartEl = document.getElementById('donutChart'); + if (donutChartEl) { + const progressData = JSON.parse(donutChartEl.dataset.progress); + + new Chart(donutChartEl.getContext('2d'), { + type: 'doughnut', + data: { + labels: ['Telah Dibaca', 'Belum Dibaca'], + datasets: [{ + data: [progressData.selesai, progressData.sisa], + backgroundColor: ['#0C5495', '#fbb716'], + borderColor: ['#ffffff'], + borderWidth: 3, + }] + }, + options: { + responsive: true, + maintainAspectRatio: false, + plugins: { + legend: { + display: false + } + }, + cutout: '75%' + } + }); + } +}); \ No newline at end of file diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..eb05362 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: diff --git a/resources/js/app.js b/resources/js/app.js new file mode 100644 index 0000000..aa5c306 --- /dev/null +++ b/resources/js/app.js @@ -0,0 +1,11 @@ +import './bootstrap'; +import './peminjaman-form.js'; +import * as bootstrap from 'bootstrap'; + +window.bootstrap = bootstrap; + +import Alpine from 'alpinejs'; +window.Alpine = Alpine; +document.addEventListener('DOMContentLoaded', () => { + Alpine.start(); +}); \ No newline at end of file diff --git a/resources/js/bootstrap.js b/resources/js/bootstrap.js new file mode 100644 index 0000000..5f1390b --- /dev/null +++ b/resources/js/bootstrap.js @@ -0,0 +1,4 @@ +import axios from 'axios'; +window.axios = axios; + +window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; diff --git a/resources/js/peminjaman-form.js b/resources/js/peminjaman-form.js new file mode 100644 index 0000000..7fa862b --- /dev/null +++ b/resources/js/peminjaman-form.js @@ -0,0 +1,188 @@ +const formPeminjamanElement = document.getElementById('formPeminjaman'); + +if (formPeminjamanElement) { + // Ambil data yang sudah disimpan di elemen HTML + const semuaBuku = JSON.parse(formPeminjamanElement.dataset.semuaBuku); + const bukuAwal = JSON.parse(formPeminjamanElement.dataset.bukuAwal); + + let bukuTerpilih = [bukuAwal.id]; + const maxBuku = 2; + + document.addEventListener('DOMContentLoaded', function () { + updateCounter(); + updateSelectedBooks(); + updateCheckboxes(); + updateBtnTambahBuku(); + updateDaftarBuku(); + }); + + function updateCounter() { + document.getElementById('counterBuku').textContent = bukuTerpilih.length; + document.getElementById('sisaSlot').textContent = maxBuku - bukuTerpilih.length; + } + + function updateBtnTambahBuku() { + const btnTambah = document.getElementById('btnTambahBuku'); + if (bukuTerpilih.length >= maxBuku) { + btnTambah.classList.add('disabled'); + btnTambah.innerHTML = 'Maksimal Buku Tercapai'; + } else { + btnTambah.classList.remove('disabled'); + btnTambah.innerHTML = 'Tambah Buku'; + } + } + + function updateSelectedBooks() { + const container = document.getElementById('selectedBooks'); + const selected = semuaBuku.filter(book => bukuTerpilih.includes(book.id)); + container.innerHTML = selected.map(book => `
  • ${book.judul}
  • `).join(''); + } + + function updateCheckboxes() { + document.querySelectorAll('.book-checkbox').forEach(checkbox => { + const bookId = parseInt(checkbox.value); + checkbox.checked = bukuTerpilih.includes(bookId); + + if (bukuTerpilih.length >= maxBuku && !bukuTerpilih.includes(bookId)) { + checkbox.disabled = true; + } else if (bookId !== bukuAwal.id) { + checkbox.disabled = false; + } + }); + } + + window.toggleBookSelection = function (bookId) { + if (bookId === bukuAwal.id) return; + + const checkbox = document.getElementById('book' + bookId); + if (!checkbox.disabled) { + checkbox.checked = !checkbox.checked; + handleCheckboxChange(checkbox); + } + } + + function handleCheckboxChange(checkbox) { + const bookId = parseInt(checkbox.value); + if (checkbox.checked) { + if (bukuTerpilih.length < maxBuku && !bukuTerpilih.includes(bookId)) { + bukuTerpilih.push(bookId); + } else { + checkbox.checked = false; + return; + } + } else { + bukuTerpilih = bukuTerpilih.filter(id => id !== bookId); + } + + updateCounter(); + updateSelectedBooks(); + updateCheckboxes(); + updateBtnTambahBuku(); + } + + document.addEventListener('change', function (e) { + if (e.target.classList.contains('book-checkbox')) { + if (e.target.value != bukuAwal.id) { + handleCheckboxChange(e.target); + } + } + }); + + document.getElementById('searchBuku')?.addEventListener('input', function (e) { + const searchTerm = e.target.value.toLowerCase(); + document.querySelectorAll('.book-option').forEach(option => { + const title = option.getAttribute('data-book-title'); + const author = option.getAttribute('data-book-author'); + + if (title.includes(searchTerm) || author.includes(searchTerm)) { + option.style.display = 'block'; + } else { + option.style.display = 'none'; + } + }); + }); + + function updateDaftarBuku() { + const container = document.getElementById('daftarBukuPinjam'); + const hiddenInputs = document.getElementById('hiddenInputs'); + const selected = semuaBuku.filter(book => bukuTerpilih.includes(book.id)); + + container.innerHTML = selected.map((book) => ` +
    +
    + + Cover + +
    +
    ${book.judul}
    +

    ${book.penulis}

    + ${book.kategori} +
    + +
    + ${book.id === bukuAwal.id + ? 'Buku Utama' + : 'Tambahan'} + + ${book.id !== bukuAwal.id + ? `` + : ''} +
    +
    +
    + `).join(''); + + + hiddenInputs.innerHTML = bukuTerpilih.map(id => + `` + ).join(''); + } + + window.removeBuku = function (bookId) { + if (bookId !== bukuAwal.id) { + bukuTerpilih = bukuTerpilih.filter(id => id !== bookId); + updateDaftarBuku(); + updateCounter(); + updateSelectedBooks(); + updateCheckboxes(); + updateBtnTambahBuku(); + } + } + + window.konfirmasiPilihanBuku = function () { + updateDaftarBuku(); + const modal = bootstrap.Modal.getInstance(document.getElementById('pilihBukuModal')); + modal.hide(); + } + + document.getElementById('konfirmasiModal')?.addEventListener('show.bs.modal', function () { + const selected = semuaBuku.filter(book => bukuTerpilih.includes(book.id)); + const ringkasan = selected.map((book, index) => + `
    + ${index + 1}. ${book.judul} + ${book.penulis} +
    ` + ).join(''); + document.getElementById('ringkasanBuku').innerHTML = ringkasan; + }); + + window.kirimForm = function () { + document.getElementById('formPeminjaman').submit(); + } + + document.getElementById('pilihBukuModal')?.addEventListener('hidden.bs.modal', function () { + const searchInput = document.getElementById('searchBuku'); + if (searchInput) { + searchInput.value = ''; + document.querySelectorAll('.book-option').forEach(option => { + option.style.display = 'block'; + }); + } + }); +} \ No newline at end of file diff --git a/resources/scss/_custom.scss b/resources/scss/_custom.scss new file mode 100644 index 0000000..2b46a15 --- /dev/null +++ b/resources/scss/_custom.scss @@ -0,0 +1,1043 @@ +@use "sass:color"; + +// =================================== +// UTILITIES (GENERATED FROM MAPS) +// =================================== +// Generator otomatis untuk variant warna (background light, soft, alert) +@each $color, +$value in $theme-colors { + .bg-#{$color}-light { + background-color: rgba($value, 0.25) !important; + } + + .bg-#{$color}-soft { + background-color: rgba($value, 0.25); + color: $value; + } + + .alert-#{$color} { + background-color: rgba($value, 0.2); + color: color.adjust($value, $lightness: -25%); + border-color: rgba($value, 0.3); + } +} + +// =================================== +// LANDING PAGE CUSTOM STYLING +// =================================== + +html { + scroll-behavior: smooth; +} + +// Navbar Landing +.landing-navbar { + padding-top: 0.75rem; + padding-bottom: 0.75rem; + z-index: 1050; + + .navbar-brand { + font-size: 1.25rem; + + i { + font-size: 1.5rem; + } + + @media (max-width: 575.98px) { + font-size: 1.1rem; + + i { + font-size: 1.25rem; + } + } + } + + .navbar-toggler { + padding: 0.25rem 0.5rem; + + &:focus { + box-shadow: none; + } + } + + .navbar-nav { + .nav-link-landing { + padding: 0.5rem 1rem; + color: #49769F; + text-decoration: none; + display: block; + transition: color 0.3s ease; + + &:hover, + &.active { + color: #0C5495; + font-weight: 500; + transition: all 0.3s ease-in; + } + + @media (max-width: 991.98px) { + padding: 0.5rem 0; + } + } + } + + @media (max-width: 991.98px) { + .navbar-collapse { + margin-top: 1rem; + padding-top: 1rem; + border-top: 1px solid rgba(0, 0, 0, 0.1); + + .navbar-nav { + text-align: left !important; + width: 100%; + } + + .nav-item { + margin: 0 !important; + text-align: left !important; + } + + .nav-link { + width: 100%; + justify-content: start; + padding-left: 0.75rem; + padding-right: 0.75rem; + } + } + } +} + +// Hero Section +.landing-hero-section { + background: linear-gradient(135deg, + #0C5495 0%, + color.adjust(#0C5495, $lightness: 10%) 100%); + padding: 60px 0; + + @media (min-width: 992px) { + padding: 100px 0; + } + + .btn-hero-solid { + background-color: #fff !important; + border-color: #fff !important; + color: $primary !important; + /* Menggunakan warna primary Anda #0C5495 */ + + &:hover { + background-color: lighten($primary, 70%) !important; + /* Sedikit keabu-abuan saat hover */ + border-color: lighten($primary, 70%) !important; + color: $primary !important; + } + } +} + +.landing-hero-illustration { + background: rgba(255, 255, 255, 0.1); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + + i { + font-size: 5rem; + } + +} + +.card-img-top { + height: 200px; + object-fit: cover; +} + +.card-title { + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; + line-height: 1.4; + min-height: 2.8rem; + font-size: 0.9rem; + + @media (max-width: 575.98px) { + font-size: 0.85rem; + min-height: 2.4rem; + } +} + +// Stat Card +.landing-stat-card { + transition: all 0.3s ease; + + &:hover { + transform: translateY(-3px); + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.12) !important; + } + + h2 { + font-size: 2rem; + + @media (min-width: 768px) { + font-size: 2.5rem; + } + } +} + +// CTA Section +.landing-cta-section { + background: linear-gradient(135deg, + #0C5495 0%, + color.adjust(#0C5495, $lightness: 10%) 100%); + border-radius: 1rem; + + @media (min-width: 768px) { + border-radius: 1.5rem; + } +} + + +// =================================== +// BASE COMPONENTS +// =================================== +// Styling komponen Bootstrap yang dioverride + +.card { + box-shadow: $card-box-shadow; + + .card-header { + background-color: #fff; + border-bottom: 1px solid rgba(map-get($grays, "dark"), 0.1); + } +} + +.alert { + border-radius: $border-radius; + box-shadow: $shadow-sm; + + .alert-icon { + width: 24px; + display: flex; + align-items: center; + justify-content: center; + } +} + +.modal { + .modal-content { + border: none; + border-radius: $border-radius-lg; + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15); + + .modal-header, + .modal-footer { + border-color: rgba(map-get($grays, "dark"), 0.1); + padding: 1.5rem; + } + + .modal-title { + color: map-get($grays, "dark"); + font-weight: 700; + } + } +} + +// Styling button dengan efek hover dan active +.btn { + padding: 0.5rem 1.5rem; + font-weight: 500; + border-radius: 0.6rem; + transition: all 0.2s ease-in-out; + + &:hover { + transform: translateY(-1px); + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); + } + + &:active { + transform: translateY(0); + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15); + } + + &.btn-sm { + padding: 0.375rem 1.25rem; + font-size: 0.875rem; + } +} + +.btn.btn-primary { + background-color: $primary; + border-color: $primary; + color: #fff; + + &:hover { + background-color: darken($primary, 5%); + border-color: darken($primary, 5%); + color: #fff; + } + + &:active { + background-color: darken($primary, 7%) !important; + border-color: darken($primary, 7%) !important; + } +} + +.badge.rounded-pill { + font-weight: 500; + padding: 0.5rem 1rem; +} + +// =================================== +// LAYOUT & NAVIGATION +// =================================== +// Struktur layout aplikasi (sidebar, main content, overlay) + +body { + background-color: map-get($grays, "light"); +} + +// Sidebar +.sidebar { + width: 270px; + position: fixed; + top: 0; + bottom: 0; + z-index: 1050; + transition: all 0.3s ease; +} + +.main-wrapper { + transition: margin-left 0.3s ease; +} + +// Overlay gelap untuk mobile sidebar +.overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + z-index: 1049; + display: none; +} + +.overlay.active { + display: block; +} + +// Desktop: sidebar selalu muncul, bisa diminimize +@media (min-width: 992px) { + .sidebar { + left: 0; + } + + .main-wrapper { + margin-left: 260px; + } + + .sidebar.minimized { + width: 70px; + } + + .sidebar.minimized .nav-text, + .sidebar.minimized .sidebar-title { + display: none; + } + + .sidebar.minimized .nav-link { + justify-content: center; + } + + .main-wrapper.sidebar-minimized { + margin-left: 80px; + } +} + +@media (max-width: 991.98px) { + .sidebar { + left: -270px; + } + + .sidebar.active { + left: 0; + } +} + +// Styling navigasi sidebar +.sidebar .nav-link { + font-weight: 500; + margin: 0.3rem 0; + border-radius: 0.5rem; + display: flex; + align-items: center; +} + +.sidebar.bg-primary { + .nav-link { + color: rgba(255, 255, 255, 0.85); + + i { + color: rgba(255, 255, 255, 0.85); + } + + &.py-1 { + color: rgba(255, 255, 255, 0.7); + } + } + + .nav-link:hover:not(.active), + .nav-link.py-1:hover { + background: rgba(255, 255, 255, 0.05); + color: #fff; + + i { + color: #fff; + } + } + + .nav-link.active { + background: rgba(255, 255, 255, 0.1); + color: #fff; + font-weight: 600; + + i { + color: #fff; + } + } +} + +.sidebar.minimized .nav-link .ms-auto { + display: none; +} + +nav { + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; +} + +// Styling navbar +.navbar { + border-bottom: none; + + .navbar-brand { + font-size: 20px; + color: var(--bs-dark-text-emphasis) !important; + + @media (max-width: 991.98px) { + font-size: 18px; + } + } + + // Icon button circular di navbar (notifikasi, profile, dll) + .nav-link, + .btn-light { + display: flex; + align-items: center; + justify-content: center; + width: 40px; + height: 40px; + border-radius: 50%; + background-color: transparent; + border: none; + transition: background-color 0.2s ease-in-out; + + &:hover, + &:focus { + background-color: var(--bs-light-bg-subtle); + } + } +} + +// =================================== +// CUSTOM COMPONENTS +// =================================== +// Komponen custom yang dibuat sendiri + +// Avatar profile circular +.profile-avatar { + width: 38px; + height: 38px; + border-radius: 50%; + object-fit: cover; + cursor: pointer; +} + +// Item di dalam dropdown menu +.dropdown-item { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.5rem 1rem; +} + +.dropdown-item i { + width: 1.25em; +} + +// Dropdown notifikasi dengan responsive design +.notification-dropdown .dropdown-menu { + width: 390px; + max-width: calc(100vw - 20px); + border-radius: 0.75rem; + padding: 0.5rem !important; + box-shadow: 0 0.5rem 1.5rem rgba(0, 0, 0, 0.12); +} + +.notification-wrapper { + max-height: 450px; + overflow-y: auto; +} + +.notification-item { + display: flex; + align-items: center; + gap: 0.8rem; + padding: 0.8rem 1rem; + transition: background-color 0.2s ease; + text-decoration: none !important; +} + +.notification-item:hover { + background-color: var(--bs-tertiary-bg); +} + +.notification-item.unread { + background-color: rgba(var(--bs-primary-rgb), 0.1); +} + +.notification-icon { + width: 42px; + height: 42px; + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: center; + border-radius: 50%; +} + +.notification-icon i { + text-align: center; + font-size: 1.25rem; +} + +.notification-content { + flex: 1; + min-width: 0; +} + +.notification-content p { + margin-bottom: 0.1rem; + font-weight: 600; + color: var(--bs-body-color); + font-size: 0.925rem; + line-height: 1.4; +} + +.notification-content small { + color: var(--bs-secondary-color); + font-size: 0.8rem; +} + +.unread-dot { + width: 8px; + height: 8px; + border-radius: 50%; + background-color: var(--bs-primary); + margin-left: auto; + flex-shrink: 0; +} + +// Responsive notifikasi untuk mobile +@media (max-width: 575.98px) { + .notification-dropdown .dropdown-menu { + position: fixed !important; + top: 60px !important; + right: 20px !important; + left: auto !important; + width: 320px !important; + max-width: calc(100vw - 20px) !important; + transform: none !important; + margin: 0 !important; + } + + .notification-wrapper { + max-height: 50vh; + } + + .notification-content p { + font-size: 0.85rem; + line-height: 1.3; + } + + .notification-content small { + font-size: 0.75rem; + } + + .notification-icon { + width: 36px; + height: 36px; + } + + .notification-icon i { + font-size: 1.1rem; + } + + .notification-item { + gap: 0.6rem; + padding: 0.65rem 0.75rem; + } + + .notification-dropdown .dropdown-menu .px-3 { + padding-left: 0.75rem !important; + padding-right: 0.75rem !important; + } + + .notification-dropdown .dropdown-menu h6 { + font-size: 0.95rem; + } +} + +// Icon wrapper untuk dashboard dan statistik +.icon-circle, +.icon-box { + display: flex; + align-items: center; + justify-content: center; + transition: $transition; +} + +.icon-circle { + width: 60px; + height: 60px; + border-radius: 15%; +} + +.icon-box { + width: 40px; + height: 40px; + border-radius: 10px; + + i { + font-size: 1.2rem; + } +} + +// =================================== +// BOOK MANAGEMENT PAGES +// =================================== +// Styling khusus untuk halaman manajemen buku + +// Cover buku dengan container gradient +.book-cover { + transition: $transition; + border-radius: $border-radius-sm; + + &-container { + background: linear-gradient(135deg, + rgba(map-get($grays, "light"), 0.5) 0%, + rgba(map-get($grays, "light"), 0.8) 100%); + border-radius: $border-radius-sm 0 0 $border-radius-sm; + } +} + +// Header section dengan border bottom +.section-header { + padding-bottom: 15px; + border-bottom: 2px solid map-get($grays, "light"); + + h5 { + color: map-get($grays, "dark"); + font-weight: 700; + } +} + +// Empty state untuk data kosong +.empty-state { + text-align: center; + padding: 3rem 1rem; + + i { + font-size: 4rem; + color: map-get($grays, "dark"); + margin-bottom: 1rem; + opacity: 0.25; + } + + p { + color: map-get($grays, "dark"); + opacity: 0.7; + font-size: 1rem; + margin: 0; + } +} + +// Button primary soft variant +.btn-primary-soft { + --bs-btn-color: #{map-get($grays, "dark")}; + --bs-btn-bg: #{map-get($theme-colors, "primary")}; + --bs-btn-border-color: #{map-get($theme-colors, "primary")}; + --bs-btn-hover-color: #{map-get($grays, "dark")}; + --bs-btn-hover-bg: #{color.adjust( + map-get($theme-colors, "primary"), + $lightness: -5%) +} + +; +--bs-btn-hover-border-color: #{color.adjust( + map-get($theme-colors, "primary"), +$lightness: -7.5%) +} + +; +} + +// Text clamp untuk truncate multi line +.line-clamp-2, +.line-clamp-3 { + display: -webkit-box; + -webkit-box-orient: vertical; + overflow: hidden; + line-height: 1.4; +} + +.line-clamp-2 { + -webkit-line-clamp: 2; +} + +.line-clamp-3 { + -webkit-line-clamp: 3; +} + +// Custom scrollbar untuk seluruh aplikasi +::-webkit-scrollbar { + width: 6px; +} + +::-webkit-scrollbar-track { + background: map-get($grays, "light"); + border-radius: 3px; +} + +::-webkit-scrollbar-thumb { + background: rgba(map-get($grays, "dark"), 0.25); + border-radius: 3px; + + &:hover { + background: rgba(map-get($grays, "dark"), 0.4); + } +} + +// Card untuk select buku (dipakai di form peminjaman) +.card-book-select { + cursor: pointer; + position: relative; + transition: $transition; + + &:hover { + transform: translateY(-5px); + box-shadow: $shadow-md; + } + + .card-select-overlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(#435ebe, 0.7); + display: flex; + align-items: center; + justify-content: center; + opacity: 0; + transition: $transition; + border-radius: $border-radius-sm; + + i { + text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); + } + } + + &.selected { + border: 2px solid map-get($theme-colors, "primary"); + + .card-select-overlay { + opacity: 1; + } + } + + &.disabled { + cursor: not-allowed; + opacity: 0.6; + } +} + +// Thumbnail cover buku di form +.form-book-cover { + width: 60px; + height: 80px; + object-fit: cover; +} + +// Item buku di list (dipakai di halaman detail peminjaman) +.book-item { + background-color: map-get($grays, "light"); + border-left: 4px solid map-get($theme-colors, "primary"); +} + +// Card buku dengan checkbox (dipakai di halaman pilih buku untuk peminjaman) +.book-card { + cursor: pointer; + transition: $transition; + border: 2px solid transparent; + box-shadow: $card-box-shadow; + + &:hover { + transform: translateY(-2px); + border-color: map-get($theme-colors, "primary"); + box-shadow: $shadow-md; + + .book-cover { + transform: scale(1.03); + } + } + + &:has(.book-checkbox:checked) { + border-color: map-get($theme-colors, "success"); + background-color: rgba(map-get($theme-colors, "success"), 0.05); + } +} + +.remove-book { + padding: 2px 6px; + font-size: 12px; +} + +.btn.disabled { + pointer-events: none; + opacity: 0.65; +} + +.book-option[style*="display: none"] { + display: none !important; +} + +// =================================== +// AUTH PAGES +// =================================== +// Styling untuk halaman login dan register + +// Background gradient hero section +.hero-gradient { + background: linear-gradient(135deg, + map-get($theme-colors, "primary") 0%, + color.adjust(map-get($theme-colors, "primary"), $lightness: 10%) 100%); +} + +// Card untuk pilih role (admin/user) +.role-card { + display: block; + + .card { + transition: $transition; + border-radius: 20px; + + &:hover { + transform: translateY(-4px); + box-shadow: $shadow-md; + } + } +} + +// Panel info di halaman auth +.info-panel { + background: linear-gradient(135deg, + map-get($theme-colors, "primary") 0%, + color.adjust(map-get($theme-colors, "primary"), $lightness: 10%) 100%); +} + +// Panel kiri auth (logo dan branding) +.auth-left-panel { + padding: 3rem; + background-size: cover; + background-position: center; + background-repeat: no-repeat; +} + +.auth-branding { + max-width: 500px; + + .auth-logo { + display: flex; + align-items: center; + gap: 1rem; + margin-bottom: 1.5rem; + + h1 { + font-size: 3rem; + font-weight: 700; + color: #fff; + margin: 0; + padding-bottom: 5px; + } + } +} + +// Panel kanan auth (form) +.auth-right-panel { + padding: 2rem; +} + +// Card form auth +.auth-card { + background-color: #ffffff; + border: none; + padding: 2.5rem; + border-radius: 1.5rem; + box-shadow: $shadow-md; + + @media (max-width: 576px) { + padding: 2rem 1.5rem; + box-shadow: none; + } +} + +// Responsive auth pages +@media (max-width: 991.98px) { + .auth-left-panel { + background-image: none !important; + background-color: #0C5495; + position: absolute !important; + min-height: 40vh; + } + + .d-lg-none { + top: 5vh !important; + } + + .auth-branding { + .auth-logo { + .icon-circle { + width: 80px !important; + height: 80px !important; + border-radius: 20px !important; + } + + h1 { + font-size: 2.5rem; + } + } + } +} + +// =================================== +// DATATABLE STYLING +// =================================== +// Override styling DataTables + +.dataTables_wrapper { + + .dataTables_length, + .dataTables_filter, + .dataTables_info, + .dataTables_paginate { + font-size: 0.875rem; + } + + .dataTables_filter input { + border-radius: $border-radius-sm; + border: 1px solid #dee2e6; + padding: 0.375rem 0.75rem; + margin-left: 0.5rem; + + &:focus { + outline: none; + border-color: map-get($theme-colors, "primary"); + box-shadow: 0 0 0 0.2rem rgba(map-get($theme-colors, "primary"), 0.25); + } + } + + .dataTables_length select { + border-radius: $border-radius-sm; + border: 1px solid #dee2e6; + padding: 0.375rem 2rem 0.375rem 0.75rem; + margin: 0 0.5rem; + } +} + +// Responsive DataTables untuk mobile +@media screen and (max-width: 576px) { + .dataTables_wrapper { + + .dataTables_length, + .dataTables_filter { + text-align: center; + margin-bottom: 1rem; + } + + .dataTables_info, + .dataTables_paginate { + text-align: center; + margin-top: 1rem; + } + } + + table.dataTable td { + white-space: normal !important; + } +} + +// =================================== +// CHART RESPONSIVE +// =================================== +// Container responsive untuk chart/grafik + +.chart-responsive { + position: relative; + width: 100%; + height: 300px; + + @media (min-width: 992px) { + height: 450px; + } +} + +// =================================== +// PROFILE PAGE +// =================================== + + +// Avatar +.profile-avatar-lg { + width: 80px; + height: 80px; + + @media (max-width: 575.98px) { + width: 64px; + height: 64px; + } +} + +// Statistik container responsive +.stats-container { + @media (max-width: 575.98px) { + .stat-item { + padding: 1rem 0; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); + + &:last-child { + border-bottom: none; + } + } + } +} + +.laporan-list { + @media (max-width: 575.98px) { + .list-group-item { + flex-direction: column; + align-items: flex-start !important; + gap: 0.25rem; + } + } +} diff --git a/resources/scss/_variables.scss b/resources/scss/_variables.scss new file mode 100644 index 0000000..7804a69 --- /dev/null +++ b/resources/scss/_variables.scss @@ -0,0 +1,47 @@ +@use "sass:color"; + +// ===================================// +// VARIABLES & MAPS +// ===================================// + +// Theme Colors Map +$theme-colors: ( + "primary": #0C5495, + "secondary": #92D0F0, + "success": #14b8a6, + "info": #7BBDE8, + "warning": #fbb716, + "danger": #f43f5e, +); + +// Gray Colors Map +$grays: ( + "light": #f9f9f9, + "dark": #696e82, +); +// Spacing & Sizing +$border-radius: 0.5rem; +$border-radius-sm: 0.25rem; +$border-radius-lg: 1rem; + +// Shadows & Transitions +$card-box-shadow: 0 0 1.25rem rgba(33, 37, 41, 0.05); +$shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.08); +$shadow-md: 0 4px 8px rgba(0, 0, 0, 0.12); +$shadow-lg: 0 8px 20px rgba(0, 0, 0, 0.15); +$transition: all 0.3s ease; + +// ============================= +// CUSTOM BOOTSTRAP VARIABLES +// ============================= +$primary: map-get($theme-colors, "primary"); + +// Tombol utama +$btn-primary-color: #fff; +$btn-primary-bg: $primary; +$btn-primary-border-color: $primary; +$btn-primary-hover-bg: darken($primary, 5%); +$btn-primary-hover-border-color: darken($primary, 5%); +$btn-focus-shadow-rgb: to-rgb($primary); +$btn-primary-active-bg: darken($primary, 7%); +$btn-primary-active-border-color: darken($primary, 7%); diff --git a/resources/scss/app.scss b/resources/scss/app.scss new file mode 100644 index 0000000..52f7513 --- /dev/null +++ b/resources/scss/app.scss @@ -0,0 +1,5 @@ +@import "bootstrap/scss/functions"; +@import "variables"; +@import "bootstrap/scss/bootstrap"; +@import "custom"; + diff --git a/resources/views/admin/buku/create.blade.php b/resources/views/admin/buku/create.blade.php new file mode 100644 index 0000000..576e5c6 --- /dev/null +++ b/resources/views/admin/buku/create.blade.php @@ -0,0 +1,126 @@ + + @section('page-title', $pageTitle) + +
    + + + +

    Formulir Tambah Buku

    +
    + +
    +
    +
    +
    +
    +
    +
    + {{-- JUDUL --}} +
    + + +
    + + {{-- PENULIS --}} +
    + + +
    + +
    + {{-- KATEGORI --}} +
    + + +
    + + {{-- TAHUN TERBIT (SOLUSI DROPDOWN / SELECT) --}} +
    + +
    + + +
    +
    + + {{-- KODE BUKU --}} +
    + + +
    + + {{-- STOK BUKU --}} +
    + + +
    +
    + + {{-- TIPE AKSES --}} +
    + +
    +
    + + +
    +
    + + +
    +
    +
    +
    + + {{-- UPLOAD FILE --}} +
    +
    + + +
    Format: JPG, PNG. Maks: 2MB
    +
    +
    + + +
    Format: PDF. Maks: 10MB
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    + + @push('scripts') + + @endpush +
    \ No newline at end of file diff --git a/resources/views/admin/buku/edit.blade.php b/resources/views/admin/buku/edit.blade.php new file mode 100644 index 0000000..52f23eb --- /dev/null +++ b/resources/views/admin/buku/edit.blade.php @@ -0,0 +1,112 @@ + + @section('page-title', $pageTitle) + +
    + + + +

    Formulir Edit Buku

    +
    + +
    +
    +
    +
    +
    + {{-- TAMBAHKAN ID PADA FORM --}} +
    +
    +
    +
    + + +
    +
    + + +
    +
    +
    + + +
    +
    + + +
    +
    + + @php + $tipe_akses = is_array($buku['tipe_akses']) ? $buku['tipe_akses'] : [$buku['tipe_akses']]; + $isOffline = in_array('offline', $tipe_akses); + @endphp + + @if($isOffline) +
    +
    + + +
    +
    + + +
    +
    + @endif + +
    + +
    + + +
    +
    + + +
    +
    + +
    +
    +
    + + + Cover saat ini +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + + @push('scripts') + + @endpush +
    \ No newline at end of file diff --git a/resources/views/admin/buku/index.blade.php b/resources/views/admin/buku/index.blade.php new file mode 100644 index 0000000..8cdbc97 --- /dev/null +++ b/resources/views/admin/buku/index.blade.php @@ -0,0 +1,368 @@ + + @section('page-title', $pageTitle) + +
    +
    +
    Daftar Buku
    + + Tambah Buku + +
    +
    + {{-- NAV TABS --}} + + +
    + + {{-- BUKU OFFLINE --}} +
    +
    + + + + + + + + + + + + + + + @forelse($bukuOffline as $buku) + + + + + + + + + + + @empty + + + + @endforelse + +
    NoCoverJudulKode BukuPenulisStokStatusAksi
    {{ $loop->iteration }}{{ $buku['judul'] }}{{ $buku['judul'] }}{{ $buku['kode_buku'] }}{{ $buku['penulis'] }}{{ $buku['stok'] ?? 0 }} + @if ($buku['status'] == 'Tersedia') + Tersedia + @else + Dipinjam + @endif + +
    + + +
    +
    Tidak ada data buku offline. +
    +
    +
    + + {{-- BUKU ONLINE --}} +
    +
    + + + + + + + + + + + + + @forelse($bukuOnline as $buku) + + + + + + + + + @empty + + + + @endforelse + +
    NoCoverJudulPenulisFile PDFAksi
    {{ $loop->iteration }}{{ $buku['judul'] }}{{ $buku['judul'] }}{{ $buku['penulis'] }}PDF Available +
    + + +
    +
    Tidak ada data buku online.
    +
    +
    + + {{-- ARSIP --}} +
    +
    + + + + + + + + + + + + + + + + +
    NoCoverJudulPenulisTipe AsalAksi
    + + Belum ada buku yang diarsipkan. +
    +
    +
    + +
    +
    +
    + + {{-- MODAL DETAIL BUKU --}} + + + @push('scripts') + + @endpush +
    \ No newline at end of file diff --git a/resources/views/admin/dashboard.blade.php b/resources/views/admin/dashboard.blade.php new file mode 100644 index 0000000..a17b2f8 --- /dev/null +++ b/resources/views/admin/dashboard.blade.php @@ -0,0 +1,182 @@ + + @section('page-title', 'Beranda') + + {{-- Welcome card Section --}} +
    +
    +
    +

    {{ $greeting }}, {{ $user->nama_lengkap }}!

    +

    Berikut adalah ringkasan aktivitas perpustakaan hari ini.

    +
    +
    + +
    + Ilustrasi Dashboard +
    +
    + + {{-- Kartu Statistik --}} +
    + @foreach ($stats as $stat) +
    +
    +
    +
    +
    +
    {{ $stat['label'] }}
    +

    {{ $stat['value'] }}

    +
    +
    +
    + +
    +
    +
    +
    +
    +
    + @endforeach +
    + +
    +
    +
    +
    +
    Total Peminjaman per Bulan
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    Komposisi Status Buku
    +
    +
    +
    + +
    +
    +
    +
    + Tersedia + Dipinjam +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    Pengumuman
    + + Kelola Semua + +
    +
    + @forelse(collect($pengumuman)->take(2) as $item) +
    + +
    +
    {{ $item['title'] }}!
    +
    {{ $item['content'] }}
    +
    +
    + @empty +

    Tidak ada pengumuman baru.

    + @endforelse +
    +
    +
    +
    +
    +
    +
    Aktivitas Peminjaman Terkini
    +
    +
    +
    + + + @forelse($aktivitasTerakhir as $aktivitas) + + + + + @empty + + @endforelse + +
    +
    {{ $aktivitas['nama'] }}
    +
    {{ $aktivitas['tipe'] }} buku "{{ $aktivitas['judul_buku'] }}"
    +
    + @if($aktivitas['status'] == 'Dikembalikan' || $aktivitas['status'] == 'Selesai') + {{$aktivitas['status']}} + @else + {{$aktivitas['status']}} + @endif +
    {{ $aktivitas['waktu'] }}
    +

    Tidak ada aktivitas terkini.

    +
    +
    +
    +
    +
    + + + @push('scripts') + + + @endpush +
    \ No newline at end of file diff --git a/resources/views/admin/denda/index.blade.php b/resources/views/admin/denda/index.blade.php new file mode 100644 index 0000000..d455dc2 --- /dev/null +++ b/resources/views/admin/denda/index.blade.php @@ -0,0 +1,260 @@ + + @section('page-title', 'Manajemen Denda') + +
    +
    +

    Manajemen Denda & Sanksi

    +

    Pantau pengguna terlambat dan berikan sanksi jika diperlukan.

    +
    +
    + + {{-- FILTER SECTION --}} +
    +
    +
    +
    + Filter Data: +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    +
    + +
    +
    +
    + + + + + + + + + + + + + @forelse ($siswaTelat as $item) + + + + + + {{-- KOLOM STATUS --}} + + + {{-- KOLOM DENDA --}} + + + {{-- KOLOM AKSI --}} + + + @empty + + + + @endforelse + +
    NONAMABUKU TERLAMBATSTATUSDENDAAKSI
    {{ $loop->iteration }} +
    {{ $item['peminjam'] }}
    + {{ $item['kelas'] }} +
    + {{ $item['nomor_hp'] }} +
    +
    +
      + @foreach ($item['books'] as $buku) +
    • {{ $buku['judul'] }}
    • + @endforeach +
    +
    + @if(isset($item['role']) && strtolower($item['role']) === 'guru') +
    -
    + @else + + Telat {{ $item['hari_terlambat'] }} Hari + +
    + Tenggat: {{ $item['tenggat_kembali']->format('d/m/Y') }} +
    + @endif +
    + @if(isset($item['role']) && strtolower($item['role']) === 'guru') +
    -
    + @else +
    Rp {{ number_format($item['total_denda'], 0, ',', '.') }}
    + Rp 1.000/hari + @endif +
    +
    + {{-- Tombol WA (Muncul untuk semua) --}} + + + + + @if(!isset($item['role']) || strtolower($item['role']) !== 'guru') + @if ($item['is_banned']) + {{-- Jika sudah dibekukan (Otomatis/Manual), muncul tombol AKTIFKAN --}} + + @else + {{-- Jika belum dibekukan, muncul tombol SANKSI (Manual) --}} + + @endif + @endif +
    +
    +
    + +

    Tidak ada buku terlambat hari ini.

    +
    +
    +
    +
    +
    + + @push('scripts') + + @endpush +
    \ No newline at end of file diff --git a/resources/views/admin/peminjaman/create.blade.php b/resources/views/admin/peminjaman/create.blade.php new file mode 100644 index 0000000..f79e132 --- /dev/null +++ b/resources/views/admin/peminjaman/create.blade.php @@ -0,0 +1,304 @@ + + @section('page-title', $pageTitle) + +
    + + + +

    Formulir Peminjaman Manual

    +
    + +
    @csrf +
    + +
    +
    +
    + +
    Data Peminjaman
    +
    + + +
    + +
    +
    Detail Identitas
    +
    +
    NIP/NISN: -
    +
    No. HP: -
    +
    Jabatan/Kelas: -
    +
    Role: -
    +
    +
    + +
    +
    + + +
    +
    + + +
    +
    + +
    + +
    +
    Buku Terpilih
    + 0 Buku +
    + +
    +
    + +

    Belum ada buku yang dipilih.

    +
    +
    + +
    + +
    + +
    + +
    +
    +
    + +
    +
    +
    +
    Pilih Buku
    +
    +
    +
    +
    + + +
    +
    + +
    + @foreach ($daftarBuku as $buku) +
    + +
    + Cover +
    +
    {{ $buku['judul'] }}
    +

    {{ $buku['penulis'] }}

    + {{ $buku['kategori'] }} +
    +
    + +
    +
    +
    + @endforeach +
    +
    +
    +
    +
    +
    + + @push('scripts') + + @endpush +
    \ No newline at end of file diff --git a/resources/views/admin/peminjaman/index.blade.php b/resources/views/admin/peminjaman/index.blade.php new file mode 100644 index 0000000..417cba0 --- /dev/null +++ b/resources/views/admin/peminjaman/index.blade.php @@ -0,0 +1,294 @@ + + @section('page-title', $pageTitle) + +
    +
    +

    Manajemen Peminjaman

    +

    Daftar ini hanya menampilkan buku yang masih berstatus "Dipinjam".

    +
    +
    +
    + + +
    + + + Peminjaman Manual + +
    +
    + +
    +
    +
    + + + + + + + + + + + + + + + @php + $now = \Carbon\Carbon::now(); + $counter = 1; + @endphp + + @forelse ($peminjamanAktif as $transaksi) + @php + $tenggat = $transaksi['tenggat_kembali']; + $isTerlambat = $now->startOfDay()->isAfter($tenggat->startOfDay()); + $isHariIni = $now->startOfDay()->isSameDay($tenggat->startOfDay()); + $selisihHari = $now->startOfDay()->diffInDays($tenggat->startOfDay(), false); + + $isGuru = isset($transaksi['role']) && strtolower($transaksi['role']) == 'guru'; + + if ($isTerlambat) { + if ($isGuru) { + $statusClass = 'badge rounded-pill bg-info-subtle text-info-emphasis'; + $statusText = 'Terlambat (Bebas Denda)'; + } else { + $statusClass = 'badge rounded-pill bg-danger-subtle text-danger-emphasis'; + $statusText = 'Terlambat ' . $tenggat->startOfDay()->diffInDays($now->startOfDay()) . ' hari'; + } + } elseif ($isHariIni) { + $statusClass = 'badge rounded-pill bg-warning-subtle text-warning-emphasis'; + $statusText = 'Jatuh Tempo Hari Ini'; + } else { + $statusClass = 'badge rounded-pill bg-success-subtle text-success-emphasis'; + $statusText = 'Sisa ' . abs($selisihHari) . ' hari'; + } + @endphp + + + + + + + + + + + + + {{-- MODAL PENGEMBALIAN --}} + + @empty + + @endforelse + +
    NOID PEMINJAMANPEMINJAM (JABATAN/KELAS)JUDUL BUKUTGL. PINJAMTENGGAT KEMBALISTATUSAKSI
    {{ $counter++ }} + {{ $transaksi['id_peminjaman'] }} + +
    {{ $transaksi['peminjam'] }}
    +
    {{ $transaksi['nomor_hp'] }}
    +
    +
      + @foreach ($transaksi['books'] as $buku) +
    • {{ $buku['judul'] }}
    • + @endforeach +
    +
    {{ $transaksi['tanggal_pinjam']->format('d/m/Y') }}{{ $transaksi['tenggat_kembali']->format('d/m/Y') }} + {{ $statusText }} + + +
    Tidak ada data.
    +
    +
    +
    + + @push('scripts') + + @endpush +
    \ No newline at end of file diff --git a/resources/views/admin/pengguna/create.blade.php b/resources/views/admin/pengguna/create.blade.php new file mode 100644 index 0000000..22c004f --- /dev/null +++ b/resources/views/admin/pengguna/create.blade.php @@ -0,0 +1,177 @@ + + @section('page-title', $pageTitle) +
    + + + +

    Formulir Tambah Pengguna

    +
    + +
    +
    +
    +
    +
    + @csrf + +
    + + + @error('role') +
    {{ $message }}
    + @enderror +
    + + {{-- Bagian Form Dinamis --}} +
    + +
    + + +
    + +
    + + + @error('nomor_induk') +
    {{ $message }}
    + @enderror +
    + +
    +
    + + + @error('email') +
    {{ $message }}
    + @enderror +
    +
    + + +
    +
    + + + +
    + +
    +
    + +
    + + + @error('password') +
    {{ $message }}
    + @enderror +
    +
    + +
    + +
    + + +
    +
    +
    + +
    + +
    +
    +
    +
    +
    +
    +
    + + @push('scripts') + + @endpush +
    \ No newline at end of file diff --git a/resources/views/admin/pengguna/edit.blade.php b/resources/views/admin/pengguna/edit.blade.php new file mode 100644 index 0000000..9acfea2 --- /dev/null +++ b/resources/views/admin/pengguna/edit.blade.php @@ -0,0 +1,128 @@ + + @section('page-title', $pageTitle) +
    + + + +

    Formulir Edit Pengguna

    +
    + +
    +
    +
    +
    +
    + @csrf + @method('PATCH') + +
    + + + @error('role')
    {{ $message }}
    @enderror +
    + +
    +
    + + +
    + +
    + @php $oldNomorInduk = old('nomor_induk', $pengguna->role == 'siswa' ? $pengguna->nisn : $pengguna->nip); @endphp + + + @error('nomor_induk')
    {{ $message }}
    @enderror +
    + +
    +
    + + + @error('email')
    {{ $message }}
    @enderror +
    +
    + + +
    +
    + + + +
    + +
    +
    + + + @error('password')
    {{ $message }}
    @enderror +
    +
    + + +
    +
    + +
    + +
    +
    +
    +
    +
    +
    +
    + + @push('scripts') + + @endpush +
    \ No newline at end of file diff --git a/resources/views/admin/pengguna/index.blade.php b/resources/views/admin/pengguna/index.blade.php new file mode 100644 index 0000000..cd829cb --- /dev/null +++ b/resources/views/admin/pengguna/index.blade.php @@ -0,0 +1,324 @@ + + @section('page-title', 'Manajemen Pengguna') +
    + +
    +

    {{ $pageTitle ?? 'Manajemen Pengguna' }}

    +
    + +
    +
    +
    Daftar Pengguna Aktif
    + +
    +
    + +
    + + + Tambah Pengguna + +
    +
    +
    +
    + + + + + + + + + + + + + + @forelse($users as $index => $user) + + + + + + + + + + @empty + + + + @endforelse + +
    NoNama LengkapKontak (Email & HP)RoleNISN / NIP / NIKKelas / GolonganAksi
    {{ $users->firstItem() + $index }}{{ $user->name }} +
    {{ $user->email }}
    +
    {{ $user->no_hp ?? + '-' }}
    +
    + @if($user->role == 'guru') + Guru + @elseif($user->role == 'siswa') + Siswa + @else + Petugas + @endif + + {{ $user->nisn ?? ($user->nip ?? '-') }} + + @if($user->role == 'siswa') + Kelas: {{ $user->kelas ?? '-' }} / {{ + $user->golongan ?? '-' }} + @else + - + @endif + + + Edit + + + + +
    + @csrf + @method('DELETE') + +
    +
    Belum ada pengguna terdaftar.
    +
    + {{ $users->links() }} +
    +
    +
    +
    + +
    + + {{-- BAGIAN DATA INDUK (WHITELIST) --}} +
    +
    +

    Data Induk (Whitelist) +

    +

    Daftar NIP/NISN/NIK yang diizinkan untuk mendaftar.

    +
    + +
    + +
    +
    +
    + + + + + + + + + + + + + @forelse($whitelists as $index => $item) + + + + + + + + + @empty + + + + @endforelse + +
    NoNIP / NISNNama PemilikRoleStatus AkunAksi
    {{ $index + 1 }}{{ $item->nomor_induk }}{{ $item->nama_pemilik }} + @if($item->role == 'guru') + Guru + @elseif($item->role == 'siswa') + Siswa + @else + Petugas + @endif + + @php + $isRegistered = \App\Models\User::where('nisn', $item->nomor_induk)->orWhere('nip', + $item->nomor_induk)->exists(); + @endphp + @if ($isRegistered) + Terdaftar + @else + Belum Daftar + @endif + +
    + @csrf + @method('DELETE') + +
    +
    Belum ada data whitelist. Silakan + tambah data.
    +
    +
    +
    +
    + + {{-- MODAL TAMBAH DATA INDUK --}} + + + @push('scripts') + + @endpush +
    \ No newline at end of file diff --git a/resources/views/admin/pengumuman/create.blade.php b/resources/views/admin/pengumuman/create.blade.php new file mode 100644 index 0000000..c1efcc5 --- /dev/null +++ b/resources/views/admin/pengumuman/create.blade.php @@ -0,0 +1,70 @@ + + @section('page-title', $pageTitle) +
    + + + +

    Formulir Tambah Pengumuman

    +
    + +
    +
    +
    +
    +
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + + @push('scripts') + + @endpush +
    \ No newline at end of file diff --git a/resources/views/admin/pengumuman/edit.blade.php b/resources/views/admin/pengumuman/edit.blade.php new file mode 100644 index 0000000..727cde7 --- /dev/null +++ b/resources/views/admin/pengumuman/edit.blade.php @@ -0,0 +1,71 @@ + + @section('page-title', $pageTitle) +
    + + + +

    Formulir Edit Pengumuman

    +
    + +
    +
    +
    +
    +
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + + @push('scripts') + + @endpush +
    \ No newline at end of file diff --git a/resources/views/admin/pengumuman/index.blade.php b/resources/views/admin/pengumuman/index.blade.php new file mode 100644 index 0000000..dc2a2e4 --- /dev/null +++ b/resources/views/admin/pengumuman/index.blade.php @@ -0,0 +1,111 @@ + + @section('page-title', $pageTitle) + +
    +
    +
    Kelola Pengumuman
    + + Buat Pengumuman + +
    +
    +
    + + + + + + + + + + + + @forelse ($semuaPengumuman as $item) + + + + + + + + @empty + + + + @endforelse + +
    NoTipeJudulIsiAksi
    {{ $loop->iteration }} + {{ Str::title($item['type']) }} + {{ $item['title'] }} + {{ $item['content'] }} + + + + + +
    +

    Belum ada pengumuman yang dibuat.

    +
    +
    +
    +
    + + @push('scripts') + + @endpush +
    \ No newline at end of file diff --git a/resources/views/admin/rekomendasi/create.blade.php b/resources/views/admin/rekomendasi/create.blade.php new file mode 100644 index 0000000..de154c3 --- /dev/null +++ b/resources/views/admin/rekomendasi/create.blade.php @@ -0,0 +1,40 @@ + + @section('page-title', $pageTitle) +
    + + + +

    Formulir Tambah Rekomendasi

    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    + @push('scripts') + + + @endpush +
    diff --git a/resources/views/admin/rekomendasi/edit.blade.php b/resources/views/admin/rekomendasi/edit.blade.php new file mode 100644 index 0000000..423033f --- /dev/null +++ b/resources/views/admin/rekomendasi/edit.blade.php @@ -0,0 +1,40 @@ + + @section('page-title', $pageTitle) +
    + + + +

    Formulir Edit Rekomendasi

    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    + @push('scripts') + + + @endpush +
    diff --git a/resources/views/admin/rekomendasi/index.blade.php b/resources/views/admin/rekomendasi/index.blade.php new file mode 100644 index 0000000..f8302fc --- /dev/null +++ b/resources/views/admin/rekomendasi/index.blade.php @@ -0,0 +1,103 @@ + + @section('page-title', $pageTitle) +
    +
    +
    Kelola Rekomendasi Pembelajaran
    + + Buat Rekomendasi + +
    +
    +
    + + + + + + + + + + + + @foreach($semuaRekomendasi as $item) + + + + + + + + @endforeach + +
    NoThumbnailJudulKategoriAksi
    {{ $loop->iteration }}Thumbnail{{ $item['judul'] }}{{ $item['kategori'] }} +
    + + + + + +
    +
    +
    +
    +
    + + @push('scripts') + + @endpush +
    \ No newline at end of file diff --git a/resources/views/auth/admin-login.blade.php b/resources/views/auth/admin-login.blade.php new file mode 100644 index 0000000..9947ac2 --- /dev/null +++ b/resources/views/auth/admin-login.blade.php @@ -0,0 +1,45 @@ + + @if ($errors->has('forbidden')) + + @endif + + + +
    + @csrf + + + +
    + +

    Login Petugas

    +

    Halaman ini khusus untuk Penjaga Perpustakaan.

    +
    + +
    + + + +
    + +
    + +
    + + +
    +
    + +
    + +
    +

    + Kembali ke halaman utama. +

    +
    +
    diff --git a/resources/views/auth/confirm-password.blade.php b/resources/views/auth/confirm-password.blade.php new file mode 100644 index 0000000..3d38186 --- /dev/null +++ b/resources/views/auth/confirm-password.blade.php @@ -0,0 +1,27 @@ + +
    + {{ __('This is a secure area of the application. Please confirm your password before continuing.') }} +
    + +
    + @csrf + + +
    + + + + + +
    + +
    + + {{ __('Confirm') }} + +
    +
    +
    diff --git a/resources/views/auth/forgot-password.blade.php b/resources/views/auth/forgot-password.blade.php new file mode 100644 index 0000000..cb32e08 --- /dev/null +++ b/resources/views/auth/forgot-password.blade.php @@ -0,0 +1,25 @@ + +
    + {{ __('Forgot your password? No problem. Just let us know your email address and we will email you a password reset link that will allow you to choose a new one.') }} +
    + + + + +
    + @csrf + + +
    + + + +
    + +
    + + {{ __('Email Password Reset Link') }} + +
    +
    +
    diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php new file mode 100644 index 0000000..4b5d875 --- /dev/null +++ b/resources/views/auth/login.blade.php @@ -0,0 +1,107 @@ + + @if ($errors->has('forbidden')) + + @endif + +
    + @csrf + + + {{-- HEADER LOGIN --}} +
    +
    + +
    +

    Login {{ Str::title($role) }}

    +

    + @if ($role == 'siswa') + Silakan masukkan NISN dan kata sandi. + @else + Silakan masukkan NIP/NIK dan kata sandi. + @endif +

    +
    + + {{-- INPUT USERNAME (NISN/NIP) --}} +
    + +
    + @if ($role == 'siswa') + + @else + + @endif +
    + {{-- Error Message --}} + @if ($role == 'siswa') + + @else + + @endif +
    + + {{-- INPUT PASSWORD --}} +
    +
    + +
    +
    + + +
    + +
    + + {{-- TOMBOL LOGIN --}} +
    + +
    + + {{-- BANTUAN / LUPA PASSWORD --}} +
    +

    Mengalami kendala login?

    + + Hubungi Petugas via WA + +
    + +

    + Kembali ke halaman utama. +

    +
    + + +
    \ No newline at end of file diff --git a/resources/views/auth/register.blade.php b/resources/views/auth/register.blade.php new file mode 100644 index 0000000..a737151 --- /dev/null +++ b/resources/views/auth/register.blade.php @@ -0,0 +1,94 @@ + +
    +

    Daftar Akun {{ ucfirst($role) }}

    +

    + Silakan isi data diri lengkap untuk mendaftar. +

    +
    + +
    + @csrf + + + +
    + + + @error('name') +
    {{ $message }}
    + @enderror +
    + +
    + + + + + @error($role == 'siswa' ? 'nisn' : 'nip') +
    {{ $message }}
    + @enderror +
    + +
    + + + +
    + + Notifikasi denda & peminjaman akan dikirim ke email ini. +
    + + @error('email') +
    {{ $message }}
    + @enderror +
    + +
    + +
    + + +
    + @error('password') +
    {{ $message }}
    + @enderror +
    + +
    + +
    + + +
    +
    + +
    + +
    + + {{-- Link Login dinamis --}} +

    + Sudah punya akun? + Masuk di + sini +

    +
    +
    diff --git a/resources/views/auth/reset-password-request.blade.php b/resources/views/auth/reset-password-request.blade.php new file mode 100644 index 0000000..3aa623a --- /dev/null +++ b/resources/views/auth/reset-password-request.blade.php @@ -0,0 +1,135 @@ + + {{-- VERIFIKASI OTP --}} +
    +
    +

    Verifikasi Kode OTP

    +

    Masukkan 6 digit kode yang diberikan Admin via WhatsApp.

    +
    + +
    +
    + + +
    + +
    + +
    + + +
    +
    + + {{-- PASSWORD BARU --}} +
    +
    +

    Buat Kata Sandi Baru

    +

    OTP Valid! Silakan buat kata sandi baru Anda.

    +
    + +
    + {{-- Password Utama --}} +
    + +
    + + +
    +
    + + {{-- Konfirmasi Password --}} +
    + +
    + + +
    +
    + +
    + +
    +
    +
    + + + + + +
    \ No newline at end of file diff --git a/resources/views/auth/reset-password.blade.php b/resources/views/auth/reset-password.blade.php new file mode 100644 index 0000000..a6494cc --- /dev/null +++ b/resources/views/auth/reset-password.blade.php @@ -0,0 +1,39 @@ + +
    + @csrf + + + + + +
    + + + +
    + + +
    + + + +
    + + +
    + + + + + +
    + +
    + + {{ __('Reset Password') }} + +
    +
    +
    diff --git a/resources/views/auth/verify-email.blade.php b/resources/views/auth/verify-email.blade.php new file mode 100644 index 0000000..eaf811d --- /dev/null +++ b/resources/views/auth/verify-email.blade.php @@ -0,0 +1,31 @@ + +
    + {{ __('Thanks for signing up! Before getting started, could you verify your email address by clicking on the link we just emailed to you? If you didn\'t receive the email, we will gladly send you another.') }} +
    + + @if (session('status') == 'verification-link-sent') +
    + {{ __('A new verification link has been sent to the email address you provided during registration.') }} +
    + @endif + +
    +
    + @csrf + +
    + + {{ __('Resend Verification Email') }} + +
    +
    + +
    + @csrf + + +
    +
    +
    diff --git a/resources/views/baca/request_code.blade.php b/resources/views/baca/request_code.blade.php new file mode 100644 index 0000000..1e2cee2 --- /dev/null +++ b/resources/views/baca/request_code.blade.php @@ -0,0 +1,122 @@ +@section('page-title', 'Kode Akses Buku') + + + + + {{-- Script untuk Salin Kode, Menampilkan Modal, dan Redirect saat ditutup --}} + + + diff --git a/resources/views/baca/view_book.blade.php b/resources/views/baca/view_book.blade.php new file mode 100644 index 0000000..a38b013 --- /dev/null +++ b/resources/views/baca/view_book.blade.php @@ -0,0 +1,31 @@ +@section('page-title', 'Membaca: ' . $book['judul']) + +
    + +
    +

    {{ $book['judul'] }}

    + + + Tutup + +
    + +
    + {{-- src memanggil route streamPdf yang aman, bukan direct link ke file PDF --}} + +
    + +
    +
    + +{{-- Override CSS agar layout
    bisa memenuhi lebar container-fluid --}} +@push('styles') + +@endpush diff --git a/resources/views/components/application-logo.blade.php b/resources/views/components/application-logo.blade.php new file mode 100644 index 0000000..46579cf --- /dev/null +++ b/resources/views/components/application-logo.blade.php @@ -0,0 +1,3 @@ + + + diff --git a/resources/views/components/auth-session-status.blade.php b/resources/views/components/auth-session-status.blade.php new file mode 100644 index 0000000..c4bd6e2 --- /dev/null +++ b/resources/views/components/auth-session-status.blade.php @@ -0,0 +1,7 @@ +@props(['status']) + +@if ($status) +
    merge(['class' => 'font-medium text-sm text-green-600']) }}> + {{ $status }} +
    +@endif diff --git a/resources/views/components/book-card.blade.php b/resources/views/components/book-card.blade.php new file mode 100644 index 0000000..1c9a539 --- /dev/null +++ b/resources/views/components/book-card.blade.php @@ -0,0 +1,26 @@ +@props(['buku']) + +
    +
    +
    +
    + Cover {{ $buku['judul'] }} +
    +
    +
    +
    +
    +
    + {{ $buku['judul'] }} +
    +

    + {{ $buku['penulis'] }} +

    +
    +
    + {{ $slot }} +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/resources/views/components/danger-button.blade.php b/resources/views/components/danger-button.blade.php new file mode 100644 index 0000000..d17d288 --- /dev/null +++ b/resources/views/components/danger-button.blade.php @@ -0,0 +1,3 @@ + diff --git a/resources/views/components/dropdown-link.blade.php b/resources/views/components/dropdown-link.blade.php new file mode 100644 index 0000000..e0f8ce1 --- /dev/null +++ b/resources/views/components/dropdown-link.blade.php @@ -0,0 +1 @@ +merge(['class' => 'block w-full px-4 py-2 text-start text-sm leading-5 text-gray-700 hover:bg-gray-100 focus:outline-none focus:bg-gray-100 transition duration-150 ease-in-out']) }}>{{ $slot }} diff --git a/resources/views/components/dropdown.blade.php b/resources/views/components/dropdown.blade.php new file mode 100644 index 0000000..a46f7c8 --- /dev/null +++ b/resources/views/components/dropdown.blade.php @@ -0,0 +1,35 @@ +@props(['align' => 'right', 'width' => '48', 'contentClasses' => 'py-1 bg-white']) + +@php +$alignmentClasses = match ($align) { + 'left' => 'ltr:origin-top-left rtl:origin-top-right start-0', + 'top' => 'origin-top', + default => 'ltr:origin-top-right rtl:origin-top-left end-0', +}; + +$width = match ($width) { + '48' => 'w-48', + default => $width, +}; +@endphp + +
    +
    + {{ $trigger }} +
    + + +
    diff --git a/resources/views/components/input-error.blade.php b/resources/views/components/input-error.blade.php new file mode 100644 index 0000000..9e6da21 --- /dev/null +++ b/resources/views/components/input-error.blade.php @@ -0,0 +1,9 @@ +@props(['messages']) + +@if ($messages) +
      merge(['class' => 'text-sm text-red-600 space-y-1']) }}> + @foreach ((array) $messages as $message) +
    • {{ $message }}
    • + @endforeach +
    +@endif diff --git a/resources/views/components/input-label.blade.php b/resources/views/components/input-label.blade.php new file mode 100644 index 0000000..1cc65e2 --- /dev/null +++ b/resources/views/components/input-label.blade.php @@ -0,0 +1,5 @@ +@props(['value']) + + diff --git a/resources/views/components/modal.blade.php b/resources/views/components/modal.blade.php new file mode 100644 index 0000000..70704c1 --- /dev/null +++ b/resources/views/components/modal.blade.php @@ -0,0 +1,78 @@ +@props([ + 'name', + 'show' => false, + 'maxWidth' => '2xl' +]) + +@php +$maxWidth = [ + 'sm' => 'sm:max-w-sm', + 'md' => 'sm:max-w-md', + 'lg' => 'sm:max-w-lg', + 'xl' => 'sm:max-w-xl', + '2xl' => 'sm:max-w-2xl', +][$maxWidth]; +@endphp + +
    +
    +
    +
    + +
    + {{ $slot }} +
    +
    diff --git a/resources/views/components/nav-link.blade.php b/resources/views/components/nav-link.blade.php new file mode 100644 index 0000000..5c101a2 --- /dev/null +++ b/resources/views/components/nav-link.blade.php @@ -0,0 +1,11 @@ +@props(['active']) + +@php +$classes = ($active ?? false) + ? 'inline-flex items-center px-1 pt-1 border-b-2 border-indigo-400 text-sm font-medium leading-5 text-gray-900 focus:outline-none focus:border-indigo-700 transition duration-150 ease-in-out' + : 'inline-flex items-center px-1 pt-1 border-b-2 border-transparent text-sm font-medium leading-5 text-gray-500 hover:text-gray-700 hover:border-gray-300 focus:outline-none focus:text-gray-700 focus:border-gray-300 transition duration-150 ease-in-out'; +@endphp + +merge(['class' => $classes]) }}> + {{ $slot }} + diff --git a/resources/views/components/primary-button.blade.php b/resources/views/components/primary-button.blade.php new file mode 100644 index 0000000..d71f0b6 --- /dev/null +++ b/resources/views/components/primary-button.blade.php @@ -0,0 +1,3 @@ + diff --git a/resources/views/components/responsive-nav-link.blade.php b/resources/views/components/responsive-nav-link.blade.php new file mode 100644 index 0000000..43b91e7 --- /dev/null +++ b/resources/views/components/responsive-nav-link.blade.php @@ -0,0 +1,11 @@ +@props(['active']) + +@php +$classes = ($active ?? false) + ? 'block w-full ps-3 pe-4 py-2 border-l-4 border-indigo-400 text-start text-base font-medium text-indigo-700 bg-indigo-50 focus:outline-none focus:text-indigo-800 focus:bg-indigo-100 focus:border-indigo-700 transition duration-150 ease-in-out' + : 'block w-full ps-3 pe-4 py-2 border-l-4 border-transparent text-start text-base font-medium text-gray-600 hover:text-gray-800 hover:bg-gray-50 hover:border-gray-300 focus:outline-none focus:text-gray-800 focus:bg-gray-50 focus:border-gray-300 transition duration-150 ease-in-out'; +@endphp + +merge(['class' => $classes]) }}> + {{ $slot }} + diff --git a/resources/views/components/secondary-button.blade.php b/resources/views/components/secondary-button.blade.php new file mode 100644 index 0000000..b32b69f --- /dev/null +++ b/resources/views/components/secondary-button.blade.php @@ -0,0 +1,3 @@ + diff --git a/resources/views/components/text-input.blade.php b/resources/views/components/text-input.blade.php new file mode 100644 index 0000000..0612d5b --- /dev/null +++ b/resources/views/components/text-input.blade.php @@ -0,0 +1,3 @@ +@props(['disabled' => false]) + +merge(['class' => 'form-control']) }}> \ No newline at end of file diff --git a/resources/views/dashboard.blade.php b/resources/views/dashboard.blade.php new file mode 100644 index 0000000..f4f919f --- /dev/null +++ b/resources/views/dashboard.blade.php @@ -0,0 +1,431 @@ +@section('page-title', 'Beranda') + + + {{-- CEK STATUS BANNED --}} + @if (Auth::user()->is_banned) + + @endif + + {{-- HERO SECTION --}} +
    +
    +
    +

    {{ $greeting }}, {{ $user->nama_lengkap }}!

    +

    Siap memulai harimu dengan bacaan baru?

    +
    +
    + +
    + Ilustrasi Beranda +
    +
    + + {{-- Statistic Card --}} +
    + @foreach ($stats as $stat) +
    +
    +
    +
    + +
    +
    +

    {{ $stat['value'] }}

    +

    {{ $stat['label'] }}

    +
    +
    +
    +
    + @endforeach +
    + + {{-- Chart Statistic --}} +
    +
    +
    +
    +
    +
    + +
    +
    Statistik Bulanan
    +
    +
    +
    + [], 'data' => []])'> + +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    Progress Membaca
    +
    +
    +
    +
    + 0, 'sisa' => 0])'> + +
    +
    +
    +
    + + Telah Dibaca + + + Belum Dibaca + +
    +
    +
    +
    +
    + + {{-- Section Pemberitahuan dan Pengumuman --}} +
    +
    +
    +
    +
    +
    + +
    +
    Pengumuman
    +
    + +
    +
    + @forelse(collect($pengumuman)->take(2) as $item) + + @empty +
    + +

    Tidak ada pengumuman baru.

    +
    + @endforelse +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    Pemberitahuan
    +
    + +
    +
    + @forelse(collect($pemberitahuan)->take(3) as $item) +
    +
    +
    + +
    +
    +
    {{ $item['title'] }}:
    +
    {{ $item['content'] }}
    +
    +
    + + {{ $item['badge'] }} + +
    + @if (!$loop->last) +
    + @endif + @empty +
    + +

    Tidak ada pemberitahuan baru.

    +
    + @endforelse +
    +
    +
    +
    + + {{-- Section Buku Pinjam Offline --}} +
    +
    +
    + Buku Pinjam Offline +
    + @if (count($bukuPinjamOffline) > 2) +
    + +
    + @endif +
    +
    +
    + @forelse($bukuPinjamOffline as $buku) +
    + + @if($buku['sisa_hari'] < 0) +
    + + Terlambat: {{ abs($buku['sisa_hari']) }} hari +
    + @else +
    + + Sisa: {{ $buku['sisa_hari'] }} hari +
    + @endif +
    +
    + @empty +
    +
    + +

    Tidak ada buku yang sedang dipinjam secara offline.

    +
    +
    + @endforelse +
    +
    +
    + + {{-- Section Baca Buku Online --}} +
    +
    +
    + Baca Buku Online +
    + @if (count($bacaBukuOnline) > 3) +
    + +
    + @endif +
    +
    +
    + @forelse($bacaBukuOnline as $buku) +
    + +
    +
    + Progress {{ $buku['progress'] }}% +
    +
    +
    +
    +
    +
    +
    + @empty +
    +
    + +

    Tidak ada buku yang sedang dibaca secara online.

    +
    +
    + @endforelse +
    +
    +
    + + {{-- Section Rekomendasi Pembelajaran (Role Guru) --}} + @if (Auth::user()->role == 'guru') +
    +
    +
    + Rekomendasi Pembelajaran +
    + +
    +
    + @forelse(collect($rekomendasiPembelajaran)->take(3) as $item) + + Thumbnail +
    +
    {{ $item['judul'] }}
    + {{ $item['kategori'] }} +
    +
    + @if (!$loop->last) +
    + @endif + @empty +

    Belum ada rekomendasi.

    + @endforelse +
    +
    + @endif + + + + + + + + + + +
    \ No newline at end of file diff --git a/resources/views/guru/laporan/index.blade.php b/resources/views/guru/laporan/index.blade.php new file mode 100644 index 0000000..5f41b83 --- /dev/null +++ b/resources/views/guru/laporan/index.blade.php @@ -0,0 +1,185 @@ + + @section('page-title', $pageTitle) + +
    +
    + {{-- ========================= --}} + {{-- KOLOM KIRI (KONTEN UTAMA) --}} + {{-- ========================= --}} +
    + {{-- Grafik Aktivitas Membaca --}} +
    +
    +

    + Grafik Aktivitas Membaca (7 Hari Terakhir) +

    +
    +
    +
    + +
    + +
    +
    + +
    + + {{-- BUKU TERPOPULER --}} +
    +
    +
    +

    + Buku Terpopuler +

    +
    +
    +
    + @foreach ($laporan['buku_terpopuler'] as $buku) +
    + Cover +
    +
    {{ $buku['judul'] }}
    +
    + + {{ $buku['total_pembaca'] }} + +
    + @if (!$loop->last) +
    + @endif + @endforeach +
    +
    +
    +
    + + {{-- KATEGORI PALING DIMINATI --}} +
    +
    +
    +

    + Kategori Paling Diminati +

    +
    +
    +
    + @foreach ($laporan['kategori_populer'] as $kategori) +
    + + + {{ $kategori['nama'] }} + + + {{ $kategori['total_pembaca'] }} + +
    + @if (!$loop->last) +
    + @endif + @endforeach +
    +
    +
    +
    +
    +
    + + {{-- ========================= --}} + {{-- KOLOM KANAN {SISWA AKTIF} --}} + {{-- ========================= --}} +
    +
    +
    +

    + Siswa Paling Aktif +

    +
    +
    + @foreach ($siswaTeraktif as $siswa) +
    + Avatar +
    +
    {{ $siswa['nama'] }}
    + {{ $siswa['kelas'] }} +
    + + {{ $siswa['total_buku'] }} + +
    + @if (!$loop->last) +
    + @endif + @endforeach +
    +
    +
    +
    +
    + + {{-- ========================= --}} + {{-- SCRIPT CHART.JS --}} + {{-- ========================= --}} + @push('scripts') + + + @endpush +
    diff --git a/resources/views/katalog/index.blade.php b/resources/views/katalog/index.blade.php new file mode 100644 index 0000000..b3ae114 --- /dev/null +++ b/resources/views/katalog/index.blade.php @@ -0,0 +1,125 @@ +@section('page-title', $pageTitle) + + + {{-- Filter Section --}} +
    +
    +
    +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    +
    +
    + + {{-- Katalog Buku Section --}} +
    + @forelse ($semuaBuku as $buku) +
    +
    + Cover {{ $buku['judul'] }} + +
    +
    +
    + {{ $buku['kategori'] }} + {{ $buku['status'] }} +
    +
    {{ $buku['judul'] }}
    +

    {{ $buku['penulis'] }}

    +
    + +
    + @php + $userBanned = $isBanned ?? false; + $isOfflineAccess = + $buku['tipe_akses'] === 'offline' || + (is_array($buku['tipe_akses']) && in_array('offline', $buku['tipe_akses'])); + $isOnlineAccess = + $buku['tipe_akses'] === 'online' || + (is_array($buku['tipe_akses']) && in_array('online', $buku['tipe_akses'])); + $stokHabis = $buku['status'] == 'Dipinjam'; + @endphp + + {{-- TOMBOL PINJAM (OFFLINE) --}} + @if ($isOfflineAccess && $mode !== 'online') + @if ($stokHabis) + @if (!$isOnlineAccess) + + @endif + @elseif($userBanned) + {{-- LOGIC : Jika Banned, tombol Pinjam MATI --}} + + @else + + Pinjam + + @endif + @endif + + {{-- TOMBOL BACA (ONLINE) - Selalu Nyala --}} + @if ($isOnlineAccess && $mode !== 'offline') + + Baca + + @endif +
    +
    +
    +
    + @empty +
    +
    +

    Tidak Ada Hasil

    +

    Tidak ada buku yang cocok dengan kriteria filter Anda. Coba reset atau ubah filter.

    +
    + Reset Filter +
    +
    + @endforelse +
    +
    diff --git a/resources/views/katalog/ringkasan.blade.php b/resources/views/katalog/ringkasan.blade.php new file mode 100644 index 0000000..720f377 --- /dev/null +++ b/resources/views/katalog/ringkasan.blade.php @@ -0,0 +1,49 @@ +@section('page-title', $pageTitle) + +
    + +
    + + + +

    Ringkasan Buku

    +
    + +
    +
    +
    + +
    + Cover {{ $buku['judul'] }} +
    + +
    +

    {{ $buku['judul'] }}

    +

    oleh {{ $buku['penulis'] }}

    + +

    + Ini adalah ringkasan atau sinopsis dari buku "{{ $buku['judul'] }}". Lorem ipsum dolor sit + amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore + magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut + aliquip ex ea commodo consequat. +

    + + +
    + +
    +
    +
    + +
    + Copyright © {{ date('Y') }} Perpus. +
    + +
    +
    \ No newline at end of file diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php new file mode 100644 index 0000000..a762f73 --- /dev/null +++ b/resources/views/layouts/app.blade.php @@ -0,0 +1,209 @@ + + + + + + + {{ config('app.name', 'Digipus.go') }} + + {{-- Fonts & Icons --}} + + @vite(['resources/scss/app.scss', 'resources/js/app.js']) + + {{-- Flatpickr --}} + + + + + + + + + + + + + + + +
    + @include('layouts.sidebar') +
    + +
    + @include('layouts.navigation') +
    + @if (session('error')) + + @endif + {{ $slot }} +
    +
    + Copyright © {{ date('Y') }} + {{ config('app.name', 'Perpus') }}. +
    +
    +
    + + + + + + + + + + + + + + + + + + @stack('scripts') + + + + \ No newline at end of file diff --git a/resources/views/layouts/guest.blade.php b/resources/views/layouts/guest.blade.php new file mode 100644 index 0000000..bffe920 --- /dev/null +++ b/resources/views/layouts/guest.blade.php @@ -0,0 +1,89 @@ + + + + + + + + {{ config('app.name', 'DIGIPUS') }} + + {{-- Fonts & Icons (Tetap) --}} + + + + + + @vite(['resources/scss/app.scss', 'resources/js/app.js']) + + + + {{-- Container Utama --}} +
    + +
    + + {{-- Branding Content --}} +
    + +

    + Gerbang Anda menuju dunia pengetahuan. Jelajahi ribuan koleksi buku digital, pinjam dengan mudah, + dan lacak progres membaca Anda. +

    +
    +
    + + {{-- FORM LOGIN --}} +
    +
    + {{ $slot }} +
    +
    + +
    +
    +
    + {{ $slot }} +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/resources/views/layouts/navigation.blade.php b/resources/views/layouts/navigation.blade.php new file mode 100644 index 0000000..b4e58fe --- /dev/null +++ b/resources/views/layouts/navigation.blade.php @@ -0,0 +1,130 @@ + diff --git a/resources/views/layouts/sidebar.blade.php b/resources/views/layouts/sidebar.blade.php new file mode 100644 index 0000000..569736c --- /dev/null +++ b/resources/views/layouts/sidebar.blade.php @@ -0,0 +1,159 @@ + diff --git a/resources/views/peminjaman/form.blade.php b/resources/views/peminjaman/form.blade.php new file mode 100644 index 0000000..34bdda7 --- /dev/null +++ b/resources/views/peminjaman/form.blade.php @@ -0,0 +1,361 @@ +@section('page-title', 'Peminjaman Buku offline') + +
    + + + +
    + +
    +
    +
    +
    + +

    Form Peminjaman Offline

    + +
    +
    + {{-- Header Section: Judul & Tombol Edit --}} +
    +
    + Informasi Peminjam +
    + + Edit Profil + +
    + +
    + {{-- Nama Lengkap (Semua Role) --}} +
    + +

    {{ $user->nama_lengkap ?? $user->name }}

    +
    + + {{-- KONDISI UNTUK GURU / PETUGAS --}} + @if(in_array($user->role, ['guru', 'penjaga perpus'])) +
    + +

    {{ $user->nip ?? '-' }}

    +
    + {{-- KONDISI UNTUK SISWA --}} + @else +
    + +

    {{ $user->nisn ?? '-' }}

    +
    + @endif + + {{-- Email (Semua Role) --}} +
    + +

    {{ $user->email }}

    +
    + + {{-- Nomor HP (Semua Role) --}} +
    + +

    + @if($user->no_hp) + {{ $user->no_hp + }} + @else + - Belum diatur - + @endif +

    +
    + + {{-- Info Tambahan Khusus Siswa --}} + @if($user->role == 'siswa') +
    + +

    {{ $user->kelas ?? '-' }}

    +
    +
    + +

    {{ $user->golongan ?? '-' }}

    +
    + @endif +
    +
    +
    + + {{-- Form untuk submit data --}} +
    + @csrf + + {{-- Informasi Buku & Tanggal --}} +
    +
    +
    Buku yang Dipinjam
    + +
    + + {{-- Container untuk daftar buku yang dipinjam --}} +
    +
    +
    + Cover +
    +
    {{ $buku['judul'] }}
    +

    {{ $buku['penulis'] }}

    + {{ $buku['kategori'] }} +
    + Buku Utama +
    +
    +
    + + {{-- Hidden inputs untuk buku yang dipilih --}} +
    + +
    + + {{-- Tanggal Peminjaman --}} +
    +
    + + +
    +
    + + +
    +
    +
    + + {{-- Peraturan Peminjaman --}} +
    +
    Peraturan Peminjaman
    +
    +
      +
    1. Perpustakaan buka pada jam operasional sekolah.
    2. +
    3. Setiap siswa hanya dapat meminjam sebanyak 1-2 buku dalam satu waktu.
    4. +
    5. Buku yang dipinjam harus dikembalikan dalam jangka waktu yang telah ditentukan. +
    6. +
    7. Jika buku tidak dikembalikan tepat waktu, akan dikenakan denda atau sanksi + lainnya.
    8. +
    9. Buku yang dikembalikan harus dalam kondisi baik, tanpa kerusakan atau hilang. +
    10. +
    11. Dilarang merusak atau mencoret-coret buku.
    12. +
    13. Setiap siswa bertanggung jawab penuh terhadap buku yang dipinjam.
    14. +
    +
    +
    + + {{-- Tombol Kirim Form --}} +
    + +
    +
    + +
    +
    +
    +
    + + {{-- Modal Pilih Buku --}} + + + + {{-- Modal Konfirmasi Kirim --}} + + + +
    \ No newline at end of file diff --git a/resources/views/profile/edit.blade.php b/resources/views/profile/edit.blade.php new file mode 100644 index 0000000..aabf59d --- /dev/null +++ b/resources/views/profile/edit.blade.php @@ -0,0 +1,124 @@ + + @section('page-title', 'Pengaturan Akun') + +
    +
    + + {{-- SIDEBAR MENU (KIRI) --}} +
    +
    +
    +
    + {{-- Header --}} +
    +
    + Pengaturan +
    +
    + + {{-- Menu Tabs --}} + +
    +
    +
    +
    + + {{-- KONTEN KANAN (FORM) --}} +
    +
    + {{-- PROFIL & HAPUS AKUN --}} +
    + + {{-- Form Edit Profil --}} +
    +
    +
    Informasi Profil
    +
    +
    + @include('profile.partials.update-profile-information-form') +
    +
    + + {{-- Form Hapus Akun --}} +
    +
    +
    +
    + +
    +
    +
    Hapus Akun Permanen
    +

    + Tindakan ini tidak dapat dibatalkan. Semua data Anda akan hilang. +

    + @include('profile.partials.delete-user-form') +
    +
    +
    +
    +
    + + {{-- KEAMANAN (PASSWORD) --}} +
    +
    +
    +
    Ganti Kata Sandi
    +
    +
    +
    + +
    + Gunakan password minimal 8 karakter dengan kombinasi huruf dan angka agar akun lebih aman. +
    +
    + + @include('profile.partials.update-password-form') +
    +
    +
    + +
    +
    +
    +
    + + @push('styles') + + @endpush +
    \ No newline at end of file diff --git a/resources/views/profile/index.blade.php b/resources/views/profile/index.blade.php new file mode 100644 index 0000000..6aecc5a --- /dev/null +++ b/resources/views/profile/index.blade.php @@ -0,0 +1,255 @@ + + @section('page-title', 'Profil') + +
    + + @if (Auth::user()->role == 'penjaga perpus') +
    +
    +
    +
    + Foto Profil +
    +

    {{ $user->name }}

    + {{ + Str::title($user->role) }} +
    + +
    +
    + +
    +
    Statistik Perpustakaan
    +
    + @foreach ($statistik as $stat) +
    +
    +
    +
    + +
    +

    {{ $stat['value'] }}

    +

    {{ $stat['label'] }}

    +
    +
    +
    + @endforeach +
    +
    +
    + +
    + + + {{--
    +
    +
    Keamanan Akun
    +

    Ubah password Anda secara berkala untuk menjaga keamanan akun. +

    + + Ubah Password + +
    +
    --}} +
    +
    + + @elseif (Auth::user()->role == 'guru') +
    +
    +
    +
    +
    + Foto Profil +
    +

    {{ $user->name }}

    + {{ + Str::title($user->role) }} +
    + +
    + +
    +
    Informasi Personal
    +
    +
    + NIP/NIK +

    {{ $user->nip ?? $user->nisn ?? '-' }}

    +
    +
    + Email +

    {{ $user->email }}

    +
    +
    + Nomor HP +

    {{ $user->no_hp ?? '-' }}

    +
    +
    +
    +
    + +
    +
    +
    +
    Ringkasan Laporan Minat Baca
    + +
    +
    +
    +
    Buku Terpopuler
    +
      + @foreach ($laporan['buku_terpopuler'] as $buku) +
    • + {{ $buku['judul'] }} + {{ $buku['total_pembaca'] }} +
    • + @endforeach +
    +
    +
    +
    Kategori Terpopuler
    +
      + @foreach ($laporan['kategori_populer'] as $kategori) +
    • + {{ $kategori['nama'] }} + {{ $kategori['total_pembaca'] + }} +
    • + @endforeach +
    +
    +
    +
    +
    +
    + +
    + @include('profile.partials.personal-activities', [ + 'bukuOffline' => $bukuOffline, + 'bukuOnline' => $bukuOnline, + ]) +
    +
    + + @else +
    +
    +
    +
    +
    + Foto Profil +
    +

    {{ $user->name }}

    + {{ + Str::title($user->role) }} +
    + +
    +
    +
    Informasi Personal
    +
    +
    + NISN +

    {{ $user->nisn ?? '-' }}

    +
    +
    + Email +

    {{ $user->email }}

    +
    +
    + Nomor HP +

    {{ $user->no_hp ?? '-' }}

    +
    +
    + Kelas +

    {{ $user->kelas ?? '-' }}

    +
    +
    + Golongan +

    {{ $user->golongan ?? '-' }}

    +
    +
    +
    +
    + +
    +
    Statistik Saya
    +
    + @foreach ($statistik as $stat) +
    +
    +
    +
    + +
    +

    {{ $stat['value'] }}

    +

    {{ $stat['label'] }}

    +
    +
    +
    + @endforeach +
    +
    +
    + +
    + @include('profile.partials.personal-activities', [ + 'bukuOffline' => $bukuOffline, + 'bukuOnline' => $bukuOnline, + ]) +
    +
    + @endif + +
    +
    \ No newline at end of file diff --git a/resources/views/profile/partials/delete-user-form.blade.php b/resources/views/profile/partials/delete-user-form.blade.php new file mode 100644 index 0000000..2f2006a --- /dev/null +++ b/resources/views/profile/partials/delete-user-form.blade.php @@ -0,0 +1,68 @@ +
    +
    +

    + {{ __('Delete Account') }} +

    + +

    + {{ __('Once your account is deleted, all of its resources and data will be permanently deleted. Before deleting your account, please download any data or information that you wish to retain.') }} +

    +
    + + {{-- Tombol Pemicu Modal --}} + + + {{-- Modal Konfirmasi --}} + +
    + +{{-- Script untuk membuka modal jika ada error validasi --}} +@if ($errors->userDeletion->isNotEmpty()) + +@endif diff --git a/resources/views/profile/partials/personal-activities.blade.php b/resources/views/profile/partials/personal-activities.blade.php new file mode 100644 index 0000000..1862ad0 --- /dev/null +++ b/resources/views/profile/partials/personal-activities.blade.php @@ -0,0 +1,44 @@ +{{-- Card Buku yang Dipinjam --}} +
    +
    +
    Buku yang Dipinjam
    +
      + @forelse ($bukuOffline as $buku) +
    • +
      {{ $buku['judul'] }}
      + {{ $buku['penulis'] }} + Sisa {{ $buku['sisa_hari'] }} hari +
    • + @empty +
    • Tidak ada buku yang sedang dipinjam.
    • + @endforelse +
    +
    +
    + +{{-- Card Riwayat Online --}} +
    +
    +
    Baca Buku Online
    +
      + @forelse ($bukuOnline as $buku) +
    • +
      {{ $buku['judul'] }}
      + {{ $buku['penulis'] }} + {{ $buku['progress'] }}% +
    • + @empty +
    • Tidak ada riwayat buku yang dibaca.
    • + @endforelse +
    +
    +
    + +{{-- Card Keamanan Akun +
    +
    +
    Keamanan Akun
    +

    Ubah password Anda secara berkala.

    + Ubah Password +
    +
    --}} \ No newline at end of file diff --git a/resources/views/profile/partials/update-password-form.blade.php b/resources/views/profile/partials/update-password-form.blade.php new file mode 100644 index 0000000..2ea39e7 --- /dev/null +++ b/resources/views/profile/partials/update-password-form.blade.php @@ -0,0 +1,103 @@ +
    +
    +

    + {{ __('Update Password') }} +

    + +

    + {{ __('Pastikan akun Anda menggunakan kata sandi yang panjang dan acak untuk menjaga keamanan.') }} +

    +
    + +
    + @csrf + @method('put') + + {{-- Current Password --}} +
    + +
    + + + @error('current_password', 'updatePassword') +
    {{ $message }}
    + @enderror +
    +
    + + {{-- New Password --}} +
    + +
    + + + @error('password', 'updatePassword') +
    {{ $message }}
    + @enderror +
    +
    + + {{-- Confirm Password --}} +
    + +
    + + + @error('password_confirmation', 'updatePassword') +
    {{ $message }}
    + @enderror +
    +
    + +
    + +
    +
    + + +
    \ No newline at end of file diff --git a/resources/views/profile/partials/update-profile-information-form.blade.php b/resources/views/profile/partials/update-profile-information-form.blade.php new file mode 100644 index 0000000..b50d66f --- /dev/null +++ b/resources/views/profile/partials/update-profile-information-form.blade.php @@ -0,0 +1,108 @@ +
    +
    +

    + {{ __('Informasi Profil') }} +

    + +

    + {{ __("Perbarui informasi profil dan alamat email akun Anda.") }} +

    +
    + +
    + @csrf +
    + +
    + @csrf + @method('patch') + + {{-- Bagian Nama Lengkap --}} +
    + + + @error('name') +
    {{ $message }}
    + @enderror +
    + + {{-- Bagian Email --}} +
    + + + @error('email') +
    {{ $message }}
    + @enderror + + @if ($user instanceof \Illuminate\Contracts\Auth\MustVerifyEmail && !$user->hasVerifiedEmail()) +
    +

    + {{ __('Alamat email Anda belum terverifikasi.') }} + +

    + @if (session('status') === 'verification-link-sent') +

    + {{ __('Tautan verifikasi baru telah dikirim ke alamat email Anda.') }} +

    + @endif +
    + @endif +
    + + {{-- Bagian Nomor Telepon (WA) --}} +
    + +
    + + +
    + @error('no_hp') +
    {{ $message }}
    + @enderror + *Nomor ini digunakan untuk verifikasi & notifikasi. +
    + +
    + + {{-- Bagian Info Spesifik Role (Tidak Dapat Diubah) --}} + @if ($user->role == 'siswa') +
    + + + NISN tidak dapat diubah. +
    +
    +
    + + +
    +
    + + +
    +
    + @else + {{-- Untuk Guru atau Penjaga Perpus --}} +
    + + + NIP/NIK tidak dapat diubah. +
    + @endif + + +
    + + + @if (session('status') === 'profile-updated') + {{ __('Tersimpan.') }} + @endif +
    +
    +
    \ No newline at end of file diff --git a/resources/views/rekomendasiShow.blade.php b/resources/views/rekomendasiShow.blade.php new file mode 100644 index 0000000..d395416 --- /dev/null +++ b/resources/views/rekomendasiShow.blade.php @@ -0,0 +1,24 @@ +@section('page-title', 'Dashboard') + + + @section('page-title', $pageTitle) +
    + + + +
    +
    +
    +
    + +
    + +

    {{ $rekomendasi['judul'] }}

    +
    + {!! $rekomendasi['deskripsi'] !!} +
    +
    +
    +
    diff --git a/resources/views/riwayat/offline.blade.php b/resources/views/riwayat/offline.blade.php new file mode 100644 index 0000000..566f7fb --- /dev/null +++ b/resources/views/riwayat/offline.blade.php @@ -0,0 +1,279 @@ +@section('page-title', $pageTitle) + +
    +
    +
    {{ $pageTitle }}
    +
    +
    +
    + + + + + + + + + + + + + + + @php $counter = 1; @endphp + @if (count($riwayatOffline) > 0) + @foreach ($riwayatOffline as $transaksi) + @foreach ($transaksi['books'] as $buku) + @php + try { + $tglKembali = \Carbon\Carbon::createFromFormat( + 'd/m/Y', + $transaksi['tanggal_kembali'], + )->startOfDay(); + } catch (\Exception $e) { + $tglKembali = \Carbon\Carbon::parse( + $transaksi['tanggal_kembali'], + )->startOfDay(); + } + + $today = now()->startOfDay(); + $isTelat = $today->gt($tglKembali) && $transaksi['status'] == 'Dipinjam'; + + $hariTelat = 0; + $denda = 0; + + if ($isTelat) { + $hariTelat = $tglKembali->diffInDays($today); + $denda = $hariTelat * 1000; + } + @endphp + + + + + + + + + + + + @endforeach + @endforeach + @endif + +
    NOID PEMINJAMANKODE BUKUJUDUL BUKUTANGGAL PINJAMTANGGAL KEMBALISTATUSAKSI
    {{ $counter++ }}{{ $transaksi['id_peminjaman'] }}{{ $buku['kode_buku'] }}{{ $buku['judul'] }}{{ $transaksi['tanggal_pinjam'] }}{{ $transaksi['tanggal_kembali'] }} + @if ($transaksi['status'] == 'Dikembalikan') + Dikembalikan + @elseif($isTelat) + {{-- LOGIC BADGE STATUS DI TABEL --}} + @if (Auth::user()->role == 'guru') + Bebas + Denda + @else + Terlambat + @endif + @else + Dipinjam + @endif + + +
    +
    +
    +
    + + {{-- MODAL DETAIL --}} + + + @push('scripts') + + @endpush +
    diff --git a/resources/views/riwayat/online.blade.php b/resources/views/riwayat/online.blade.php new file mode 100644 index 0000000..6f1efab --- /dev/null +++ b/resources/views/riwayat/online.blade.php @@ -0,0 +1,145 @@ +@section('page-title', $pageTitle) + +
    +
    +
    {{ $pageTitle }}
    +
    +
    +
    + + + + + + + + + + + + + @php $counter = 1; @endphp + @forelse ($riwayatOnline as $transaksi) + @foreach ($transaksi['books'] as $buku) + + + + + + + + + @endforeach + @empty + + + + @endforelse + +
    NOID BACAJUDUL BUKUTANGGAL AKSESSTATUSAKSI
    {{ $counter++ }}{{ $transaksi['id_baca'] }}{{ $buku['judul'] }}{{ $transaksi['tanggal_akses'] }} + {{ $transaksi['status'] }} + + +
    Tidak ada riwayat baca buku online.
    +
    +
    +
    + + {{-- MODAL DETAIL RIWAYAT --}} + + + + @push('scripts') + + + + @endpush +
    \ No newline at end of file diff --git a/resources/views/welcome.blade.php b/resources/views/welcome.blade.php new file mode 100644 index 0000000..b866bd5 --- /dev/null +++ b/resources/views/welcome.blade.php @@ -0,0 +1,411 @@ + + + + + + + Selamat Datang di {{ config('app.name', 'Perpus Digital') }} + + + @vite(['resources/scss/app.scss', 'resources/js/app.js']) + + + + + @php + // Dummy data untuk landing page (Hanya contoh) + $buku_unggulan = \App\Services\DummyDataService::getAllBooks()->take(6); + $stats = [ + ['label' => 'Koleksi Buku', 'value' => 12500, 'icon' => 'bi-bookshelf'], + ['label' => 'Pengguna Aktif', 'value' => 4500, 'icon' => 'bi-person-lines-fill'], + ['label' => 'Total Dibaca', 'value' => '900K+', 'icon' => 'bi-hand-thumbs-up-fill'], + ['label' => 'Tahun Berdiri', 'value' => 2018, 'icon' => 'bi-clock-fill'], + ]; + @endphp + + {{-- Navbar --}} + + +
    + + {{-- Hero Section --}} +
    +
    +
    +
    +
    + Perpustakaan Digital +
    +

    Jelajahi Ribuan Buku Digital di Satu Tempat

    +

    + Gerbang menuju dunia pengetahuan tanpa batas. Akses ribuan koleksi buku digital, kapan saja, + di mana saja, dan tingkatkan minat baca Anda. +

    + + + +
    +
    +
    + Hero Illustration +
    +
    +
    +
    +
    + +
    + + {{-- Koleksi Section --}} +
    +
    +

    Koleksi Unggulan Terbaru

    +
    + @foreach ($buku_unggulan as $buku) +
    +
    + Cover {{ $buku['judul'] }} +
    + {{ $buku['kategori'] + }} +
    {{ $buku['judul'] }}
    +

    {{ $buku['penulis'] }}

    +
    + + (4.5) +
    +
    +
    +
    + @endforeach +
    +
    +
    + +
    + + {{-- Fitur Section --}} +
    +
    +
    + + Keunggulan Kami + +

    Manfaat Menggunakan DIGIPUS.GO

    +

    Akses mudah, koleksi lengkap, pengalaman membaca yang lebih baik.

    +
    + +
    +
    +
    +
    + +
    +
    Akses Online & Offline
    +

    Baca kapan saja. Unduh buku untuk dibaca tanpa koneksi internet. +

    +
    +
    +
    +
    +
    + +
    +
    Peminjaman Digital Otomatis
    +

    Proses pinjam dan kembali tercatat otomatis, bebas antri.

    +
    +
    +
    +
    +
    + +
    +
    Rekomendasi Personal
    +

    Temukan buku baru berdasarkan minat dan riwayat baca Anda.

    +
    +
    +
    +
    +
    + +
    +
    Akses 24/7 Responsif
    +

    Tersedia 24 jam sehari, 7 hari seminggu, di semua perangkat.

    +
    +
    +
    +
    +
    + +
    +
    Tandai & Simpan
    +

    Buat koleksi pribadi, tandai halaman penting, dan lanjutkan + bacaan Anda.

    +
    +
    +
    +
    +
    + +
    +
    Konten Selalu Baru
    +

    Ribuan buku dan modul pembelajaran terbaru ditambahkan setiap + bulan.

    +
    +
    +
    +
    +
    + +
    + + {{-- About Section --}} +
    +
    +
    + + {{-- Bagian Logo (Kolom Kanan) --}} +
    + Logo SMPN 1 Bagor +
    + + {{-- Bagian Teks (Kolom Kiri) --}} +
    + + Tentang Kami + +

    Misi Kami: Mencerdaskan Bangsa Melalui Akses Digital

    +

    + DIGIPUS.GO adalah platform perpustakaan digital resmi + milik + SMPN 1 Bagor. + Kami bertujuan menyediakan akses mudah, cepat, dan merata terhadap sumber daya + pengetahuan berkualitas tinggi bagi seluruh siswa dan staf pengajar. +

    +
      +
    • Mewujudkan + ekosistem literasi digital yang inklusif.
    • +
    • Mendukung + proses pembelajaran berbasis teknologi.
    • +
    • Menjadikan + membaca sebagai kebiasaan sehari-hari.
    • +
    +
    + +
    +
    +
    + +
    + + {{-- Statistik Section --}} +
    +
    +

    DIGIPUS.GO Dalam Angka

    +
    + @foreach ($stats as $stat) +
    +
    + +

    {{ $stat['value'] }}

    +

    {{ $stat['label'] }}

    +
    +
    + @endforeach +
    +
    +
    + +
    + + {{-- CTA Section --}} +
    +
    +
    +

    Siap Memulai Petualangan Membaca Anda?

    +

    Baca sekarang dan akses ribuan koleksi buku digital gratis!

    + +
    +
    +
    + +
    + + {{-- Footer Section --}} +
    +
    +
    +
    +
    + +
    DIGIPUS.GO
    +
    +

    Gerbang digital untuk seluruh koleksi buku pendidikan dan umum. + Dikelola oleh [Nama Institusi/Sekolah Anda].

    +
    + + + +
    +
    + +
    +
    Link Cepat
    + +
    + +
    +
    Informasi Hukum
    + +
    + +
    +
    Hubungi Kami
    +
      +
    • smpn1bagor@yahoo.co.id +
    • +
    • (+62) 856-0642-8357
    • +
    • Banaran Kulon, Kec. Bagor, Kabupaten Nganjuk, Jawa Timur 64461 +
    • +
    +
    +
    + +
    +
    + © {{ date('Y') }} DIGIPUS.GO. Hak Cipta Dilindungi. +
    +
    +
    + + + + + \ No newline at end of file diff --git a/routes/auth.php b/routes/auth.php new file mode 100644 index 0000000..a0c6418 --- /dev/null +++ b/routes/auth.php @@ -0,0 +1,59 @@ +group(function () { + // Route::get('register', [RegisteredUserController::class, 'create']) + // ->name('register'); + + // Route::post('register', [RegisteredUserController::class, 'store']); + + Route::get('login', [AuthenticatedSessionController::class, 'create']) + ->name('login'); + + Route::post('login', [AuthenticatedSessionController::class, 'store']); + + Route::get('forgot-password', [PasswordResetLinkController::class, 'create']) + ->name('password.request'); + + Route::post('forgot-password', [PasswordResetLinkController::class, 'store']) + ->name('password.email'); + + Route::get('reset-password/{token}', [NewPasswordController::class, 'create']) + ->name('password.reset'); + + Route::post('reset-password', [NewPasswordController::class, 'store']) + ->name('password.store'); +}); + +Route::middleware('auth')->group(function () { + Route::get('verify-email', EmailVerificationPromptController::class) + ->name('verification.notice'); + + Route::get('verify-email/{id}/{hash}', VerifyEmailController::class) + ->middleware(['signed', 'throttle:6,1']) + ->name('verification.verify'); + + Route::post('email/verification-notification', [EmailVerificationNotificationController::class, 'store']) + ->middleware('throttle:6,1') + ->name('verification.send'); + + Route::get('confirm-password', [ConfirmablePasswordController::class, 'show']) + ->name('password.confirm'); + + Route::post('confirm-password', [ConfirmablePasswordController::class, 'store']); + + Route::put('password', [PasswordController::class, 'update'])->name('password.update'); + + Route::post('logout', [AuthenticatedSessionController::class, 'destroy']) + ->name('logout'); +}); diff --git a/routes/console.php b/routes/console.php new file mode 100644 index 0000000..3c9adf1 --- /dev/null +++ b/routes/console.php @@ -0,0 +1,8 @@ +comment(Inspiring::quote()); +})->purpose('Display an inspiring quote'); diff --git a/routes/web.php b/routes/web.php new file mode 100644 index 0000000..f9ec0da --- /dev/null +++ b/routes/web.php @@ -0,0 +1,129 @@ +group(function () { + + // Rute Umum untuk Siswa & Guru + Route::get('/dashboard', [DashboardController::class, 'index'])->name('dashboard'); + Route::get('/katalog', [KatalogController::class, 'index'])->name('katalog.index'); + Route::get('/rekomendasi/{id}', [RekomendasiController::class, 'show'])->name('rekomendasi.show'); + + Route::prefix('peminjaman-offline')->name('peminjaman.')->group(function () { + Route::get('/', [PeminjamanController::class, 'index'])->name('index'); + Route::get('/{id}/ringkasan', [PeminjamanController::class, 'ringkasan'])->name('ringkasan'); + Route::get('/{id}/form', [PeminjamanController::class, 'form'])->name('form'); + Route::post('/store', [PeminjamanController::class, 'store'])->name('store'); + }); + + Route::prefix('baca-online')->name('baca.')->group(function () { + Route::get('/', [BacaOnlineController::class, 'index'])->name('index'); + Route::get('/{id}/ringkasan', [BacaOnlineController::class, 'ringkasan'])->name('ringkasan'); + Route::get('/{id}/request', [BacaOnlineController::class, 'showCodeRequestPage'])->name('request_code'); + Route::post('/{id}/verify', [BacaOnlineController::class, 'verifyCode'])->name('verify_code'); + Route::get('/{id}/view', [BacaOnlineController::class, 'viewBook'])->name('view_book'); + Route::get('/secure-pdf/{id}', [BacaOnlineController::class, 'streamPdf'])->name('stream_pdf'); + }); + + Route::prefix('riwayat')->name('riwayat.')->group(function () { + Route::get('/offline', [RiwayatController::class, 'offlineIndex'])->name('offline'); + Route::get('/online', [RiwayatController::class, 'onlineIndex'])->name('online'); + }); + + Route::prefix('profile')->name('profile.')->group(function () { + Route::get('/', [ProfileController::class, 'index'])->name('index'); + Route::get('/edit', [ProfileController::class, 'edit'])->name('edit'); + Route::patch('/', [ProfileController::class, 'update'])->name('update'); + Route::delete('/', [ProfileController::class, 'destroy'])->name('destroy'); + }); + + // --- GRUP RUTE KHUSUS UNTUK GURU --- + Route::middleware(['role:guru'])->prefix('guru')->name('guru.')->group(function () { + Route::get('/laporan-minat-baca', [LaporanController::class, 'index'])->name('laporan.index'); + }); +}); + +// --- GRUP RUTE KHUSUS UNTUK ADMIN / PENJAGA PERPUSTAKAAN --- +Route::middleware(['auth', 'role:penjaga perpus'])->prefix('admin')->name('admin.')->group(function () { + Route::get('/dashboard', [AdminDashboardController::class, 'index'])->name('dashboard'); + + Route::get('/buku', [AdminBookController::class, 'index'])->name('buku.index'); + Route::get('/buku/tambah', [AdminBookController::class, 'create'])->name('buku.create'); + Route::get('/buku/{id}/edit', [AdminBookController::class, 'edit'])->name('buku.edit'); + + Route::get('/pengguna', [AdminUserController::class, 'index'])->name('pengguna.index'); + Route::get('/pengguna/tambah', [AdminUserController::class, 'create'])->name('pengguna.create'); + Route::post('/pengguna', [AdminUserController::class, 'store'])->name('pengguna.store'); + Route::get('/pengguna/{id}/edit', [AdminUserController::class, 'edit'])->name('pengguna.edit'); + Route::patch('/pengguna/{id}', [AdminUserController::class, 'update'])->name('pengguna.update'); + Route::delete('/pengguna/{id}', [AdminUserController::class, 'destroy'])->name('pengguna.destroy'); + + Route::get('/pengumuman', [AdminPengumumanController::class, 'index'])->name('pengumuman.index'); + Route::get('/pengumuman/tambah', [AdminPengumumanController::class, 'create'])->name('pengumuman.create'); + Route::get('/pengumuman/{id}/edit', [AdminPengumumanController::class, 'edit'])->name('pengumuman.edit'); + + Route::get('/rekomendasi', [ + AdminRekomendasiController + ::class, + 'index' + ])->name('rekomendasi.index'); + Route::get('/rekomendasi/tambah', [AdminRekomendasiController::class, 'create'])->name('rekomendasi.create'); + Route::get('/rekomendasi/{id}/edit', [AdminRekomendasiController::class, 'edit'])->name('rekomendasi.edit'); + + Route::get('/peminjaman', [AdminPeminjamanController::class, 'index'])->name('peminjaman.index'); + Route::get('/peminjaman/tambah', [AdminPeminjamanController::class, 'create'])->name('peminjaman.create'); + + Route::get('/denda', [AdminPeminjamanController::class, 'dendaIndex'])->name('denda.index'); + Route::post('/denda/sanksi', [AdminPeminjamanController::class, 'berikanSanksi'])->name('denda.sanksi'); + + Route::post('/master-induk', [MasterIndukController::class, 'store'])->name('master-induk.store'); + Route::delete('/master-induk/{id}', [MasterIndukController::class, 'destroy'])->name('master-induk.destroy'); +}); + +// --- RUTE LOGIN KHUSUS ADMIN --- +Route::middleware('guest')->group(function () { + Route::get('/admin/login', [AdminLoginController::class, 'create'])->name('admin.login'); + Route::post('/admin/login', [AdminLoginController::class, 'store'])->name('admin.login.store'); +}); + +// -- RUTE RESET PASSWORD -- +Route::get('/reset-password', function () { + return view('auth.reset-password-request'); +})->name('reset.password-request'); + +require __DIR__ . '/auth.php'; \ No newline at end of file diff --git a/storage/app/books/.gitkeep b/storage/app/books/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/storage/app/books/ayah.pdf b/storage/app/books/ayah.pdf new file mode 100644 index 0000000..36b0f7d --- /dev/null +++ b/storage/app/books/ayah.pdf @@ -0,0 +1,10918 @@ + https://pustaka-indo.blogspot.co.id/ + + Hak cipta dilindungi undang-undang. + Dilarang mengutip atau memperbanyak sebagian +atau seluruh isi buku ini tanpa izin tertulis dari penerbit. + Andrea Hirata + +https://pustaka-indo.blogspot.co.id/ + AYAH +Andrea Hirata + +Cetakan Pertama, Mei 2015 + +Penyunting: Imam Risdiyanto +Perancang sampul: Andreas Kusumahadi +Pemeriksa aksara: Intan & Fitriana +Penata aksara: Martin Buczer & Tri Raharjo +Digitalisasi: Rahmat Tsani H. + +Diterbitkan oleh Penerbit Bentang +(PT Bentang Pustaka) +Anggota Ikapi +Jln. Plemburan No. 1, Pogung Lor, RT 11, RW 48 +SIA XV, Sleman, Yogyakarta – 55284 +Telp.: 0274 – 889248 +Faks: 0274 – 883753 +Surel: bentang.pustaka@mizan.com +Surel redaksi: bentangpustaka@yahoo.com +http://bentang.mizan.com +http://www.bentangpustaka.com + +Perpustakaan Nasional: Katalog Dalam Terbitan (KDT) +Andrea Hirata + + Ayah/Andrea Hirata; penyunting, Imam Risdiyanto.—Yogyakarta: +Bentang, 2015. + +xx + 412 hlm.; 20,5 cm. + +ISBN 978-602-291-102-9 + +1. Fiksi Indonesia. I. Judul. II. Imam Risdiyanto. + + 899.221 3 + +E-book ini didistribusikan oleh: +Mizan Digital Publishing +Jl. Jagakarsa Raya No. 40 +Jakarta Selatan - 12620 +Phone.: +62-21-7864547 (Hunting) +Fax.: +62-21-7864272 +email: mizandigitalpublishing@mizan.com + +https://pustaka-indo.blogspot.co.id/ + Teriring terima kasih untuk guruku + James Alan McPherson + +https://pustaka-indo.blogspot.co.id/ + Seperti +dikisahkan Amiru + + kepadaku + Daftar Isi + +Purnama Kedua Belas ~ 1 +Radio ~ 5 +Pensil ~ 9 +Pingsan ~ 14 +Seorang Ayah Bernama Markoni ~ 17 +Volare ~ 22 +Masih Berlaku ~ 26 +Bunga Ilalang ~ 30 +SMA ~ 35 +Izmi ~ 39 +Intervensi ~ 45 +Surat ~ 48 +Barang Antik ~ 51 +Perlambang ~ 54 +Enam ~ 59 +Merayu Awan ~ 61 +Sayap Kecil yang Sempat Tumbuh dan Patah Lagi ~ 66 +Semua Kebaikan dari Saputangan ~ 73 +Rahasia ~ 79 + Geometri ~ 83 +Amiru dan Sepedanya ~ 86 +Terima Kasih ~ 94 +Cita-Cita Izmi dan Amiru ~ 105 +Pahlawan ~ 107 +Tanjong Pandang ~ 111 +Puisi ~ 123 +Amiru dan Kantor Gadai ~ 129 +Saat Langit Menjadi Biru ~ 135 +Pendamba Cinta ~ 139 +Wawancara ~ 144 +Kue Satu ~ 148 +Biru Karena Rindu ~ 152 +Medali Keemasan ~ 158 +Konfigurasi ~ 166 +Stadium 3 ~ 171 +Juru Puisi ~ 174 +Ayah yang Bersembunyi ~ 178 +Aya ~ 187 +Semua Telah Membeku di dalam Waktu ~ 193 +Ruang Sidang III ~ 207 +Menyukai Travelling ~ 214 +Rabun ~ 218 +37 Syarat ~ 231 +Satire Akhir Tahun ~ 237 + Surat-Surat Lena ~ 240 +“Besame Mucho” ~ 247 +Kisah Keluarga Langit ~ 253 +Sketsa ~ 261 +Kota yang Pandai Berpuisi ~ 266 +Delapan Tahun Kegilaan ~ 280 +Genap ~ 286 +Bahasa Indonesia ~ 290 +Kapal Ternak ~ 298 +Juliet-mu ~ 301 +Ilmu Bumi ~ 306 +Indonesia Lonely Man ~ 314 +Sahabat Pena dan Hikayat 6 Kota ~ 317 +Stolen Generation ~ 328 +Musibah ~ 336 +25 Km/Jam ~ 342 +Api Neraka ~ 346 +Piala ~ 351 +Merdeka ~ 360 +Biru ~ 376 +Janji Lama ~ 383 +Sweet ~ 387 +Purnama Kedua Belas ~ 392 + Purnama +Kedua Belas + +MALAM senyap, tak ada suara kecuali bunyi kafilah-kafilah +angin berembus dari selatan, menampar-nampar atap rum- +bia, menyelisik daun delima, menjatuhkan buah kenari, me- +nepis permukaan Danau Merantik, menyapu padang, lalu +terlontar jauh, jauh ke utara. Sesekali burung-burung pipit +yang tidur di gulma terbangun, bercuit-cuit berebut tempat +tidur, lalu senyap lagi. + + Meski tersembul di antara gumpal awan April, purnama +kedua belas terang benderang. Begitu terang sehingga Sabari +yang duduk sendiri di beranda, sedih, kesepian, dan merana, +dapat melihat gurat nasib di telapak tangan kirinya. Tangan +kanannya erat menggenggam pensil. + + Tak ada yang dapat dipahaminya, telapak tangannya +adalah anak-anak sungai yang tak tentu mana hulu mana hi- +lirnya. Sabari terombang-ambing di riaknya, timbul, tengge- + 2 ~ Andrea Hirata + +lam. Dibekapnya pensil itu, bunga-bunga ilalang beterbangan +dalam dadanya. + + Seekor kucing berbulu hitam, tetapi telah berubah men- +jadi abu-abu, karena suka tidur di tungku, melompat ke pang- +kuannya. Kucing yang telah berjanji pada dirinya sendiri, un- +tuk ikut Sabari sampai ajal menjemput, juga merana. Biduk +rumah tangganya, persis rumah tangga Sabari, telah karam. +Marleni, istrinya, telah minggat, direbut kucing garong dari +pasar pagi Tanjong Pandan yang tak tahu adat. + + Bentuk rumah Sabari pun macam orang kesepian, bong- +kok, mau tumpah, kurang percaya diri. Sebatang pohon deli- +ma di pojok kanan pekarangan ikut-ikutan kesepian. Mereka, +termasuk pohon delima itu, rindu kepada Marlena, Marleni, +dan terutama, Zorro. + + Abu Meong, nama kucing tadi, meloncat dari pangku- +an juragannya lalu melangkah menuju dapur dengan gaya +seperti orang habis melemparkan bola boling. Penuh gaya, +tetapi palsu. Selain patah hati, kucing dapur itu juga mende- +rita tekanan batin, post power syndrome istilah masa kini, sejak +tikus-tikus di rumah itu minggat. Tetangga kiri-kanan bilang, +tikus-tikus itu tak tahan karena Sabari selalu muram, tak ceria +seperti dulu. Buncai, tukang kredit alat-alat rumah tangga, +malah menyebarkan gosip tak sedap. Katanya, tikus-tikus itu +terjun ke dalam sumur, mengakhiri hidup mereka, lantaran +tak sanggup kelaparan sebab Sabari begitu miskin. Ting- +gallah Abu Meong yang baru sadar bahwa kaum tikus yang + Ayah ~ 3 + +kerap mengalami perlakuan represif darinya adalah sumber +wibawa, sekaligus kebahagiaannya, satu-satunya. + + Marlena, oh, Marlena, perempuan yang telah membuat +Sabari senewen karena kasmaran. Cinta pertamanya, belah- +an jiwanya, segala-galanya. Sayang seribu sayang, tak sedikit +pun Lena mengacuhkannya. Gambar-gambar hitam putih, +karena sudah lama tentu saja, silih berganti melayang dalam +kepala lelaki lugu yang melankolis itu. Gambar waktu Sabari +mengambil saputangan Lena yang jatuh di lapangan upacara. + + “Siapa yang menyuruhmu mengambilnya?! Siapa?! Aku +bisa mengambilnya sendiri!” Padahal, Sabari menyerahkan- +nya tak kurang khidmat dari cara Paskibra Kabupaten me- +nyerahkan bendera. + + “Buku tulis untukmu, Lena,” kata Sabari selembut +mungkin, malu dan gugup. Buku itu adalah hadiah harap- +an tiga lomba menulis puisi tingkat pelajar, prestasi tertinggi +Sabari. Dia ingin Lena bangga kepadanya. Tak usah ya, kata +Lena. + + Maka, Sabari gelisah, lalu kecewa, lalu menderita. Ten- +tu kemudian khalayak ramai tak habis pikir melihat seorang +lelaki hanya terpaku pada satu perempuan, tak dapat dibelok- +belokkan ke perempuan lain, seolah dunia ini hanya selebar +saputangan Lena. + + Kawan dekat Sabari, yakni Maulana Hasan Magribi— +lahir saat azan Maghrib—biasa dipanggil Ukun dan Mus- +tamat Kalimat, biasa dipanggil Tamat, berkali-kali mengi- + 4 ~ Andrea Hirata + +ngatkan Sabari bahwa dia bisa berakhir di Panti Rehabilitasi +Gangguan Jiwa Amanah di bawah pimpinan Dra. Ida Nurai- +ni, apabila kepalanya yang ditumbuhi rambut keriting ber- +gumpal-gumpal itu hanya dipenuhi bayangan Lena. Sabari +bergidik. Dia pun sering mengingatkan dirinya sendiri akan +hal itu. + Radio + +SEPANJANG pengetahuan Amiru, ayahnya, Amirza, tak +pernah ke warung kopi seperti kebanyakan lelaki di Kampung +Nira. Meski belum bolehlah dikatakan panjang pengetahuan- +nya sebab dia cuma bocah lelaki berusia sepuluh tahun, kelas +lima SD. + + Amirza bekerja sebagai buruh pabrik sandal jepit bermu- +tu. Malam dilewatkannya dengan menjalin pukat di bawah +temaram lampu minyak sambil menyimak siaran radio. Istri, +tiga anak, pabrik sandal jepit, menjual pukat, dan radio. Da- +lam lingkaran itulah hidup Amirza berputar, hari demi hari, +tahun demi tahun, tak ada hal lain. + + Bahasa yang asing dan irama yang aneh dari negeri- +negeri yang jauh kemerosok, timbul tenggelam, menguing +dari radio kuno yang tutup belakangnya tak tahu sudah +minggat ke mana, sehingga tampak rangkaian kabel berke- +lak-kelok semau-maunya di antara tabung-tabung berdebu, + 6 ~ Andrea Hirata + +lalu secara ajaib mengeluarkan bunyi, bahkan musik, bahkan +orang berkata-kata! + + Di atas tombol fine tuning ada tulisan PHIL dari bahan +berkilau. Lalu, ada jejak tulisan LIP di sampingnya, menan- +dakan radio itu telah mengalami masa-masa yang jaya se- +kaligus perjuangan yang sulit. Ujung antenanya dililit kawat +kuningan yang diulur menuju belakang rumah lalu ditautkan +ke kawat kandang bebek. Tentu dimaksudkan agar dapat me- +nerima siaran radio lebih jelas. Bagaimana kandang bebek +bisa menjadi perpanjangan antena radio adalah bagian dari +petualangan epik Amirza bersama radionya, yang di dalam- +nya melibatkan seorang lelaki Melayu amatir bernama Syarif +Miskin. + + Seandainya mau disebut sebagai teknologi, radio itu +adalah teknologi pertama dan satu-satunya di rumah itu, +yang bahkan tak berlistrik. Jika mau disebut hiburan, radio itu +pula satu-satunya hiburan bagi Amirza sekeluarga. Jika ingin +disebut harta, radio itu pula harta paling berharga di rumah +itu. Dan, jika ingin disebut sebagai budaya, Amirza adalah +penganut budaya radio yang setia. + + Radio itu diletakkan dengan penuh hormat di atas le- +mari rendah berkaca. Harap maklum, segala sesuatu yang +terbuat dari kaca dianggap mewah di Kampung Nira. Mes- +ki rupanya kaca lemari itu hanya plastik serupa kaca. Lokasi +radio pun dipilih dengan teliti, di pojok ruang tengah, agar +terhindar dari guyuran hujan lantaran atap seng yang bocor. + Ayah ~ 7 + +Taplak bermotif Melayu tradisional dirajut khusus oleh istri +Amirza untuk alas radio itu. Di sebelah radio dipajang vas bu- +nga plastik berisi lima tangkai bunga mawar, juga dari plastik. +Melihat dekorasi itu pasti Mister Phillip sendiri akan terharu. + + Setiap malam Amirza duduk di kursi rotan di samping +radio itu. Disampirkannya ujung pukat pada paku yang ter- +tancap di dinding, dinyalakannya lampu minyak, dihidupkan- +nya radio. + + Setelah bercerita untuk mengantar tidur dua adik perem- +puannya, Amirta, usia lima tahun dan Amirna, usia tiga ta- +hun, dari kamar sebelah, melalui celah dinding papan, Amiru +sering mengintip ayahnya. Senang dia melihat ayahnya terse- +nyum mendengar lagu-lagu yang indah. Tak ada yang lebih +diinginkan Amiru selain melihat ayahnya tersenyum. + + Acara kesenangan ayahnya adalah ceramah agama Is- +lam, sandiwara radio, lagu-lagu Semenanjung, dan tak lupa, +berita tentang Lady Diana. Entah bagaimana mulanya, pen- +duduk Kampung Nira gemar sekali kepada Lady Diana. Tak +peduli tua, muda, wanita maupun pria. Kegemaran itu tak lu- +put menghinggapi ayah Amiru. Jika RRI atau radio lokal me- +nyinggung sedikit saja nama Lady Diana, lekas-lekas Amirza +membesarkan volume radio. + + Lady Diana adalah kembang dunia yang selalu membesarkan hati +orang miskin, kata mereka. Jika ada berita Lady Diana mengun- +jungi kampung miskin nun di belahan dunia antah-berantah, +mereka mendekatkan telinga ke radio atau berkerumun di + 8 ~ Andrea Hirata + +depan televisi umum, Sanyo hitam putih, empat belas inci, +di pekarangan balai kampung. Lady Diana muncul di layar, +mereka berdiri dan mendekati TV karena mau melihat Lady +Diana dari dekat. + + Keesokannya tak ada topik bicara lain di sekolah, kan- +tor desa, pasar, warung-warung kopi, selain soal Lady Diana. +Mereka yang tak sempat melihatnya, menyesal, membanting +topi ke meja. + + “Rugilah kau!” kata kawan-kawannya. + Pembicaraan itu baru reda setelah berhari-hari. Orang- +orang Nira berharap suatu hari Lady Diana bersedia me- +ngunjungi kampung mereka yang miskin. Ada yang bermak- +sud mengirim surat kepada presiden agar mengundang Lady +Diana ke Indonesia. Setelah mengunjungi Istana Negara, +barangkali Lady Diana berminat bertandang ke Kampung +Nira. + Pensil + +PERTANYAANNYA sekarang, bagaimana mulanya sehingga +Sabari tergila-gila kepada Lena? + + Dulu dia tak ubahnya anak-anak lain di Belantik, kam- +pung paling ujung, di pinggir laut Belitong sebelah timur. +Pulang sekolah dia langsung mengalungkan katapel, me­ +ngantongi duku muda untuk pelurunya, bersandal cunghai, +melempari buah sagu, mengejar layangan, berlari-lari di pa- +dang, dan berenang di danau galian tambang. Kulit kelam +terbakar matahari, luka-luka seantero kaki, pulang ke rumah +dimarahi Ibu demi melihat baju penuh bercak getah buah hu- +tan, lalu pontang-panting berlari ke masjid agar tak terlambat +dan dimarahi guru mengaji. Di masjid tertawa, bersorak, be- +rebut, bertengkar, menangis. + + Soal cinta? Sabari tak kenal dan tak suka. Cinta adalah +kata yang asing. Cinta adalah racun manis penuh tipu mus- +lihat. Cinta adalah burung merpati dalam topi pesulap. Cin- + 10 ~ Andrea Hirata + +ta adalah tempat yang jauh, sangat jauh, dan urusan konyol +orang dewasa. + + Waktu kelas dua SMP, Ukun berkata kepada Sabari +bahwa dia suka sama Hanifa, sampai tak bisa tidur dibuat- +nya. Sebelumnya, Ukun juga pernah bilang bahwa dia suka +sama Sita, Mawar, Anisa, Laila, Nurmala, Aini, Indra, Deli, +Lili, Mumun, Nizam, Latifah, Salamah, Fatimah, Hasanah, +Sasha, Zasa, Zaza, dan Shasya. Adapun Tamat, tanpa malu- +malu bilang bahwa dia suka sama Amoi, Zarina, A Yun, Mi- +nar, A Mung, Nuri, Rifa, Umi kampung seberang, dan Umi +anak Pak RT. + + “Tapi, hanya suka pandang,” kata Tamat. + “Maksudmu?” tanya Sabari. + “Kata ayahku, aku tak boleh pacaran sebelum tamat +perguruan tinggi. Itulah sebabnya ayahku menamaiku Ta- +mat.” Padahal, ayahnya sendiri punya tiga istri. Lempar batu +sembunyi tangan. + Menurut Sabari semua itu menjijikkan. Setiap kali Ukun +berkoar soal putri-putri kecil yang disukainya itu, Sabari +­ngomel-ngomel. Sangat mungkin karena dia telah melihat +dengan matanya sendiri betapa buruknya cinta. Keluarga se- +pupu-sepupunya berantakan. Dia selalu bertanya, mengapa +tak ada hukum yang menjerat orang-orang yang suka main- +main dengan cinta macam Ukun, Tamat, dan sepupu-sepu- +punya itu? Baginya cinta adalah perbuatan buruk yang dilin- +dungi hukum. + Ayah ~ 11 + + Karena tahu Sabari anti cinta, pernah Ukun menggo- +danya dengan memasang-masangkannya dengan Shasya. +Sabari muntab tak keruan. Tiga hari Ukun didiamkannya. Sa- +bari yang penyabar, tak pernah begitu sebelumnya. Ukun se- +lalu menggoda Sabari dengan berbagai tingkah, tetapi kapok +menggodanya soal anak perempuan. + + Alkisah, tamatlah Sabari, Ukun, dan Tamat dari SMP. +Impian mereka berikutnya sama dengan impian lulusan SMP +lainnya, yaitu masuk SMA negeri. Demikian banyak lulusan +SMP dari berbagai SMP di puluhan kecamatan, tetapi bang- +ku SMA terbatas. Maka, diadakan ujian seleksi selama tiga +hari, bertempat di Markas Pertemuan Buruh (MPB). + + Hari terakhir adalah ujian Bahasa Indonesia. Sabari ter- +senyum simpul. Dijawabnya semua soal dengan tenang. Cin- +cai. Dilihatnya nun di sana, Ukun mengaduk-aduk rambut. +Sabari tersenyum lagi. Di arah pukul 5.00, Tamat tercenung, +tampak tertekan batinnya. Sabari kembali tersenyum. Maaf, +siswa lain bolehlah jago Matematika, IPA, Bahasa Inggris, +Geografi, Biologi, tetapi Sabari adalah Isaac Newton-nya Ba- +hasa Indonesia. + + Dalam waktu singkat, Sabari telah menjawab semua +soal, tetapi dia tak ingin mengecewakan pihak-pihak yang te- +lah memberinya nama Sabari, yakni ayahnya dan diaminkan +neneknya. Ditunggunya dengan sabar sampai waktu mau ha- +bis. Jika menyerahkan jawaban secara mendadak, peserta lain +bisa terintimidasi, lalu grogi, pecah konsentrasi lalu berantak- +an. Betapa tampan budi pekerti anak itu. + 12 ~ Andrea Hirata + + Akhirnya, waktu hampir habis. Sabari membereskan +tasnya dan bersiap-siap menyerahkan kertas jawaban kepada +pengawas di depan sana, tetapi mendadak dia terperanjat ka- +rena sekonyong-konyong seorang anak perempuan menikung +di depannya, merampas kertas jawabannya, duduk di sam- +pingnya, dan tanpa ba bi bu langsung menyontek jawabannya. + + Tangkas sekali anak itu memindahkan semua jawaban +Sabari ke kertas jawabannya sendiri. Wajahnya tegang, na- +pasnya memburu, keringat bertimbulan di dahinya. Sabari +terpaku. Posisi pengawas yang jauh di depan membuat anak +itu bebas melakukan pelanggaran. Semuanya berlangsung +dengan sangat cepat. Yang diketahui Sabari kemudian ada- +lah teriakan dari pengawas bahwa waktu telah habis, harap +kertas jawaban diserahkan, jika tidak, pengawas akan menda- +tangi peserta dan mengambilnya secara paksa. + + Usai menyalin semua jawaban, anak perempuan itu me- +nyerahkannya kembali kepada Sabari. Tahu-tahu pengawas +telah berdiri di depan mereka dan mengambil kertas jawaban +sambil ngomel-ngomel. + + Anak perempuan itu membereskan tasnya. Sabari ter- +pana melihat bunga-bunga ilalang dalam tasnya. Tanpa ber- +kata-kata, anak itu tersenyum kepada Sabari dan menyerah- +kan pensilnya. Mungkin semacam hadiah untuk kebaikan +Sabari. + + Sabari menerima pensil dengan tangan yang dirasakan- +nya tak lagi merupakan bagian dari tubuhnya. Dia tertegun + Ayah ~ 13 + +karena tak pernah melihat mata manusia seindah mata anak +perempuan itu. Begitu indah, teduh tetapi berkilau, bak pur- +nama kedua belas. + + Anak itu bangkit, melangkah pergi, meninggalkan Sa- +bari yang gemetar sehingga bangku tempat duduknya berge- +meletuk. + + Usai ujian itu, sepanjang sore dan malam, Sabari te- +rus menggenggam pensil pemberian anak perempuan yang +tak dikenalnya itu. Tak pernah sedetik pun melepaskannya. +Ke­esokannya dia terbangun, pensil itu masih berada dalam +genggamannya. + Pingsan + +AMIRU senang melihat ayahnya bereksperimen dengan ra- +dio. Karena dengan begitu, kata hatinya, pikiran ayahnya, +juga pikirannya sendiri, akan teralihkan dari kesedihan. Kese- +dihan karena ibu Amiru sering jatuh sakit. Ibunya bisa sehat +selama berminggu-minggu, tetapi jika penyakitnya kambuh, +dia tak bisa bangun dari tempat tidur. + + Amiru kagum akan rasa sayang, kesabaran, dan ketela- +tenan ayahnya merawat ibunya. Oleh karena itu, dia, selaku +anak tertua, juga selalu rajin merawat ibunya. Jika keadaan +mencemaskan, Amiru berbaring di samping ibunya, diciumi­ +nya tangan ibunya sambil berdoa agar ibunya lekas sembuh. +Sementara ayahnya terus berusaha mencari penyembuhan +untuk ibunya. + + Maka, jika ada satu hal yang dapat membuat ayahnya +senang, dapat melupakan sejenak kemalangan yang merun- + Ayah ~ 15 + +dung, Amiru akan berusaha untuk mendapatkannya, dan hal +itu adalah radio. + + Dalam kaitan-kaitan itu, secara aneh, Amiru selalu men- +dukung eksperimen ayahnya akan radio itu sekaligus selalu +berharap agar eksperimen itu gagal. Supaya ayahnya tetap +sibuk. + + Pernah, karena ingin mendengar siaran langsung per- +tandingan bulu tangkis Thomas Cup Indonesia versus Malay- +sia yang disiarkan RRI secara langsung, ayahnya meminjam +kuali ibunya. Diulurnya seutas kawat yang panjang dari ante- +na radio lalu ditautkannya ujung kawat itu pada telinga kua- +li yang dipasang di atap rumah. Maksudnya mungkin untuk +memfungsikan kuali itu sebagai semacam antena parabola. +Siaran radio tidak membaik. Eksperimen antena kuali: gagal. + + Tak kenal menyerah, Amirza mencoba berbagai cara su- +paya mendapat siaran radio yang lebih jelas. Dia memanjat +pohon gayam di samping rumah lalu mengikat sebatang besi +di puncaknya. Di ujung batang besi itu ditautkan kawat yang +telah diulur dari antena radio. Hasilnya siaran radio malah +makin kemerosok. + + Ayah Amiru penasaran. Dibalutnya ujung besi di pun- +cak pohon gayam itu dengan gulungan timah. Tindakan +itu mengikuti sebuah alur logika yang amat akademik, yaitu +sebagai kaum yang akrab dengan tambang, penduduk Nira +paham bahwa petir gemar sekali menyambar tanah yang me- +ngandung timah. Karena petir adalah listrik dan frekuensi ra- + 16 ~ Andrea Hirata + +dio juga salah satu bentuk penjelmaan listrik, frekuensi radio +pasti senang menyambar antena radio yang dilapisi timah. +Akibatnya, tidak bisa tidak, siaran radio pasti akan semakin +jelas. Begitu dasar pemikiran Amirza. Jika pemikiran itu di- +jadikan proposal skripsi mahasiswa tingkat akhir, pasti dosen +pembimbing akan mengangguk tanpa ragu. + + Yang terjadi adalah pada satu malam hujan lebat, ante- +na di puncak pohon gayam itu disambar petir. Akibatnya, bu- +kan hanya antena itu hangus menjadi arang, melainkan juga +pohon gayam layu sebelah. Ayah Amiru yang tengah khidmat +mendengarkan lagu “Green Green Grass of Home” terpelan- +ting dari tempat duduk. Radio itu mengerang sebentar, ber­ +asap-asap, lalu pingsan. + Seorang Ayah +Bernama Markoni + +AYAH yang keras, begitu semua anaknya menganggap Mar- +koni. Markoni sadar akan hal itu, tetapi tak dapat mengu- +bahnya. Sistem militan yang diterapkannya di rumah adalah +akibat dari penyesalan paling besar dalam hidupnya, yang tak +ada hari dilaluinya tanpa menyesalinya, yaitu tidak sempat +sekolah tinggi. + + Padahal, ayahnya dulu orang mampu, dan pernah me- +ngatakan sesuatu yang semakin menambah sesak dada Mar- +koni, bahwa kalau Markoni mau sekolah, ayahnya, Tuan +Razak, yang adalah seorang Syah Bandar, bersedia membia- +yai sekolahnya sampai mana pun. + + “Kalau perlu menggadaikan rumah.” Terngiang-ngiang +dalam telinga Markoni kalimat itu. + + Tuan Razak ingin sekali Markoni mengikuti jejaknya di +bidang maritim. Markoni dinamai begitu agar menjadi seo- +rang markonis kapal. + 18 ~ Andrea Hirata + + “Markonis adalah orang terpandang, perwira di kapal. +Atasan markonis satu-satunya hanya nakhoda,” ayahnya me- +nyemangati Markoni. + + Ayahnya berlapang hati, berbesar harapan, lantaran +tahu Markoni sesungguhnya sangat cerdas. Melihat anaknya, +Tuan Razak membayangkan Marchese Guglielmo Marconi, +ilmuwan jempolan keturunan Irlandia Italia, manusia perta- +ma yang mampu menyeberangkan pesan tanpa kabel melin- +tasi Samudra Atlantik. Tak terperi jasanya bagi keselamatan +kapal, bagi umat manusia. + + Tuan Razak mengimpikan orang-orang memanggil anak +sulungnya, Spark, satu panggilan keren untuk seorang radio +­officer, perwira radio, seperti panggilan keren Kep, untuk kapten +kapal. Untuk itu, Markoni mesti masuk Sekolah Perwira Ra- +dio Pelayaran di Tasikmalaya, aih, gagahnya. Namun, sayang +seribu sayang, Markoni memilih jalan hidup sebagai bedebah. + + Baru kelas satu SMP dia sudah merokok. Lengan baju +yang sudah pendek digulung tinggi-tinggi, mending kalau +lengan berotot. Potongan rambut bersurai panjang pada +bagian belakang. Mirip ekor burung bayan. Satu ciri anak +bergajul. Bolos sekolah adalah hobinya. Semua nilai yang +dijunjung para pelopor pendidikan Indonesia dikhianatinya +terang-terangan pada siang bolong. Tak tahu apa yang me- +rasukinya, orangtua selalu dimusuhinya, pelajaran disepele- +kan, guru-guru dilawan. Adalah satu keajaiban dia bisa tamat +STM, jurusan Listrik. + Ayah ~ 19 + + Memang sempat Markoni berangkat ke Tasikmalaya +dan masuk sekolah radio itu, tetapi kerjanya berleha-leha. + + “Cuma dua tahun, bersabarlah,” kata ayahnya agar +Markoni menamatkan sekolah D-2 itu. Namun, tak ada kesa- +baran dalam diri Markoni. Dia pulang ke Belitong, bukannya +membawa ijazah, dia membawa istri. + + Tak lama kemudian ayahnya meninggal dan mulai saat +itulah Markoni kena tampar kenyataan hidup yang sebenar- +nya. Menanggung istri dan anak, tanpa dukungan orangtua, +tanpa pekerjaan, tanpa pengalaman, tanpa ijazah memadai. +Air dingin di dalam gelas macam mendidih, begitu Markoni +menggambarkan krisis hidupnya kepada seorang kawan. + + Melamar kerja di sana sini ditolak. Usaha ini gagal, usa- +ha itu merosot. Memang ada lowongan kerja di kapal, perusa- +haan pelayaran atau lowongan di bagian mekanikal elektrikal +rumah sakit daerah, tetapi memerlukan ijazah paling tidak +sarjana muda. + + Harus menyokong keluarga, Markoni tak bisa dan tak +boleh menyerah. Dibukanya warung sembako, gulung tikar, +warung makan, habis modal, bengkel motor, lebih banyak +pengeluaran ketimbang pendapatan, kaki lima, kena uber +polisi pamong praja, warung sayur, macet, jual batu satam, +kena tipu, jual bakso, kalah saingan, jual minyak tanah, kena +kurung polisi, jual kupon judi buntut, takut sama api neraka. + + Usaha rental alat musiknya berakhir secara mengerikan +karena orang-orang udik dari Belantik, yang mau belajar mu- + 20 ~ Andrea Hirata + +sik rock, memperlakukan gitar seperti dayung, drum seperti +kasur yang boleh digebuk sekuat tulang, dan organ seperti +adonan kue satu. Senar bas sampai putus, bayangkan itu! Se- +nar bas sampai putus! Barangkali itu untuk kali pertama terja- +di dalam sejarah musik internasional. Usaha rental alat musik +yang berakhir tragis itu memengaruhi kepercayaan Marko- +ni terhadap musisi dan punya perasaan tersendiri terhadap +orang-orang Belantik. + + Terlilit utang pada rentenir dan harus berurusan dengan +orang-orang yang kasar, Markoni mati kutu dan mulailah +kata-kata ayahnya dulu menjelma menjadi hantu. + + Hatinya sakit melihat kawan-kawannya yang dulu me- +nyelesaikan sekolah di Tasikmalaya telah menjadi perwira ka- +pal. Muhtadin yang waktu STM tak bisa menjawab soal ujian +jika tidak diberinya sontekan, kini sudah menjadi Kepala Di- +nas Pendidikan. Tersayat hati Markoni. Kata orang, Markoni +selalu sial lantaran kualat sama ayahnya. Hukum karma pasti +berlaku. Di pusara ayahnya, Markoni minta maaf. + + Satu-satunya harapan tinggal Abu Dhabi. Dulu kawan- +nya penah menawarinya bekerja sebagai sopir truk di negeri +yang konon kalau musim panas orang bisa menggoreng telur +di jalan aspal. Markoni tak tahan panas karena hidupnya, ha- +tinya, telinganya, kepalanya sudah cukup panas. Suhu panas +membuatnya gelisah. Namun, dia sudah terpojok, tak punya +pilihan lain. + + Tercenung Markoni di warung kopi. Matanya kuyu me- +natap anak-anak yang berduyun-duyun pulang dari sekolah. + Ayah ~ 21 + +Pedih dia membayangkan dirinya dulu sebagai anak sekolah, +selalu khianat kepada ayahnya. Wajah ayahnya terbayang- +bayang, seandainya dia bisa membalik waktu. + + Akan tetapi, melihat anak-anak sekolah itu, tiba-tiba +Markoni terpikir akan sesuatu, sesuatu yang hebat! Lekas- +lekas dia keluar dari warung kopi lalu berdiri di pinggir jalan +raya untuk mengamati dari dekat rombongan anak-anak se- +kolah itu. Satu teori pendidikan yang dahsyat terangkai dalam +kepalanya. Markoni melonjak girang. Itulah momen eureka! + + Teori pendidikan itu bermula dari asumsi bahwa sema- +ngat orang untuk beranak tak pernah surut, akibatnya murid +sekolah akan semakin banyak, otomatis guru akan semakin +banyak. Dari kacamata bisnis, semua itu hanya berarti satu +hal, yakni permintaan kertas, buku-buku, dan segala hal +berbentuk cetakan, kartu, formulir, poster, selebaran pasti +meningkat. Dilihatnya anaknya sendiri, masih SD, tetapi pa- +ling tidak punya empat puluh buku. Usaha percetakan akan +b­ ooming. + + Markoni melompat-lompat girang. Dia ingin terlibat +dalam upaya pemerintah mencerdaskan kehidupan bangsa. +Keesokannya dia langsung menjual alat-alat musik yang telah +diperlakukan dengan semena-mena oleh para musisi Belantik +itu. Hasil penjualan itu langsung dipakainya untuk memulai +usaha baru: percetakan batako. + Volare + +SAMBARAN petir itu tidak hanya menghanguskan antena +radio di puncak pohon gayam, tetapi juga membuat radio itu +rusak. + + Amirza tak mau ketinggalan sandiwara radio Menantu +Durhaka, yang saban malam diudarakan radio lokal. Sandiwa- +ra radio itu juga acara kesayangan Amiru dan ibunya. Maka, +segera Amirza membawa radio itu ke kios reparasi elektronik +Gaya Baru di kawasan pasar ikan. Pemilik kios itu, tak lain tak +bukan, satu dan hanya satu-satunya, Syarif Miskin. + + Dari Syarif Miskin-lah kemudian Amirza mendapat pe- +ngetahuan yang lebih bisa dipertanggungjawabkan tentang +cara kerja antena. Kawan, mohon kata “bisa dipertanggung- +jawabkan” itu disikapi secara bijaksana. + + Syarif Miskin dulu berprofesi sebagai asisten operator +alat berat. Heavy Duty, orang-orang berhelm kuning nan ga- +gah dengan mesin-mesin raksasa, excavator, kendaraan dobel + Ayah ~ 23 + +gardan, delapan belas roda, itulah permainannya sehari-hari. +Semuanya tiarap saat PN Timah gulung tikar. Syarif bergan- +ti profesi menjadi juru rias pengantin. Bosan di bidang itu, +sekonyong-konyong, seakan mendapat mukjizat dari langit, +dia menjelma menjadi montir radio. Mengenai bonus nama +“Miskin” di belakang namanya itu, kiranya tak perlu lagi di- +uraikan. + + Kepada Amirza, Syarif bersabda, bahwasanya siaran +radio akan lebih mudah ditangkap jika ujung kawat yang diu- +lur dari antenanya ditautkan ke kumparan logam yang lebar. + + Kumparan adalah makhluk ningrat yang hanya mun- +cul di buku yang biasa dipegang orang-orang pintar. Adapun +pembicaraan Amirza sehari-hari adalah pukat, semprong +lampu petromaks, sabun colek, sandal jepit putus, kutu be- +ras, minyak jelantah, perigi, tali rafia, obat nyamuk, aspirin, +kerokan, batu baterai, dan atap bocor. Maka, ketika Syarif +mengucapkan kata “kumparan”, Amirza, yang hanya tamat +SD dan buruh pabrik sandal jepit, bertekuk lutut di haribaan +kecerdasan lelaki Melayu sok tahu itu. + + Sampai di rumah, Amirza hilir mudik dan berkali-kali +menarik napas panjang. Wajahnya tegang, kepalanya dipe- +nuhi oleh pertimbangan-pertimbangan ilmiah tingkat uni- +versitas. Dia berusaha keras menerjemahkan kata-kata dari +Syarif soal kumparan logam yang lebar. + + Tiba-tiba dia tersenyum. Sesuatu memantik dalam ke- +palanya. Diulurnya kawat dari ujung antena radio menuju +belakang rumah, tepatnya ke kandang bebek. Rupanya Amir- + 24 ~ Andrea Hirata + +za telah menemukan definisi kumparan logam yang lebar itu, yaitu +jalinan kawat ram yang menjadi kandang bebek. + + Amiru menyaksikan tingkah laku ayahnya sambil ber- +usaha keras menahan tawa. Dia adalah murid yang cerdas. +Nilai IPA di rapornya tak kurang dari 8,5. Dia tahu apa yang +dilakukan ayahnya itu konyol dan tak berguna. Diam-diam +dia selalu melakukan analisis atas eksperimen-eksperimen +ayahnya. Jika eksperimen kandang bebek ini gagal, berarti +ayahnya telah gagal membuat siaran radio lebih baik seba- +nyak enam belas kali. + + Menurut Amiru, menautkan kawat antena ke kandang +bebek pasti membuat siaran radio semakin buruk karena bisa +terjadi induksi. Bisa juga terjadi satu korslet yang berbahaya +karena frekuensi radio saling bertabrakan, belum menghitung +radiasi sinar matahari, ultraviolet, serta risiko atas reaksi me- +dan listrik yang berkolaborasi dengan medan magnetik (sebe- +narnya apa, sih, yang sedang kita bicarakan ini?). + + Akan tetapi, Amiru diam saja. Tak mau dia mengecilkan +hati ayahnya yang sedang dilanda awan-awan ilmiah. Lebih- +lebih karena dia tahu makna radio itu bagi ayahnya. Serius +dia menonton aksi ayahnya. Melihat anaknya memandang- +nya dengan penuh kagum, Amirza semakin gesit. + + Antena selesai ditautkan. Amirza meminta Amiru meng- +ambil batu baterai yang sedang dijemur di atap rumah. Sege- +ra Amiru melaksanakan perintah itu. + + Empat batu baterai dimasukkan ke radio. Tegang wa- +jah Amirza ketika memutar tombol volume yang sekaligus + Ayah ~ 25 + +tombol on-off. Amiru cepat-cepat menutup telinga dengan ta- +ngan karena tahu eksperimen itu akan gagal dan radio akan +menguing. Benar saja. Dia tersenyum sebab teorinya benar. +Amirza kecewa, diputar-putarnya tombol tuning, srasak, srosok, +srasak, srosok, bbbrbrbtttt ... brrrhhh .... Diputarnya lagi, ngiiiiiinggg +... bunyi berdenging panjang, nyaring, dan sangat menggang- +gu. Diputarnya lagi, srosok, bbrbrbttttbhhh ... brrrhhhbbb ... ngu­ +iiiiiiiiinggg, gagal total. Amirza terhenyak pasrah di atas kursi +rotan. Amiru terpingkal-pingkal di dalam hati, tetapi seko- +nyong-konyong terdengar musik yang rancak dan lagu yang +indah volareee ... o ... o ... volare o o o ... gembira, lantang, tanpa +kemerosok sedikit pun. Tak pernah sebelumnya terdengar su- +ara sebersih itu dari radio tua itu. + + Amirza terpana, ditatapnya radio itu seperti menatap +benda ajaib. Ibu Amiru yang tengah berbaring di kamar +bangkit karena mendengar sebuah lagu melantun dengan jer- +nih. Apakah Amirza baru membeli tape? katanya dalam hati. Dia +melangkah menuju ruang tengah, dari ambang pintu kamar +dilihatnya Amirza dan Amiru terpaku di depan radio. Mu- +lut Amirza komat-kamit, diputarnya lehernya pelan-pelan ke +arah Amiru, yang berdiri tertegun di situ macam orang kena +tenung. + Masih Berlaku + +HANYA mereka yang diberkahi Yang Mahatinggi dengan +kecerdasan istimewa yang dapat melihat hubungan antara +anak-anak yang berduyun-duyun pulang sekolah dengan usa- +ha percetakan batako. Salah satu dari orang yang diberkahi +itu adalah Markoni. + + Karena banyak anak sekolah, tentu pemerintah perlu +membangun sekolah. Pembangunan sekolah tentu perlu bata- +ko. Begitulah skenario genius Markoni. Dengan cepat, usaha +percetakan batakonya mengalami kemajuan. + + Markoni adalah orang yang kenyang pengalaman seka- +ligus orang yang traumatis. Masa lalu yang pahit membuat- +nya tak ingin pengalamannya dialami anak-anaknya. Kepada +mereka, Markoni selalu mengatakan sesuatu yang dikatakan +ayahnya kepadanya dulu, bahwa jika anaknya mau sekolah, +akan disekolahkannya sampai kapan pun, ke mana pun. Dia +siap berkorban apa saja. + Ayah ~ 27 + + “Kalau perlu menggadaikan rumah.” + Akan tetapi, hukum karma tetap berlaku dan masih ber- +laku. Dua anak lelakinya, seperti dirinya dulu, menempuh ja- +lan hidup sebagai bedebah. + Anak ketiganya perempuan, pendiam, dan penuh bisa. +Baru kelas dua SMP anak itu sudah disambar seorang lelaki +berpembawaan kalem. Yang kalau diajak bicara banyak me- +nunduk. Lantaran dilanda kekecewaan yang besar atas tak +becusnya tiga anaknya, Markoni menaruh harapan terbesar +kepada si bungsu. Namun sial lagi, di balik wajah manis si +bungsu itu, tersimpan jiwa pemberontak. + Si bungsu telah menunjukkan tanda-tanda berandal se- +jak SD. Disuruh belajar sama susahnya dengan menyuruh +kambing berkokok. Dimarahi, dianggapnya angin lalu saja. +Diperingatkan, tak mempan. Diancam, tak gentar. Dinasi- +hati, melawan. Satu patah kata ayahnya, dua patah kata dia. +Dihardik supaya rajin belajar biar nanti bisa sekolah tinggi, +dipulangkannya kata-kata ayahnya, bahwa ayahnya sendiri +dulu drop out. Markoni panas telinga, tetapi mati kutu. + Markoni bertanya kepada istrinya, mengapa si bung- +su keras begitu. Istrinya berkata, lihatlah siapa yang bicara +itu. Berkali-kali si bungsu hampir tak naik kelas. Kritis. Yang +membuat Markoni sangat jengkel adalah kata guru-guru, si +bungsu itu sesungguhnya sangat pintar. Sekarang Markoni +dapat merasakan betapa pedih hati ayahnya dulu sebab dia +dulu juga sebenarnya murid yang pintar. + 28 ~ Andrea Hirata + + Kata guru, kalau mau, dengan mudah si bungsu bisa da- +pat rengking. Namun, karena wataknya yang keras, si bungsu +seakan menyabotase dirinya sendiri. Mungkin itu bentuk pro- +tes terselubung kepada ayahnya yang otoriter. + + Melihat tabiat si bungsu yang makin kacau, Markoni +muntab lalu mengancam, “Kalau kau tak lulus ujian masuk +SMA negeri, tak usah sekolah sekalian!” + + Ancaman berikutnya gawat, “Kau akan kukawinkan +saja!” + + Kawan ayahnya, seorang pengusaha kopra dari Kari- +mun, memang disebut-sebut melirik si bungsu yang manis +berlesung pipit itu. Si bungsu gemetar. + + Si bungsu telah melihat betapa runyamnya kawin muda +seperti yang dialami kakaknya. Setiap kali berjumpa, wajah +kakaknya kusut masai macam pukat diterjang hiu. Tak ada +hal lain yang keluar dari mulutnya selain keluhan. Dia pun +tak mau terlempar ke Karimun, tak ada kawan dan saudara di +sana. Si bungsu ciut karena tahu ancaman ayahnya tak main- +main. Lagi pula, perjodohan masih sangat biasa di Kelumbi. + + Sekonyong-konyong dia rajin belajar agar bisa lolos dari +ancaman yang mengerikan itu. Namun, semuanya telah ter- +lambat karena ujian masuk SMA negeri sudah terlalu dekat. +Ketinggalan pelajarannya begitu banyak, tak dapat dikebut +dengan belajar semalam dua malam saja. + + Ujian itu diikutinya dengan cemas, tak percaya diri. Ni- +lai rata-rata untuk lulus adalah 6,5. Hampir mustahil diraih + Ayah ~ 29 + +si bungsu mengingat soal-soal yang sangat sulit dan saingan +yang ketat. + + Setiap hari dia gelisah menunggu pengumuman hasil +ujian itu. Ancaman ayahnya menghantuinya sehingga dia +susah tidur. Belum-belum dia telah membayangkan tinggal +di kampung terpencil, kawin dengan lelaki yang tak dicintai­ +nya, bahkan tak dikenalnya. Dia menyesal tak pernah serius +belajar. Kini ancaman yang besar merundungnya. Dia ingin +seseorang menyelamatkannya, tetapi orang itu tak ada. Dia +mengadu kepada ibunya, bahkan ibunya tak mampu mela- +wan kemauan ayahnya. + Bunga Ilalang + +DI kampung lain, Belantik, Sabari juga gelisah menunggu +hasil ujian itu, bukan hanya karena dia ragu bisa diterima di +SMA negeri, melainkan lebih karena perempuan misterius +yang telah memberinya pensil dan membuat badannya panas +dingin. Layaknya orang yang kena sambar cinta pertama, dia +serbasalah, susah tidur. Miring ke kiri salah, ke kanan salah. +Telentang, dia malu, karena cicak-cicak mengejeknya. + + Sekarang dia memaklumi perasaan Ukun kepada Ha- +nifa, Sita, Mawar, Anisa, Laila, Nurmala, Aini, Indra, Deli, +Lili, Mumun, Nizam, Latifah, Salamah, Fatimah, Hasanah, +Sasha, Zasa, Zaza, dan Shasya, serta perasaan Tamat kepada +Amoi, Zarina, A Yun, Minar, A Mung, Nuri, Rifa, Umi kam- +pung seberang, dan Umi anak Pak RT, block, copy, paste. + + Bertemu dengan Ukun dan Tamat, meski mereka tak +tahu rahasia hatinya, Sabari merasa malu dan tak tahu ba- +gaimana cara memulangkan kata-katanya sendiri soal perem- + Ayah ~ 31 + +puan kepada kawan-kawannya itu. Karena, dia telah menjadi +orang yang dulu dicemoohnya. + + Sabari melamun. Apakah aku kelihatan seperti orang yang se- +dang memendam sebuah rahasia? Apakah Ukun dan Tamat tahu rahasia +hatiku? Bahwa aku sedang jatuh cinta? Perlukah kukabari mereka bah- +wa aku sedang jatuh cinta? Kukabari sedikit mungkin, jangan banyak- +banyak, tapi jangan ah, aku malu. Oh, apakah gerangan yang kualami +ini? Mengapa kebingungan bisa menjadi begitu indah? + + Ukun dan Tamat sendiri jengkel karena Sabari tak mau +lagi diajak ke danau tambang untuk berenang. Diajak me- +ngejar layangan di padang, dia menggeleng. Diajak meng- +gantungkan sepeda guru ngaji di dahan pohon bantan, dia tak +berminat. Padahal, dulu dialah biangnya. Diajak melempar +buah sagu, dengan sungkan dia berangkat. Namun, tingkah- +nya aneh. Dia memasukkan bajunya. Ukun jengkel. + + “Boi! Kau ini mau menghadap Pak Camat atau mau ke +hutan?!” + + Dibongkarnya baju Sabari. Diam-diam Sabari mema- +sukkannya lagi. + + Sekonyong-konyong, Sabari bukan Sabari yang dulu +lagi. Dia lebih kalem, lebih sering mandi, dan tak mau me- +ngenakan baju bernoda getah buah hutan. + + Saban malam dia rindu kepada perempuan yang me- +rampas kertas jawabannya itu. Mata anak itu lekat dalam +kepalanya. Di dinding kamarnya dia menulis; Purnama kedua +belas, siapakah dirimu? + 32 ~ Andrea Hirata + + Dulu, di antara kawan-kawannya, Sabari paling terlam- +bat pandai naik sepeda. Dia juga terakhir pandai mengaji, +pandai menulis dan membaca, semua itu lantaran kesabar- +annya. Namun, kali ini dia tak dapat bersabar. Sebab, dia tak +tahan memegang pensil sepanjang malam. Dia lelah melihat +bunga-bunga ilalang beterbangan dalam kamarnya. Dia ha- +rus tahu siapa anak perempuan itu dalam tempo sesingkat- +singkatnya. Untuk itu, satu-satunya cara adalah dengan me- +nunggu anak itu di MPB, pas hari pengumuman hasil ujian +masuk SMA nanti. + + Sabari mengarungi hari demi hari bak mengarungi +samudra waktu. Akhirnya, tibalah hari pengumuman yang +mendebarkan itu. Sejak siang Sabari sudah bercokol di peka- +rangan Gedung MPB. Belum pernah dia merasa waktu ber- +jalan begitu lambat sekaligus cepat. Cepat sekaligus lambat. +Membingungkan. + + Agar sasaran tak lolos, Sabari mengambil posisi di ping- +gir selasar. Siapa pun yang ingin melihat pengumuman harus +melalui selasar panjang itu. + + Petugas menempelkan lembar pengumuman, anak-anak +mulai berdatangan. Lekat Sabari menatap setiap anak perem- +puan, jantungnya mau copot. Teriakan anak-anak yang lulus +membuatnya makin gugup. Dia sendiri tak peduli akan hasil +ujiannya karena pikirannya terfokus kepada perempuan ber- +mata indah seperti purnama kedua belas itu. + + Tiba-tiba anak perempuan itu berbelok di ujung selasar. +Sabari terpana. Anak itu melangkah dengan cepat, wajahnya + Ayah ~ 33 + +seperti mau menangis. Dia tak tahu Sabari menatapnya ma- +cam bayi menatap kelereng karena dia cemas tak lulus lalu +dikawinkan ayahnya dengan lelaki dari Karimun. + + Makin dekat ke papan pengumuman, si bungsu semakin +gugup. Apalagi, dilihatnya anak-anak yang tak lulus mena- +ngis. Dipanjatkannya doa agar nilai rata-ratanya paling tidak +6,5. Itu batas minimum kelulusan. Sampai di muka papan +pengumuman, dia langsung menyelinap di antara kerumum- +an. Karena kecemasan yang memuncak, susah dia menemu- +kan namanya di antara ratusan nama siswa. Berulang-ulang +mencoba, akhirnya dia lihat namanya, MARLENA. + + Sejarah: 7 + IPS: 7 + PMP: 7 + Pendidikan Jasmani: 7 + Biologi: 6 + Matematika: 5 + Fisika: 5 + Bahasa Inggris: 5 + Bahasa Indonesia: 9,5 + Rata-rata: 6,5 + LULUS. + Dia bersorak dan melompat-lompat, matanya terbelalak +melihat nilai Bahasa Indonesia-nya yang fantastis, 9,5, hampir +sempurna 10. Tak pernah seumur hidupnya mendapat nilai +setinggi itu dan nyata-nyata nilai itu telah menyelamatkannya + 34 ~ Andrea Hirata + +sehingga dia lulus. Marlena merasa sangat lega karena berha- +sil lolos dari ancaman ayahnya. Dia ingin segera pulang untuk +memberi tahu ibunya hasil ujian itu. + + Sementara itu, nun di pojok selasar itu, Sabari yang be- +lum sadar dari pukau saat Lena datang tadi, kembali diserbu +pesona yang seluruh dirinya tak dapat menanggungnya. Di- +lihatnya Lena berjalan seakan-akan melayang-layang, lebih +memesona daripada saat dia datang tadi, sebab sekarang dia +tersenyum berbunga-bunga. Sabari berpegangan kuat-kuat +pada tiang untuk meredakan tubuhnya yang berguncang +macam dilanda angin ribut. Lena melewatinya, sepintas dili- +hatnya anak lelaki berwajah aneh, dengan mulut ternganga, +menatapnya tak berkedip sambil memeluk tiang. Siapakah anak +itu? Rasanya aku kenal? + SMA + +DALAM peri kehidupan manusia, sebelum nasib sial meng- +hantam bertubi-tubi, menganggur, tak lolos audisi, kena +PHK, kena tipu, utang membelit, prahara rumah tangga, +ekonomi sulit, berupa-rupa penyakit, tiada jeda menghantam +sampai napas tersangkut di tenggorokan, lalu mati, nasib me- +manjakan manusia dengan satu masa yang hebat: SMA. + + Sabari mengawali langkah pertama di SMA dengan se- +nyum terlebar yang dia miliki. Satu senyum dari telinga ke +telinga. Kawan-kawan baru, guru-guru baru, ilmu-ilmu baru, +dan terutama, yang paling mendebarkan: seseorang bernama +Marlena. + + Ingin Ukun membelah kepala Sabari untuk melihat apa +yang terjadi di dalamnya. Karena melihat Lena berkelebat +sedikit saja, dia macam kena penyakit angin duduk. Sebalik- +nya, Lena benci. Sabari tak hirau. Filosofi hidupnya adalah +mencintai seseorang merupakah hal yang fantastis, meskipun + 36 ~ Andrea Hirata + +orang yang dicintai itu merasa muak. Itu soal lain, tidak re- +levan. + + Tak ada hari dilewatkannya tanpa memandangi foto +Lena, berukuran 3 x 4 hitam putih, yang dia dapatkan dengan +cara menggelapkannya, melalui satu konspirasi dengan petu- +gas tata usaha SMA. Tiada jeda puisi dan surat dikirimnya. + + Tahu-tahu dia punya pekerjaan usai jam sekolah, yaitu +menghambabudakkan dirinya kepada tukang sampah di Pa- +sar Belantik, demi sedikit upah yang dipakainya untuk mem- +beli kartu request—selembar lima ratus perak—di radio lokal +AM Suara Cinta. Saban petang mengudaralah lagu dan sa- +lam untuk Lena di Kelumbi, dari DYSMJDB. Tak jelas apa +maksud singkatan itu. + + Sering Ukun, Tamat, dan Toharun menggoda Sabari +dengan mengatakan bahwa mereka baru saja melihat Lena. +Itu tipuan, Sabari muntab. Namun, sesungguhnya tak perlulah +mereka memberi tahu di mana Lena, sebab khusus untuk ga- +dis Kelumbi itu, Sabari telah bermutasi menjadi lumba-lum- +ba. Dia punya semacam kemampuan ecolocation. Kepala lon- +jong buah kemirinya dapat memancarkan sonar yang akan +dipantulkan oleh dinding sekolah, pohon-pohon bungur, pa- +gar berduri, dan tiang bendera sehingga Sabari dapat menen- +tukan satu koordinat di mana Lena bercokol. Satu bukti nyata +bahwa cinta sebelah mata bisa meningkatkan kapasitas otak. + + Jika Lena berada di kantin, Sabari pasti berada dekat +rumpun-rumpun beluntas di muka perpustakaan. Berpura- +pura melihat-lihat sarang burung prenjak, padahal matanya + Ayah ~ 37 + +mencuri pandang. Jika Lena ada di tempat parkir sepeda, +Sabari gelisah menunggunya melewati gerbang. Kalau Lena +main pingpong, Sabari rajin sekali menyapu ruang olahraga, +meski bukan giliran piketnya. Kalau Lena main kasti, tak tahu +siapa yang menyuruhnya, Sabari sigap sekali latihan baris- +berbaris di lapangan sekolah, sendirian. + + Akan tetapi, rupanya, cinta, meski sebelah mata mau- +pun buta, selalu saja berbuah kebaikan. Nilai rapor semester +1 Sabari jauh lebih baik daripada nilai Ukun dan Tamat, apa- +lagi Toharun. Mungkin karena Toharun hanya tertarik pada +pelajaran Pendidikan Jasmani dan Seni Suara. Dia gemar se- +kali bernyanyi lagu India. + + Pelajaran kesayangan Sabari adalah Bahasa Indonesia. +Bakat ayahnya sebagai guru Bahasa Indonesia SD nyata-nya- +ta menurun kepadanya. Kelihaiannya membuat puisi diakui +semua pihak: kawan-kawan, kepala sekolah, guru-guru, mau- +pun penjaga sekolah. + + Bakat puisinya terendus waktu para siswa diberi tugas +menulis puisi. Puisi Sabari berjudul Adalah, sebagai berikut. + + Cinta adalah mahkota puisi + Musim adalah giwang puisi + Hujan adalah kalung puisi + Bulan adalah gelang puisi + Cincin adalah perhiasan + 38 ~ Andrea Hirata + + Bergetar tak keruan hati Ibu Norma, guru Bahasa Indo- +nesia, sekaligus wali kelas, demi membaca puisi itu. Selama +lima belas tahun mengajar, sejak tamat SPG (sekolah pendi- +dikan guru), belum pernah dia menemukan murid SMA yang +dipenuhi anak-anak kuli timah, menulis puisi seperti itu. Apa- +lagi, siswa itu berasal dari Belantik, kampung tambang yang +hidup segan mati tak mau itu. Maaf, Kampung Belantik yang +dikenalnya disesaki orang-orang udik yang berkeringat kalau +makan, tetapi kalau bekerja tidak. Pernah dia bersuamikan +orang Belantik, cukup sekali! + + Lama Bu Norma menelaah puisi itu. Cinta adalah mahkota +puisi, bukankah kalimat yang spektakuler? Bagaimana anak +udik cengengesan itu mendapat kalimat itu? Soal cincin ada- +lah perhiasan, pastilah, pikir Bu Norma, Sabari mencoba me- +masukkan unsur realitas dalam puisinya yang metaforis. + + Bu Norma terkenal galak, suka berterus terang, tetapi +tulus dan disenangi. Dia tidak menjelekkan atau memuji di +belakang. Karena itu, dia dihormati. Dipanggilnya Sabari, di- +katakannya bahwa dia berbakat di bidang puisi. Sabari terse- +nyum. Dia sendiri tak tahu arti kata metaforis. Yang dia tahu +semuanya digerakkan oleh cintanya kepada Lena, cinta yang +bahkan telah membuatnya melihat WC umum di pasar ikan +Belantik, yang baunya dapat membuat bola mata meloncat, +indah tak terperi. + Izmi + +KARENA tak ingin melihat kawan menggantang asap, tak +sampai hati melihatnya ditolak Lena hari Senin, Selasa, Rabu, +Kamis, Jumat, Sabtu, Minggu, sampai Senin lagi. Ditolak +pagi, siang, dan malam, full time, berkali-kali Ukun, Tamat, +dan Toharun mengingatkan Sabari agar melupakan Lena. + + “Dia melirikmu? Sama dengan ayam mengeong, musta- +hil,” kata Tamat. + + “Mending kau bergeser ke arah Shasya,” saran Ukun. + “Berdasarkan perhitunganku, rasa sayang Lena padamu +lebih kecil daripada rasa bencinya. Kita tahu dalam Matema- +tika, nilai yang lebih kecil dikurangkan dengan nilai yang le- +bih besar, hasilnya nol. Maka nol persen, itulah peluangmu,” +kata Toharun. Wajar nilai Matematika-nya 2. + Sabari tak terpengaruh oleh suara-suara yang mengecil- +kan hati itu. Baginya itu bunyi distorsi radio, menguing-ngu- + 40 ~ Andrea Hirata + +inglah sesuka kalian. Dia fokus kepada Lena. Dia tak mau dan +tak dapat pindah ke frekuensi lain. + + Untuk keperluan itu dia punya mata-mata, yaitu salah +seorang kawan terdekat Lena, Zuraida, yang senang saja diso- +gok Sabari dengan buah nangka hasil kebun sendiri. + + Di bawah pohon urisan, di belakang sekolah, sambil si- +buk memamah biak nangka, Zuraida berkisah bahwa Lena +suka main kasti. Kasti? Berdebar dada Sabari. + + Sabari yang tak pernah suka olahraga, yang badannya +seperti mau patah kalau ditiup angin barat, bulan berikutnya +terpilih masuk tim inti kasti SMA. Lain waktu Zuraida ber- +kata bahwa Lena suka lompat jauh. Tak ada angin tak ada +hujan, tahu-tahu Sabari menggondol juara pertama lompat +jauh tingkat SMA. Gayanya melompat macam belalang sem- +bah. Izmi bertepuk tangan. + + Izmi, kawan sekelas Zurai, dianggap siswa lain mirip +Ukun, Tamat, Toharun, dan Sabari sendiri, yakni sama-sama +orang yang tidak keren, para pecundang. Wajahnya tak me- +narik. Nilai rapornya buruk karena dia harus bekerja. Alasan- +nya klasik, ekonomi. Usai jam sekolah, dia bekerja mencuci +dan menyetrika pakaian tetangga sampai malam. Profesi itu +sudah dijalaninya sejak kelas dua SMP. Jika berkaca, sering +Izmi benci kepada dirinya sendiri karena tak ada yang dapat +dibanggakan dalam dirinya. Dia selalu merasa dirinya sial. + + Keluarga Izmi tadinya kaya, tetapi mendadak miskin. +Waktu Izmi kelas satu SMP, ayahnya ditangkap polisi lantaran + Ayah ~ 41 + +korupsi. Semua harta benda disita. Keluarga itu kocar-kacir. +Untuk bertahan, ibu Izmi berjualan kue. Izmi, anak tertua, +menjadi tukang cuci dan setrika. Gara-gara musibah itu, Izmi +yang bercita-cita ingin menjadi dokter hewan mengubur cita- +citanya dalam-dalam. + + Jumlah angka merah di rapor Izmi pada semester 1 ti- +dak tanggung-tanggung, delapan. Yang biru hanya Pendidik- +an Keterampilan Keluarga, yang merupakan kejahatan jika +sampai seorang siswa dapat angka merah. Kata wali kelasnya, +Izmi pasti takkan naik ke kelas dua. + + Izmi berkecil hati dan bermaksud berhenti dari sekolah. +Tak ada gunanya belajar, mending bekerja, dapat membantu +keluarga. Namun, nasib berkata lain. Saat berada dalam per- +timbangan yang putus asa itu, dia mendengar cerita Zuraida +soal kerasnya perjuangan Sabari untuk mendapatkan Lena. + + Izmi bukanlah kawan Sabari—mereka bahkan tak per- +nah bertegur sapa—tetapi ajaib, kisah konyol Sabari mem- +buat Izmi terinspirasi. Sabari membuatnya merasa dia bukan +satu-satunya orang yang malang di dunia ini. + + Kata Zurai, Lena suka menulis indah. Minggu depannya +Sabari sudah menjadi ahli kaligrafi. Dia bisa menulis nama +Marlena binti Markoni dengan huruf-huruf berupa burung +merak. Semangat belajar Izmi pelan-pelan bangkit. + + Kata Zurai, Lena suka melihat laki-laki pakai baju se- +ragam. Agustus berikutnya, Sabari yang suka bolos upacara, +terpilih masuk tim Paskibra SMA. Terpana Izmi melihat Sa- +bari berbaris macam siswa sekolah militer. + 42 ~ Andrea Hirata + + Sabari masuk band SMA demi mendengar kabar angin +Lena suka sama pemain gitar band itu. Karena tak bisa main +musik, Sabari menjadi tukang gulung kabel yang berdedikasi +tinggi. + + Tak seperti para pemain band yang berantakan, Sabari +rapi jali. Tak bisa dia melihat kabel centang-perenang tak ke- +ruan, pasti digulungnya. Kerap dia dimarahi lantaran meng- +gulung kabel di atas pentas tak peduli pertunjukan sedang +berlangsung. Terpingkal-pingkal Izmi melihatnya repot seka- +li menggulung kabel di antara anak-anak band yang tengah +berjingkrak-jingkrak membawakan lagu “The Final Count- +down”. + + Akhirnya, Sabari kena pecat ketua band, yang juga gitaris +cakap yang ditaksir Lena itu. Sabari tak terima. Dia protes +di muka ketua OSIS, katanya tak pernah band itu sebersih +dan serapi sejak dia bergabung sebagai pembantu band, dan +bahwa kabel-kabel yang tak tertib dapat menyebabkan orang +kena sambar listrik, bahwa betapa dia mencintai musik dan +menyukai pekerjaannya, meskipun menjadi jongos kawan- +kawannya sendiri. Ketua OSIS tak berdaya karena yang me- +mecat Sabari kemudian bukan hanya ketua band, melainkan +juga seluruh anggota band. Apa boleh buat. + + Kata Zurai, Lena punya hobi sahabat pena. Sering dia +berkirim surat kepada sahabat pena di Sumatra. Sabari me- +ngirim surat kepada Patrick Confident Mwana di Zimbabwe. + Ayah ~ 43 + + Dear Mister Patrick Confident Mwana + My name is Sabari, from Belitong Island, Indonesia. + I am high school student. + I see photo you in the Sahabat Pena Magasin, very very good. + I want friend with you. + I am sorry my english language very very bad, 4 in my report, very +very red. + But let no english good, I write a poem for you. + + I have a friend + My friend from Africa + I love my girlfriend + Her name is Marlena + + What you think, Mister Confident? + + Thank you very very much. + If you want write letter for me, my address on envelope. + Sincerely yours. + Very very happy. + Sabari + + Malangnya, seluruh prestasi Sabari yang fenomenal itu +membuat Lena malah semakin brutal menolaknya. Jika dulu +dia sekadar tidak membalas surat Sabari, sekarang surat-surat +itu dirobeknya kecil-kecil lalu dihamburkan di tempat parkir. + 44 ~ Andrea Hirata + +Jika dulu dia hanya mengatakan tak usah ya jika dikirimi Sa- +bari nangka hasil kebun sendiri, disertai satu kartu ucapan +yang manis, “Purnama Kedua Belas, silakan menikmati semua keba- +ikan dari buah nangka”, kini dibantingnya nangka hasil kebun +sendiri itu sambil ngomel-ngomel. + + Adakah kemudian Sabari membenturkan kepalanya ke +pohon nangka? Tidak. Adakah dia mengumpankan lehernya +ke gergaji mesin? Tidak. Adakah dia mengikat tangan dan +kakinya sendiri lalu memplester mulutnya? Tak tahu bagaimana +caranya, sebab bukankah tadi tangannya terikat? Lalu, mencebur- +kan diri ke Sungai Lenggang agar ditelan buaya muara bu- +lat-bulat? Tidak. Ataukah dia menggunakan cara-cara yang +picik, bahkan anarkis, untuk menarik perhatian Lena? Maaf, +Sabari tak punya sifat-sifat obsesif semacam itu. Halo? + Intervensi + +“KARENA siaran radio kita sudah jernih, kalau nanti ada +siaran Lady Diana, undanglah tetangga, Miru, biar bisa men- +dengar radio di rumah kita. Lebih jelas suaranya.” + + “Iya, Ayah,” kata Amiru. Sementara itu, dia penasaran, +bagaimana kandang bebek bisa menyebabkan penangkapan +siaran radio menjadi lebih baik? + + Dalam pelajaran IPA di kelas, dia menanyakan soal itu +kepada guru, tetapi tak mendapat jawaban yang memuaskan. +Didorong perasaan ingin tahu, dan minat belajar yang selalu +tinggi, jauh-jauh dia bersepeda ke perpustakaan daerah un- +tuk membaca buku-buku soal radio. Sayangnya buku-buku +semacam itu amat terbatas. Tak ditemukannya penjelasan +yang khusus soal itu. Akhirnya, Amiru merasa satu-satunya +orang yang dapat menerangkannya—meski dia malas ber- +jumpa dengannya—adalah Syarif Miskin. + 46 ~ Andrea Hirata + + Pulang sekolah siang itu, Amiru ke kios elektronik Gaya +Baru dan langsung bertanya soal antena radio itu. Syarif ma- +lah menjawab dengan pertanyaan. + + “Kelas berapa kau?” + “Kelas lima, Bang.” + “SD?” Syarif tersenyum meremehkan. “Seperti kau ke- +tahui, Amiru, tapi mungkin juga kau belum tahu ....” + Amiru jengkel. + “Gelombang radio itu bergentayangan di udara, dia +hinggap sesuka hatinya, tak tampak oleh mata. Semua yang +tak tampak, tapi ada akibatnya adalah misteri, contohnya se- +tan! Dapatkah kau melihat setan?” + “Tidak, Pak Cik.” + “Dapatkah kau melihat angin?” + “Jadi, maksud Pak Cik?” + “Maksudku, jangan kau arahkan pikiranmu pada hal- +hal yang tak kasatmata. Itu mistik. Gelombang radio adalah +hal yang gaib. Bisa gila kau nanti.” + Tentu saja Amiru yang cerdas tak bisa menerima pen- +dapat yang sembarangan itu. Dikatakannya, dia hanya mau +bertanya soal penerimaan radio yang buruk di rumahnya dan +mengapa masalah itu bisa dibereskan oleh kandang bebek. +Merasa didesak, Syarif tak suka. + “Kalau kujelaskan padamu, kau tak akan mengerti! Mi- +salnya, mengapa siaran radio bisa muncul pada kelipatan fre- +kuensinya, tak ada ilmu yang dapat menjelaskannya. Menga- +pa? Karena semua itu adalah perbuatan iblis!” + Ayah ~ 47 + + “Tak apa-apa, Pak Cik, jelaskan saja sekarang. Aku pasti +mengerti.” + + “Baiklah, kujelaskan padamu! Penerimaan sinyal radio +di rumahmu buruk karena terlalu dekat dengan menara mas- +jid, maka terjadilah intervensi.” + + Ha, Intervensi? pekik Amiru dalam hati. Di perpustaka- +an daerah dia pernah membaca buku pengantar elektronika, +pastilah yang dimaksud Syarif itu interferensi, sok tahu! + + Berpanjanglebarlah Syarif soal intervensi itu. Amiru +mengangguk-angguk saja lalu minta diri. + + “Nanti kalau kau sudah SMP, sudah belajar soal gelom- +bang radio, baru ke sini lagi!” + + Pulang dari kios Gaya Baru, Amiru belajar dengan te- +kun. Dia mau segera masuk SMP. Dia bertekad untuk meng- +hadapi Syarif Miskin lagi. + Surat + +SABARI patah hati, tetapi dia tak patah harapan. Perasaan- +nya kepada Lena sama seperti saat Lena merampas kertas ja- +wabannya pada hari keramat itu. Lagi pula, ayahnya sering +mengatakan bahwa Tuhan selalu menghitung, dan suatu keti- +ka, Tuhan akan berhenti menghitung. + + Benar saja, hari itu, setelah dua tahun terus-menerus di- +tolak Lena, Tuhan berhenti menghitung. + + “Kun! Ukun!” + Ukun menoleh. + “Marlena membuat puisi untukku!” Wajah Sabari pu- +cat. Ukun tersenyum remeh. + “Di majalah dinding!” + “Benar?” + “Benar!” + “Kau tak sedang mabuk air legen, kan?” + “Tidak!” + Ayah ~ 49 + + “Kau tak salah lihat?!” + “Dua bola mata, yang kiri dan kanan, aku tak salah li- +hat!” + “Puisi menyumpah-nyumpah biar kau dicakar iblis atau +dilindas truk timah atau puisi baik-baik?” + “Bolehlah disebut puisi cinta!” + “Serius?” + Tenganga mulut Ukun. Mungkinkah Lena berubah pi- +kiran lantaran Sabari baru menang lomba menulis puisi ting- +kat SMA? Atau karena mau libur Lebaran, saat semua orang +tiba-tiba menjadi baik? Lena menulis puisi untuk Sabari? Sa- +ngat mustahil! + Bergegas Ukun menuju majalah dinding dengan kesan +siap mendaratkan satu sepakan Bruce Lee ke selangkang Sa- +bari kalau dia berani-berani berbohong. Namun, di sana dia +tertegun. Tak percaya dia melihat puisi diketik rapi itu. + + Untuk kau yang bernama S + Terima kasih untuk surat dan puisi-puisimu + Maaf, aku selalu tak sempat membalasnya + Tapi biar kau tahu, aku membaca semuanya, kalimat demi kali- + mat, kata demi kata + Lagu yang kau kirimkan lewat radio, aih, aku suka + L + + Ukun menatap Sabari. + “Kau yakin S itu maksudnya kau, Ri?” + 50 ~ Andrea Hirata + + “Siapa lagi?” + “Tahukah kau berapa banyak siswa bernama depan S? +Sulaiman, Syahrir, Salim, Silam, Salam, Sabarudin, Syam- +sudin, Sardin, Setegar, Setabah, Sahari, Samalam. Banyak +nama orang Melayu berawal S, bagaimana kau bisa yakin?” + “Indra keenam.” + “Indra keenam apanya? Indra keenam itu untuk orang +melihat iblis, bukan untuk melihat surat!” + “Suka-suka kaulah,” Sabari berkeras. + “Lantas dari mana kau bisa pasti L itu Lena. Bisa saja +Lina, Lia, Lisa, Lita, Liana, Ling-Ling.” + “Intuisi.” + “Intuisi dari mana?” + “Siapa yang suka mengirimi Lena puisi? Siapa yang +suka mengiriminya lagu lewat radio? Aku.” + “Memangnya orang lain yang mengirimi Lena lagu +akan memberi tahu kepala desa melalui surat, lalu suratnya +ditembuskan kepadamu dan rumah sakit jiwa?!” + “Puisi itu jelas untukku,” Sabari berkeras. + “Bukan! Dan, itu bukan puisi! Itu surat biasa, apa kau +tak bisa membedakan puisi dan surat biasa?!” + “Ai, sejak kapan kau tahu soal puisi? Ujian Geografi saja +kau menyontek jawabanku!” + “Cabut kata-katamu! Jangan kau ungkit-ungkit soal itu, +Geografi bukan ukuran kecerdasan! Apa susahnya untuk tahu +Lee Kuan Yew adalah Presiden Filipina!” + Barang Antik + +SEJAK pagi Amiru mengharapkan hujan turun karena dia +suka bunyi hujan, dia suka gemuruh sesekali menggelegar di +antara bunyi kecil rintik-rintik. Bukankah sebuah komposisi +musik yang dramatis? + + Akhirnya, hujan turun, menghantam atap seng. Amiru +memejamkan mata, lama, lambat laun dia mendengar sebu- +ah irama. Dia tersenyum. Dia tersenyum karena ingin seperti +ayahnya, yakni dapat menjadi senang karena hal-hal yang ke- +cil. Seni menyenangi hal-hal yang biasa saja, begitu istilah ayahnya +yang hanya tamat SMP itu. Amiru ingin menguasai seni itu +sampai tingkat ayahnya telah menguasainya sehingga men- +jadi orang yang dapat menertawakan kesusahan. Itulah ilmu +tertinggi seni menyenangi hal-hal kecil. Itulah sabuk hitam- +nya. + + Maka, Amiru paham benar arti radio Phillip tua itu bagi +ayahnya. Radio tak sekadar kotak elektronik yang pandai + 52 ~ Andrea Hirata + +mengeluarkan suara, tetapi juga kisah tentang seorang lelaki +yang bersusaha tetap senang dalam kepungan kesulitan. Ka- +rena itu, meski sebenarnya jengkel kepada Syarif, kejengkelan +itu lindap ketika melihat ayahnya tersenyum simpul di depan +radio itu. Amiru ingin menghadap Syarif. + + Tentu Syarif kaget melihat Amiru yang telah dimarahi- +nya berani datang lagi ke kiosnya. + + “Mau apa lagi kau, Bujang?!” + Amiru berterus terang bahwa dia mau belajar lebih ba- +nyak soal radio sebab dia senang pengetahuan listrik dan elek- +tronika. + “Apa katamu? Coba kau ulangi lagi.” + “Aku mau belajar ilmu radio.” + “Ulangi lagi.” + “Aku mau belajar ilmu radio dari Pak Cik.” + “Hmmm ....” + “Pak Cik Syarif Miskin.” + Syarif senang dan serta-merta menjelaskan beragam te- +ori tentang intervensi siaran radio. + Di rumah, Amiru sering menemani ayahnya mendengar +radio sambil membicarakan pelajaran yang didapatnya dari +Syarif Miskin. Ayahnya makin bergairah, apalagi telah bere- +dar kabar di kampung bahwa akan ada siaran yang tak boleh +dilewatkan. + Hari silih berganti. Amiru naik ke kelas enam. Amir- +ta, naik ke kelas empat. Si bungsu Amirna masuk kelas satu. + Ayah ~ 53 + +Amirza kesulitan mengatasi biaya sekolah, dan kali ini situasi +gawat karena dia juga memerlukan biaya sebab istrinya harus +dirawat di rumah sakit. + + Istrinya dirawat di rumah sakit di kabupaten. Besar bia- +yanya jauh dari kemampuan Amirza. Dengan panik dia men- +jual apa pun yang bisa dijual termasuk sebidang tanah. Ha- +sil penjualan itu dengan cepat habis. Dia masih perlu sedikit +uang dan sedapat-dapatnya tak mau berutang. Amirza habis +akal, tetapi kemudian dia teringat Syarif Miskin pernah me- +ngatakan bahwa radio Phillip itu tergolong barang antik yang +langka, harganya mahal. Dengan berat hati Amirza mem- +bungkus radio itu dengan taplak mejanya sekalian dan tergo- +poh-gopoh ke ibu kota kabupaten untuk menggadaikannya. + + Amiru tak tahu ayahnya telah menggadaikan radio itu. +Pulang dari sekolah dia terkejut melihat radio itu tak ada lagi +di tempatnya. Dari menggadaikan radio itu, Amirza bisa +membawa istrinya pulang setelah beberapa waktu dirawat di +rumah sakit. + + Malamnya Amiru mengintip ayahnya dari celah dinding +papan kamar. Dia selalu melihat ayahnya mendengar radio, +memutar-mutar tombol tuning, kini ayahnya hanya duduk ter- +mangu di kursi rotan itu. + + Malam beranjak, Amiru tak dapat tidur karena dia te- +lah terbiasa mendengar bunyi radio itu sejak masih kecil. Tak +pernah dia mengalami malam sesenyap dan sepahit malam +itu. + Perlambang + +SABARI menyesal telah mendebat Ukun soal surat itu, lebih- +lebih telah mengungkit-ungkit soal Geografi. Setelah ditela- +ahnya lebih lanjut, dia memang keterlaluan. Mengidentikkan +dirinya dengan satu huruf S saja dan Lena dengan satu huruf +L adalah satu perbuatan amatir yang tidak masuk akal. + + Dengan lapang dada dia melakukan semacam rekonsi- +liasi dengan mentraktir Ukun, Tamat, dan Toharun minum +kopi di warung kopi Kutunggu Jandamu. + + “Sudahlah, Ri, semua itu hanya harapan palsu. Kasih- +an aku melihatmu. Masih banyak perempuan di Belantik ni,” +kata Tamat. + + “Aku gagal mendekati Shasya, dia muak padaku, siapa +tahu kau berhasil, Boi. Kudegar tren zaman sekarang ini ba- +nyak perempuan cantik suka sama lelaki yang dungu, siapa +tahu,” saran Ukun. + + Sabari mengangguk-angguk. Tampak benar minatnya +untuk mempertimbangkan saran itu. + Ayah ~ 55 + + “Di dunia ini hanya ada dua macam laki-laki, yang gagal +dan yang sukses.” Ini teori Toharun. + + “Delapan puluh persen laki-laki sukses, sisanya, tiga pu- +luh persen, gagal. Nah, tak perlu kujelaskan lebih lanjut, kau +tahu sendiri di mana kau berada.” + + Sabari berterima kasih atas wejangan dan nasihat ka- +wan-kawan dekatnya itu. Dia sadar bahwa sudah saatnya +bersikap rasional soal Lena. + + “Menyesal aku harus bertengkar dengan kalian gara- +gara Lena, gara-gara huruf S dan L. Maafkan aku, Boi.” Ke- +empat sahabat itu bersalaman dengan takzim. Sabari terharu. + + “Ah, apa jadinya aku ini tanpa kalian? Sahabat-Saha- +bat Terbaikku, sehidup semati, sejak dari susuan, dalam susah +dan senang, makan sepinggan tidur sebantal.” + + Bersusah payah Ukun membujuk agar Sabari tak ma- +cam pelem India. Namun, nasib berkata lain, di majalah din- +ding kembali terpasang surat yang terketik rapi. + + Untuk kau yang bernama S, dengan dua huruf A + Usahlah jemu mengirimiku surat dan puisi + Puisimu adalah hiburan bagi sepiku di Kelumbi yang penuh de- + ngan orang-orang udik ini + Wahai S dengan dua huruf A + Sudilah menerima maafku, karena aku belum sempat membalas + puisimu + Telah kucoba menulis puisi, namun rupanya hanyalah mereka yang + disayangi Tuhan yang mampu menulis puisi + Puisi-puisimu akan menjadi utang asmaraku untukmu + 56 ~ Andrea Hirata + + Yang akan kubayar nanti, lunas, sen demi sennya + Kulihat sesekali kau melintas di muka rumahku, mencuri pandang + Aku tahu, tak dekat jarak rumahmu ke rumahku + 188 tiang listrik paling tidak + Namun, mana ada Romeo yang tak berkorban? + Julietmu, Lena + + “Buka mata kalian lebar-lebar!” Sabari membentak +Ukun, Tamat, dan Toharun. Sama sekali tak mencerminkan +kata lemah lembutnya kemarin, sahabat sehidup semati, sejak +dari susuan, dalam susah dan senang, makan sepinggan tidur +sebantal kemarin. + + “S dengan dua huruf A, es a sa beh a ba er i ri! Sabari! +Lihat baik-baik, siapa yang benar sekarang!? Aku apa kalian?!” + + “Tap, tap ...,” Ukun tergagap-gagap. + “Tapi apa?” + “Pasti kau mau bertanya soal tiang listrik itu, bukan? Ja- +ngan cemas, sudah kuhitung, tepat 188 tiang listrik!” + “Tapi, di Jalan Padat Karya, kan, belum ada listrik?” +sanggah Ukun. Jalan Padat Karya adalah lokasi rumah Sa- +bari. + “Benar, tapi hitung saja, jarak antartiang listrik rata-rata +60 meter. 60 kali 188 hasilnya 11.280, dibulatkan jadi 12.000, +dijadikan kilometer menjadi 12 kilometer, persis jarak antara +rumahku dan rumah Lena. Maaf, Boi, ini puisi, bukan berita +koran. Orang-orang kampungan yang tak bisa membaca per- + Ayah ~ 57 + +lambang macam kalian-kalian ini, takkan memahami puisi! +Ini urusan orang pintar, Boi. Pakai imajinasi!” + + Ukun dan Toharun ternganga. Tamat tak terima. + “Waspada, Ri. Kalau ternyata surat ini untuk orang lain, +kau bisa senewen.” + “Benar! Hati-hati kau. Ada istilah untuk orang macam +kau ni,” sambung Toharun. + “Apa?” + “Opsesip kumulatip!” + “Nama depan S dan dua huruf A belum tentu kau, Boi! +Kemungkinan masih sangat luas!” kata Ukun. + “Boleh jadi, boleh jadi ....” Sabari menjawab dengan te- +nang, penuh perhitungan. + “Tapi, semua sudah kuperiksa. Mari kita tinjau. Saba­ +rudin, huruf S dan dua huruf A adalah petugas kebersihan +sekolah sekaligus ustaz, tak mungkin ada main sama Lena. +Syahrani, tata usaha sekolah, perempuan. Sahari, penjaga +kantin sekolah, juga perempuan. Sya’ban, mantan suami Ha- +sanah, bekerja di pejagalan, sudah kawin lagi sama Martun. +Safarudin, guru Kimia, sudah pensiun. Syamsiar, guru Bio- +logi, galak minta ampun, tapi setia sama istri. Sahani, guru +Pendidikan Moral Pancasila, adalah umat manusia berakhlak +mulia yang mustahil main api sama murid. Safani, adik Saha- +ni, mandor pabrik sepatu sirat. Burhanadin, guru Seni Suara, +ada dua huruf A, tapi tak ada huruf S. Senyorita, nama an- +jing penjaga sekolah. + 58 ~ Andrea Hirata + + “Woeri guru Seni Lukis, lima puluh tahun umurnya, +patah hati sejak SMP, tak mau pacaran lagi. Samura, guru +Pengantar Ilmu Komputer, sudah pindah ke Kundur, cut, +paste. Mas’ud, tetangga Samura, sudah meninggal, ctrl strip +alt strip del. Sinatra, nama burung murai batu Samura, sudah +mati keracunan dedak, shut down. Abdalla Syahbana Salam, +bertaburan huruf S dan A, ketua OSIS angkatan pertama +SMA ini. Itu masa lampau, waktu Biologi masih bernama +Ilmu Hayat, Matematika masih bernama Berhitung, Fisika +masih bernama Ilmu Pasti, Geografi masih bernama Ilmu +Bumi, Kimia bernama Ilmu Zat-Zat. Tentu banyak siswa lain +bernama depan S dengan dua huruf A, dari kelas satu sampai +kelas tiga, semua sudah kuhitung, enam puluh delapan orang, +tapi semuanya bergajul! Tak bisa bikin puisi!” + + Siapa yang mengatakan Sabari obsesif ? Siapa? Itu adalah tuduh- +an yang tahu adat! + + Sabari meninggalkan Ukun, Tamat, dan Toharun yang +berdiri terpaku. Dihampirinya majalah dinding, dicopotnya +tulisan Lena itu, dilipatnya dengan tenang, lalu dibawanya +pergi. Langkahnya seperti langkah Julius Caesar usai meng- +hancurkan pasukan Germania. Satu langkah kemenangan gi- +lang-gemilang, kemenangan bagi mereka yang sabar, pantang +menyerah, berani bermimpi. + Enam + +IZMI juga melangkah dengan gagah usai menerima kembali +kertas ulangan dari guru Matematika. Ibu Guru tersenyum. +Dari tadi Bu Guru terus-menerus tersenyum untuk Izmi. Ber- +kali-kali ulangan, nilai Izmi sangat buruk kalau tak mau dise- +but memalukan sehingga dia pernah disemprot guru habis- +habisan di depan kelas. + + Jika tak benar-benar keterlaluan, Ibu Guru Matematika +sebenarnya tak gampang muntab. Wajar saja dia panas hati pa- +nas kepala melihat nilai ulangan Izmi selalu 2, paling tinggi 3. +Padahal, dia telah bersusah payah membimbing Izmi dengan +pelan dan sabar. Menghadapi Izmi, guru yang paling sabar +sekalipun pasti akan jengkel. + + “Beb ... beb ....” Hampir saja minggu lalu kata yang bi- +asa dipakai orang di geladak kapal itu dilontarkan Bu Guru +kepada Izmi. Sore itu Bu Guru diantar suaminya ke klinik. +Dia pening karena tensinya naik. + 60 ~ Andrea Hirata + + Kini Bu Guru menyesal telah menyemprot Izmi. + “Aku terlalu memerehkanmu, Izmi. Maafkan aku, Boi.” + Izmi tersenyum. + Di tempat duduknya Izmi berdebar membuka lagi lipat­ +an kertas ulangan itu. Berkali-kali diyakinkan dirinya sendiri +bahwa angka kecil yang melingkar, berperut gendut macam +cacing hamil itu adalah angka 6. Angka 6, bulat dan genap, +untuk geometri. Ah, tidaklah terlalu buruk keadaannya. + Pulang sekolah, sebagaimana biasa, Izmi berangkat ke +rumah seorang tauke, untuk mencuci dan menyetrika segu- +nung pakaian. Tak mudah mengurus pakaian tauke yang pu- +nya anak lima beserta ibu-bapak dari pihak suami dan istri. +Sebelas orang semuanya. Namun, tiba-tiba pekerjaan itu tak +terasa terlalu berat lagi bagi Izmi. Dirogohnya saku, diam- +bilnya kertas ulangan itu, diamatinya lagi, lalu dia bekerja +dengan gesit karena ingin cepat pulang, ingin segera belajar. + Kertas ulangan Matematika itu ditempel Izmi di dinding +kamar, dekat kaca. Di sampingnya ditulis nama Sabari, lalu +dia berkaca dan tersenyum. Diamatinya wajahnya, rasanya +telah lama sekali dia tak berani berkaca. + Merayu Awan + +INSYAFI, ayah Sabari, adalah pensiunan guru SD, bidang +studi Bahasa Indonesia. Dipilihnya bidang itu lantaran gemar +akan puisi. Dia memberi nama anak-anaknya dengan satu +kata sifat yang mulia dan menambahi huruf i di belakang +nama itu, agar terdengar lebih sastrawi. + + Anak pertamanya, laki-laki, dinamai Berkahi. Anak ke- +dua, perempuan, dinamai Pasrahi. Setelah lama menunggu, +terus berusaha dan berdoa, akhirnya lahirlah si bungsu, lang- +sung dinamai Sabari. + + Si bungsu itu sempat mau dinamai Tobati, tetapi nama +itu keburu diambil sepupu ibu Sabari untuk menamai anak- +nya yang baru lahir di Kampung Kelapa Lutung. Satu hal +yang kemudian disyukuri Insyafi karena sesudah besar, Tobati +itu tak berhenti berurusan dengan polisi. + + Jarak yang jauh dari abang sulung dan kakaknya, bung- +su pula, membuat Sabari menjadi anak emas. Saban malam + 62 ~ Andrea Hirata + +ayahnya bercerita untuk menidurkannya. Bukan karena Sa- +bari merengek, melainkan memang karena ayahnya senang +bercerita. Sesekali ayahnya mengucapkan kata yang tak biasa +didengar Sabari kecil, tetapi terasa indah. Sabari bertanya, +apakah yang diucapkan ayahnya itu? + + “Itulah puisi, Boi.” + “Apakah puisi itu?” + “Puisi adalah salah satu temuan manusia yang paling +indah.” + Merona-rona Sabari menatap ayahnya bergaya memba- +ca puisi. Ingin sekali dia pandai membuat puisi seperti ayah- +nya. Insyafi bahagia dapat membesarkan anaknya dengan pu- +isi dan gembira dapat menurunkan hobinya kepada anaknya. +Suatu ketika Sabari dan ayahnya duduk di beranda. + “Tahukah kau, Boi, langit adalah sebuah keluarga. Li- +hat awan yang berarak-arak itu, tak terpisahkan dari angin. +Coba, bagaimana kau dapat memisahkan awan dari angin?” +Sabari terpesona pada pertanyaan itu. + “Awan dan angin tak terpisahkan karena mereka sauda- +ra kandung. Ibu mereka adalah bulan, ayah mereka mataha- +ri. Setiap sore angin menerbangkan awan ke barat, matahari +memeluk anak-anaknya dan dunia mendapat senja yang me- +gah.” + Sabari terpukau. + “Awan adalah anak perempuan penyedih, gampang me- +nangis. Jika awan menangis, turunlah hujan. Namun, kalau +kau pandai membujuknya, ia takkan menangis.” + Ayah ~ 63 + + “Bagaimana cara membujuk awan, Ayah?” + “Nyanyikan puisi untuknya, namanya puisi merayu +awan.” Ayahnya bersenandung. + + Wahai awan + Kalau bersedih + Jangan menangis + Janganlah turunkan hujan + Karena aku mau pulang + Untukmu awan + Kan kuterbangkan layang-layang .... + + Sejak saat itu, setiap menjelang tidur, tak jemu-jemu Sa- +bari meminta ayahnya bercerita tentang keluarga langit dan +melantunkan nyanyian untuk merayu awan. Tak lama kemu- +dian Sabari kecil sudah bisa menyanyikan lagu itu. Awan sisik +Januari yang berarak-arak di atas rumah beratap rumbia itu, +diam menyimak seorang bocah bernyanyi untuknya. + +Insyafi sering sakit. Penyebabnya antara lain usia tua. Dia per- +nah kena stroke ringan. Setelah itu, dia memakai kursi roda. + + Sabari senang mengajak ayahnya jalan-jalan. Dia se- +nang mendorong kursi roda ayahnya keliling kampung, ke +pinggir padang bahkan sampai pasar, bantaran Sungai Leng- + 64 ~ Andrea Hirata + +gang, dan dermaga. Ayahnya gembira, daripada sepanjang +hari hanya diam di rumah. + + Sepanjang jalan Insyafi berkisah ini-itu, sesekali berpu- +isi. Bagi Sabari, itulah bagian paling istimewa dari ayahnya, +yakni bagian puitisnya. Banyak orang yang makin tua ma- +kin cerewet, makin temperamental, makin genit, makin ke- +kanakan. Ayah Sabari, makin puitis. + + Insyafi sendiri melihat perubahan yang aneh pada diri +Sabari beberapa waktu terakhir itu—yang dia tak tahu bahwa +semuanya bersangkut paut dengan surat untuk Sabari dari Ju- +liet-mu, Lena itu. Sore itu Sabari mendorong kursi roda ayah- +nya melintasi padang ilalang. Dia berhenti dan memandangi +ilalang yang meliuk-liuk ditiup angin. Sabari tersenyum. +Ayahnya menatap dan langsung tahu bahwa anaknya sedang +dilanda cinta. + + Tak ada lagi yang perlu diceritakan. Sabari telah diajari +ayahnya untuk membaca tanda-tanda, sebagai bagian dari +istimewanya puisi, bahwa apa yang diceritakan mata lebih te- +rang daripada apa yang diucapkan mulut. Ayahnya menatap +angkasa lalu berkata: + + Waktu dikejar + Waktu menunggu + Waktu berlari + Waktu bersembunyi + Biarkan aku mencintaimu + Dan biarkan waktu menguji + Ayah ~ 65 + + Kena singgung secara puitis, Sabari tersipu, sekaligus +kagum kepada ayahnya yang gampang terinspirasi oleh apa +saja, sekejap kemudian mencipta puisi, begitu gampang, se­ +akan ada peternakan puisi dalam mulutnya. + + Mereka sampai di pasar, melihat orang naik sepeda mo- +tor secara bergajul, tiga orang satu motor, pontang-panting +diuber polisi, ayahnya berfilosofi: + + “Segala hal dalam hidup ini terjadi tiga kali, Boi. Per- +tama lahir, kedua hidup, ketiga mati. Pertama lapar, kedua +kenyang, ketiga mati. Pertama jahat, kedua baik, ketiga mati. +Pertama benci, kedua cinta, ketiga mati. Jangan lupa mati, +Boi.” + + Anak dan ayah itu menuju dermaga, untuk menyaksikan +matahari terbenam nun di muara Sungai Lenggang. + Sayap Kecil +yang Sempat Tumbuh +Lalu Patah Lagi + +BOLEHLAH orang membuat lagu karena tak suka Senin. +Namun, Sabari tidak termasuk dalam golongan orang-orang +itu. Dia suka Senin. Senin adalah langkah awal menuju se- +gala-galanya. Senin mengandung semua kebaikan dari hari- +hari. Senin buah manis dari pohon Minggu. Senin adalah +hari yang disayangi Tuhan dan dibenci iblis, dan Senin ini +akan menjadi hari paling indah dalam hidupnya. + + Karena dia melihat surat Lena untuknya di majalah din- +ding hari Kamis, Jumat dan Sabtu dia tidak masuk sekolah +lantaran shock akibat terlalu bahagia, akhirnya Senin ini dia +akan memanen cinta dari benih yang telah lama ditaburnya. +Siapa pun, silakan iri. + + Bukan hanya itu, Sabari menjadi sangat gembira se- +hingga tubuhnya menggigil membayangkan betapa bola telah +bergulir ke arahnya sehingga dia bisa membasmi habis-habis- + Ayah ~ 67 + +an para pecundang tengik itu: Ukun, Tamat, dan si gunung +Toharun. Rasakan! + + Sabari telah berdiri tegak menunggu Lena di bawah po- +hon akasia, dekat gerbang sekolah, sejak masih gelap. Bah- +kan, penjaga sekolah belum bangun. Dia melihat matahari +terbit, mendengar anjing menggonggong dan ayam berkokok +menjelang pagi. + + Hampir dua jam menunggu, satu per satu siswa mulai +datang, lalu berbondong-bondong. Sabari gelisah sebab Lena +tak kunjung muncul. Akhirnya, lonceng masuk berdentang, +pada saat yang sama datanglah Lena, mengebut naik sepeda +menuju sekolah. Sabari berdebar-debar. + + Lima meter lebih kurang jaraknya dengan Lena, satu +jarak sopan yang dijaganya dengan teliti, di samping Sabari, +Senyorita, anjing penjaga sekolah, melakukan tindakan tak +senonoh number two. Sekilas mereka beradu pandang, semua­ +nya seperti dalam gerak lambat, tetapi Lena seakan melihat +angin saja. Seakan Sabari tak ada di situ. Sikapnya sama se- +kali tak mencerminkan kata-kata romansa dalam suratnya. +Sabari terpana, Senyorita juga. + + Jangankan Sabari, bahkan Ukun, Tamat, dan Toharun +tak habis mengerti melihat sikap Lena. Ingat benar Ukun kata +manis Lena untuk Sabari, Romeo, Juliet-mu. Namun nyatanya, +Lena masih tetaplah Lena. Boro-boro senang sama Sabari, +melirik pun tidak. + + “Jangan-jangan dia kena penyakit kepribadian ganda, +bisolar!” kata Toharun. + 68 ~ Andrea Hirata + + Sabari tersenyum pahit. Ukun menjadi iba. + “Usahlah kau risaukan, Boi,” bujuknya. + “Perempuan cantik memang suka plinplan, itu merupa- +kan bagian dari kecantikan mereka. Aku sendiri punya penga- +laman yang sama denganmu. Jadi, aku mengerti perasaanmu. +Kita senasib.” + “Pengalaman dengan siapa, Kun?” + “Siapa lagi? Shasya!” + “Pengalaman bagaimana?” + “Ya, aku bingung karena Shasya selalu plinplan. Hari +ini dia bilang tak suka padaku, esoknya bilang benci, esoknya +lagi bilang muak. Sungguh tak punya pendirian. Yang benar +yang mana?!” + +Tak tahu kopiah siapa yang pernah dilangkahi Sabari, kar- +manya lekat, sialnya bertubi-tubi. Belum usai satu kemalang- +an, disambut kemalangan lain. Waktu berjalan ke tempat +parkir sepeda, tiba-tiba seorang siswa mengadangnya. Siswa +itu tersenyum tengik sambil mencium-cium saputangan. Sa- +bari terpana karena detik itu dia langsung tahu Marlena binti +Markoni sudah diraup Bogel Leboi. + + Sabari tahu saputangan itu punya Lena, dibelinya di +kaki lima Uda Syam Robet. Sering dilihatnya saputangan itu +dipakai Lena melapisi sadel sepeda, seperti kebiasaan anak +perempuan Melayu lainnya. + Ayah ~ 69 + + Sabari pun tahu Lena pernah dikabarkan dekat dengan +Hasan, Halim, Arsya, Syamsul, Sya’ban, Wahab, Mursyid, Ju- +naidi, Munaf, Kholil, Zulfan, Razak, Ilham, Madan, Khai­rul, +Zainal, Zainul, tapi Bogel Leboi? Wahai Yang Mahatinggi, +mengapa wanita cantik senang sekali dengan lelaki bertabiat +macam setan? Sabari melihat seakan satu sepeda rebah lalu +merebahkan ratusan sepeda lainnya. Dipandanginya Lena. +Dia merasa pedih. Lena menghancurkan hatinya, Bogel Le- +boi meremukkannya. + + Sabari demam lagi, kali ini tiga hari. Dia masuk sekolah +sehari, lalu demam lagi enam hari. Lalu, terdengarlah kabar +yang mengerikan itu, bahwa Sabari mau men-dropout-kan di- +rinya sendiri. + + Kabar itu sampai ke telinga Ibu Norma. Mendidih hati- +nya, apalagi didengarnya desas-desus bahwa masalah Sabari +bersangkut paut dengan Ukun, Tamat, Toharun, dan Bogel +Leboi. Memang sudah lama dia mau menggasak para cecu- +nguk itu sekaligus. Sekali tepuk, lima nyamuk rontok. + + Mereka dipanggil Bu Norma. Di bangku panjang di ru- +ang guru mereka duduk berjajar. + + “Raskal 1, Raskal 2, Raskal 3, Raskal 4, Raskal 5,” kata +Bu Norma menunjuk mereka satu per satu. + + “Ri, kudengar kau mau keluar dari sekolah? Rencana +macam apa itu?! Kau adalah atlet yang tangguh sekaligus +pencipta puisi jempolan, satu kombinasi yang langka. Jangan- +jangan di dunia ini hanya kau yang punya kombinasi itu. Kau + 70 ~ Andrea Hirata + +siswa penuh harapan, amat berbeda dengan Ukun, Tamat, +Toharun, dan Bogel ini! Mereka ini tukang bikin onar saja!” + + Ketiga cecunguk itu mengerut. + “Coba, mana pernah aku ngasih angka sembilan untuk +Bahasa Indonesia, mana pernah!? Kecuali untuk kau, Ri!” + “Terima kasih, Bu.” + “Sebenarnya, aku ingin sekali memberimu nilai sepuluh, +Ri, tapi aku sadar, mustahil manusia mendapat angka sepuluh +untuk bahasa.” + “Terima kasih, Bu.” + “Lalu, mana pernah aku ngasih angka empat kecuali un- +tuk Ukun, Tamat, dan Toharun amit-amit ini?! Saban malam +nongkrong di warung kopi! Berleha-leha macam orang de- +wasa. Jangan-jangan sudah merokok dan minum cap monyet +segala! Tak masuk kalau dinasihati. Istilah orang Melayu, bo- +doh tak menurut, pintar tak mengajar. Orang macam itulah +kau itu, Kun! Nilai Bahasa Indonesia saja merah macam buah +saga! Patutnya kau ini dideportasi!” + Ukun menunduk. + “Kau, Mat! Susah payah ayahmu menghidupi tiga istri, +kau sangka gampang?! Seenaknya saja kau bolos. Durhaka!” + Tamat menyesal. Bu Norma menatap Bogel. + “Tak ada kerusakan di sekolah ini yang kau tak terlibat. +Corat-coret sana sini, merokok di dalam WC, merusak pot- +pot bunga, aku tahu, kau pelakunya! Brutal! Kau ini Hitler +dalam bentuk pelajar!” + Ayah ~ 71 + + Toharun membetulkan posisinya, siap disemprot Bu +Norma. + + “Kau, Run! Di mana ada dangdut, di situ ada kau! Lalu, +kau pikir ini sekolah olahraga?! Ini SMA! Kalau mau belajar +olahraga, jangan masuk sekolah, masuk tambang timah sana! +Pikullah pipa sekehendak hatimu!” + + “Tapi, Bu, nilai Matematika-ku sedikit lebih baik daripa- +da Sabari,” Toharun membela diri. + + “Nilai Pengetahuan Umum-ku juga lebih baik daripada +Sabari,” Tamat ikut-ikutan. + + “Apa katamu, Run?! Coba kutes! Kalau seratus adalah +sepuluh persennya seribu, maka seratus itu berapa persennya +empat ratus?!” + + Toharun tergagap-gagap. + “Kalau kau pintar, harusnya kau bisa menjawab dengan +cepat!” + Toharun panik, dia mencoba menghitung dengan jari- +jarinya, mulutnya komat-kamit, keringatnya bertimbulan. Sa- +bari tak tega, dia ingin membantu, tetapi tak berani. Empat +puluh lima persen! Aih, bodoh sekali! Empat puluh lima persen! + “Macam mana, Run!? Kau bilang kau pintar Matemati- +ka? Persoalan sederhana saja kau tak becus! Itulah kalau ma- +sih kecil kebanyakan diminumi air tajin!” Toharun menyerah. +Diempaskan tubuh tegapnya ke sandaran bangku. Keringat- +nya bercucuran. + “Tiga puluh persen! Itulah jawabannya kalau kau mau +tahu!” Bu Norma tersenyum puas. + 72 ~ Andrea Hirata + + Sabari bernapas lega, Untung tadi aku tak memberitahumu, +Run. + + “Sekarang kau, Mat, kau bilang Pengetahuan Umum- +mu bagus?” + + Berbeda dengan Toharun, Tamat tenang sekali. Sebab, +dia memang hobi membaca buku HPU (Himpunan Pengetahuan +Umum). + + “Terkhusus soal nama-nama kantor berita, presiden dan +perdana menteri, serta bandar-bandar udara seluruh dunia, +bolehlah kalau mau dicoba.” + + Jengkel sekali Bu Norma mendengarnya. + “O, begitu rupanya! Baiklah!” Bu Norma berpikir untuk +menemukan pertanyaan yang dapat memukul Tamat. + “Baiklah, ini pertanyaanku, Mat, siapa nama istri dikta- +tor Uganda Idi Amin?” + Senyum tengik Tamat mendadak lenyap. Dia hafal ba- +nyak nama pemimpin negara, tetapi tak pernah terpikir akan +ada orang yang menanyakan nama istri mereka. Merosot tu- +buh Tamat di bangku itu. Meski mencoba berpikir, dia tak +tahu jawabannya. + “Tak tahulah aku, Bu. Idi Aminah mungkin ...,” jawab- +nya pelan, tak yakin. + Semua Kebaikan +dari Saputangan + +MESKI sudah dinasihati Bu Norma panjang lebar, Sabari +tetap membolos. Dia tak sanggup mengatasi sakit hati kare- +na perlakuan Bogel Leboi, terutama karena perlakuan Lena. +Bagaimana dia bisa ke sekolah kalau sekolah telah menjadi +neraka? Dia bertekad meninggalkan sekolah. Bahkan, ayah- +nya tak bisa membujuknya. + + Mungkin bagi banyak orang hal itu absurd. Hanya kare- +na cinta? Namun, mengingat banyak orang di dunia ini men- +jerat leher mereka sendiri karena cinta, bolehlah tindakan +Sabari disebut konyol, tetapi tidak luar biasa. + + Ukun, Tamat, dan Toharun bermuram durja. Pedih +mereka membayangkan tak ada Sabari di sekolah. Mereka +merasa timpang. Tanpa Sabari mereka merasa tak lengkap. +Karena Ukun adalah si tukang cari gara-gara, Tamat si bi- +jaksana, Toharun si pintar pengakuan sendiri, Sabari si ko- +nyol dan lugu minta ampun, secara aneh perkongsian mereka + 74 ~ Andrea Hirata + +telah menimbulkan kombinasi perkawanan yang unik, yakni +satu orang bergantung dengan orang lainnya. Mereka seperti +empat sekawan bertualang ke pulau kaum nudis (adakah kisah +seperti itu?). + + Ukun berharap terjadi keajaiban sehingga Sabari me- +ngurungkan niatnya berhenti sekolah, dan keajaiban itu ter- +jadi. Pontang-panting Ukun naik sepeda ke rumah Sabari. +Sampai di sana napasnya tersengal-sengal. + + “Boi, cepat ke sekolah! Ada lagi surat Lena untukmu!” + Sabari yang tergeletak lemah tak berdaya di atas tempat +tidur sontak melompat. Jika tak diingatkan Ukun, hampir saja +dia ke sekolah hanya dengan celana pendek dan kaus singlet. + Di depan majalah dinding, Sabari berdiri terpaku de- +ngan wajah haru. Matanya berkaca-kaca. Berulang-ulang di- +bacanya surat itu. + + Hai kau yang bernama awal huruf S, lalu huruf A, sesudah itu +B, sesudah itu A lagi, sesudah itu R, akhirnya I. Tak ada huruf M. + + Bolehlah kita ini miskin, bodoh, jelek, pesek, tak punya dagu, te- +linga lambing, mata sayu, kening lutung, gigi tupai, kepala bola bekel, +tapi janganlah kita pernah berhenti dari sekolah. Apalah artinya kita ini +tanpa sekolah? Tak berarti, meaningless, hopeless, apes, itulah arti kita +tanpa sekolah, men sana in corpore sano, di dalam badan yang sehat +terdapat jiwa yang sehat, tetap semangat! + + Always, L + Ayah ~ 75 + + Keesokannya, pagi-pagi sekali, sebelum siswa lain da- +tang, tampak Sabari menyapu ruang olahraga dengan gesit, +meski hari itu bukan jadwal piketnya. Setelah itu, dia membu- +ka baju lalu berlari mengelilingi lapangan upacara. + + Pada pertandingan antarkelas di akhir semester, Sabari +menjadi juara maraton. + + “Men sana in corpore sano! Di dalam badan yang sehat ter- +dapat jiwa yang sehat!” pekiknya sambil mengangkat tropi +tinggi-tinggi. Tepuk tangan membahana untuknya. Yang ber- +tepuk tangan paling keras adalah Izmi. + + Hari yang menyenangkan, pulang dari sekolah, Sabari +mampir di kaki lima Uda Syam Robet dan membeli tiga sa- +putangan. Dikirimkannya kepada Lena melalui Zuraida, di- +sertai satu kartu ucapan kecil. + + Purnama Kedua Belas alias Always, L + Selamat menikmati semua kebaikan dari saputangan. + Tertanda + Satu S, dua huruf A, ada B, R, dan I + + Sabari sulit mengendalikan tangannya sendiri yang mau +menulis Romeo-mu, Sabari, sebagai penutup ucapan itu, tetapi +dia ingat kembali bahwa perempuan tak suka diburu-buru. + + Surat terakhir Lena membuat Sabari terlahir kembali. +Dihitungnya surat dari Lena untuknya, dan dia terbelalak. + 76 ~ Andrea Hirata + +Benar kata ayahnya, segala hal dalam hidup ini terjadi dalam +tiga babak! + + Sabari semakin yakin bahwa Lena bukan hanya cin- +tanya, tetapi juga nasibnya. Perempuan Kelumbi bermata +aduhai itu diturunkan dari langit memang untuknya. Itulah +hukum hidupnya, begitukah secara de jure, secara de facto, Lena +lengket sama Bogel Leboi macam nyawa lekat di badan ke- +coa. Ke sana kemari selalu berdua. Jika ngobrol, dunia punya +mereka, yang lain ngontrak. Mereka sekelas, bahkan duduk +berdekatan. Kalau tak ada yang melihat, berani mereka ber- +gandeng tangan, bayangkan itu! + + Zuraida bersabda, “Lena sendiri yang meminta pada +wali kelas agar dipindahkan ke kelas Bogel. Ada saja alasan- +nya.” + + Sabari tersenyum pahit. + “Belum pernah kulihat Lena sekasmaran itu.” + Sabari merasa seakan disiram air es. + “Tak ada omongan selain soal Bogel.” + Sabari komat-kamit. + “Kata Lena, Bogel adalah cinta pertamanya.” + Sabari panas dingin. + “Tamat SMA mereka mau ke Jakarta. Kalau orangtua +tak setuju, mereka mau kawin lari.” + Sabari menggigil. + Akan tetapi, Sabari tak surut semangat sebab dia selalu +berpegang teguh pada pesan ayahnya bahwa Tuhan selalu + Ayah ~ 77 + +menghitung, dan suatu ketika, Tuhan akan berhenti meng- +hitung. + + Malah Sabari makin rajin belajar. Apalagi, sejak kelas +Lena bersebelahan dengan kelasnya. Murid-murid lain ngan- +tuk, Sabari duduk dengan tegak, mirip prajurit mau ditanya +jatah beras oleh komandan. Telinga lambingnya berdiri, jari- +nya gesit, tak tahu apa yang dicatatnya. Tanpa diminta, bah- +kan guru belum begitu selesai mencatat, dan bukan giliran pi- +ketnya, melihat papan tulis penuh, Sabari serta-merta bangkit +untuk menghapusnya. + + Tak ada yang menunjuknya menjadi ketua kelas, dia me- +nunjuk dirinya sendiri. Tujuannya, agar dia seolah-olah men- +jadi penting. Kalau dia penting, mungkin Lena akan sedikit +melirik kepadanya. Sedikit saja, cukuplah. + + Jika guru bertanya, meski pertanyaan itu bukan untuk- +nya, tanpa peduli salah atau benar, Sabari langsung menja- +wab. Jawabannya sangat keras sehingga siswa lain yang se- +dang tidur terperanjat. Tentu semua itu dimaksudkan agar +Lena mendengarnya dari kelas sebelah. Bangunan sekolah +kampung yang hanya berdinding papan menyebabkan suara +tembus antarkelas. + + Saat itu di kelas Lena sedang pelajaran Bahasa Indone- +sia. Bu Norma melemparkan pertanyaan. + + “Kalimat majemuk!” teriak Sabari. + “Cerdas!” kata Bu Norma, tanpa menyadari bahwa ja- +waban berasal dari kelas sebelah yang tengah belajar Biologi. + 78 ~ Andrea Hirata + +Sampai usai pelajaran, Sabari disuruh guru Biologi berdiri +dengan kaki sebelah di pojok kelas, sambil menjewer telinga- +nya sendiri. Seisi keras terpingkal-pingkal melihatnya. + + Begitu juga jika bertanya. Kerap pertanyaan Sabari tak +masuk akal, tak berhubungan dengan pelajaran, pokoknya +bertanya. Semuanya agar didengar Lena. Waktu itu guru +Fisika menjelaskan teori sifat bayangan pada cermin datar, +cekung, dan cembung serta segala hitungan runyam sudut- +sudut pantul, yang membuat siswa tampak hilang dalam tem- +pat dan waktu. Semakin dalam guru menjelaskan, semakin +banyak murid yang bingung, termasuk Sabari, tetapi di te- +ngah kebingungan itu dia menunjuk. + + “Saya mau bertanya, Pak!” Lantang sekali suara Sabari. + “Silakan, Ri.” + “Apakah Bapak pernah menonton pelem Perempuan Beram- +but Api?!” + Dan, terdengarlah auman yang dahsyat. + “Keluaaaaaarrr!!!” + Rahasia + +BERBISIK Izmi di telinga Zuraida, yang dibisikkannya +adalah sebuah rahasia untuk disampaikan kepada Sabari. +Namun, tak semudah itu, kata Izmi, yaitu Sabari tak boleh +tahu bahwa informasi itu berasal darinya. Zuraida diam me- +nyimak. Rahasia itu ternyata soal Izmi tahu siapa yang suka +mengikat rantai sepeda Sabari dengan tali rafia. Dia juga +tahu siapa yang menyangkutkan sepeda Sabari di puncak ti- +ang bendera tempo hari, dan tahu siapa yang menulis Sabari +gigi tupai, Sabari majenun, Sabari monyet di dinding toilet sekolah. + + “Bogel Leboi!” bisik Izmi serius. Zuraida biasa saja. Izmi +heran. + + “Mengapa kau tak terkejut, Rai? Harusnya kau terkejut! +Kecewa aku!” + + Dengan tenang Zuraida berkata bahwa tanpa diberi +tahu pun, Sabari sudah tahu bahwa semua itu kelakuan Bogel +Leboi dan sekongkol-sekongkolnya. + 80 ~ Andrea Hirata + + Bogel sering mengejek puisi-puisi Sabari, sambil me- +main-mainkan korek gas Zippo, dipanggilnya Sabari majenun +alias gila. Bogel jengkel karena Sabari tak pernah terpancing. +Ditariknya kerah baju Sabari, ditantangnya berkelahi. Sabari +tak melawan, hanya tersenyum, karena dia takkan meren- +dahkan dirinya sendiri dengan menggunakan mulutnya un- +tuk memaki dan takkan menghinakan dirinya sendiri dengan +menggunakan tangannya untuk memukul. Bagi Sabari, Bogel +dan kawan-kawan hanya sedang menjadi anak SMA. Sama +sekali tak dihiraukannya hal yang tak penting itu. + + Pernah Bogel menggemboskan ban sepedanya sehing- +ga dia harus pulang menuntun sepeda itu, padahal jarak dari +sekolah ke rumahnya hampir dua puluh kilometer. Dilewati­ +nya padang ilalang yang tengah berbunga. Warna putih ter- +bentang bak hamparan kabut. Sabari masuk ke padang ila- +lang yang meliuk-liuk ditiup angin. Dipejamkannya mata, +dibentangkannya tangan, lalu dia meliuk-liukkan tubuhnya +mengikuti gelombang ilalang. Terbayang wajah seorang anak +perempuan yang merampas lembar jawaban ujian Bahasa +Indonesia-­nya itu, Sabari merasa terbang. + + Izmi kagum kepada Sabari karena tak pernah membalas +Bogel. Dia makin kagum ketika membandingkan keduanya. +Bogel punya segalanya, keluarga mampu, kawan banyak, ber- +wajah menarik, flamboyan, populer, trendi, lumayan pintar. +Banyak siswa ingin sepertinya, tetapi di mata Izmi, Bogel tam- +pak selalu ingin menjadi orang lain. Sabari adalah kebalikan + Ayah ~ 81 + +dari semua kelebihan Bogel, dan tampak bangga menjadi di- +rinya sendiri. + + “Boi, coba kau tanyakan pada Sabari, apa cita-citanya?” + “Baiklah.” + Zuraida kemudian menyampaikan kepada Izmi bahwa +Sabari mau menjadi guru Bahasa Indonesia seperti ayahnya. +Izmi tercenung, dia ingat akan cita-citanya dulu ingin menja- +di dokter hewan, tetapi sejak ayahnya diciduk polisi gara-gara +korupsi, cita-citanya pingsan. + “Guru Sabari, pantas nian kedengarannya,” kata Ukun +di warung kopi Usah Kau Kenang Lagi. + “Kau? Apa cita-citamu, Mat?” tanya Ukun. + “Aku mau menjadi pilot.” + “Kau sendiri, Kun?” + “Aku mau menjadi dokter.” Jawaban yang mantap. + “Kau, Run?” + “Aku mau menjadi Menteri Olahraga Republik Indone- +sia!” jawab Toharun. + +Izmi ingin mengatakan cita-citanya kepada siapa saja, tetapi +ada belasan siswa yang diperkirakan tidak naik ke kelas dua, +salah satunya dia. + + Maka, saat pembagian rapor kenaikan kelas, dia gugup +bukan main. Memang sudah lumayan kemajuannya dalam + 82 ~ Andrea Hirata + +ulangan, tetapi rapor semester 1-nya sangat jatuh. Terperosok +nun jauh ke dasar sana. Angka merahnya ada delapan. Ka- +laupun angka merah itu berkurang setengah, menjadi empat, +dia tetap takkan naik kelas. Karena batas minimum untuk +naik kelas adalah tiga angka merah. Dan, rasanya mustahil +bisa mengurangi delapan angka merah menjadi tiga. Sering +Izmi melamun, seandainya dia mengenal Sabari lebih awal, +tentu keadaannya takkan segawat sekarang. Mengapa orang- +orang yang tepat selalu datang terlambat? + + Wali kelas membagikan rapor, sesekali tajam menatap +Izmi. Firasat buruk melanda pelajar sekaligus pembantu ru- +mah tangga paruh waktu itu. Nama dipanggil satu per satu, +kawan-kawannya menerima rapor, keluar dari kelas lalu ber- +sorak gembira. Dada Izmi sesak. + + Izmi tak langsung membuka rapornya. Dia menunggu +seluruh siswa pulang. Dia sudah punya rencana, jika angka +merah di rapornya ada empat atau lebih, yang berarti dia +tak naik kelas, dia akan langsung pulang, sampai di jembatan +akan dilemparkan rapor itu ke Sungai Lenggang. Keesokan- +nya dia takkan kembali ke sekolah. + + Izmi menyingkir ke bawah pohon bantan. Dilihatnya se- +keliling, tak ada siapa-siapa, dibukanya rapor itu pelan-pelan, +jantungnya berdebar. Matanya dengan cepat mendeteksi ang- +ka merah dan dia terkejut. Memang ada angka merah, teta- +pi hanya tiga, Matematika 3, Fisika 3, Kimia 3,5. Izmi naik +kelas. + Geometri + +SESEKALI, jika dilanda rindu, Sabari memanfaatkan satu- +satunya kesempatan untuk menemui Lena, yaitu usai jam se- +kolah. Semua siswa sudah pulang, diam-diam dia masuk ke +kelas sebelah dan berjumpa dengan Lena, walaupun hanya +dalam bentuk bangkunya yang kosong. Sabari duduk di bang- +ku itu dan tertegun dilanda perasaan indah tak terperi. Dia +melamun, merenung, berkhayal, tersenyum, tertawa, semua- +nya sendirian. + + Suatu ketika, saat duduk di bangku itu dan menunduk +untuk membetulkan tali sepatu, dia terkejut melihat rumus +matematika berderet di bagian bawah laci meja Lena dan laci +meja Bogel Leboi di sebelahnya. Kedua sejoli itu pasti telah +bersekongkol untuk menyontek pada ujian antarsemester se- +bentar lagi. Sungguh romantis. Sabari cemburu. + + Soal Lena tukang sontek kelas kakap sudah menjadi ra- +hasia umum di SMA. Sabari sendiri punya pengalaman pri- + 84 ~ Andrea Hirata + +badi atas sepak terjangnya saat ujian masuk SMA dulu. Na- +mun, karena itulah dia menemukan Lena, sesuatu yang tak +pernah berhenti disyukurinya. + + Sabari tersenyum geli lagi melihat rumus sontekan volu- +me kerucut itu. Dia tak terlalu pintar Matematika, tetapi dia +tahu ada yang salah dengan rumus itu. Seingat Sabari notasi +tinggi atau t dalam rumus itu harusnya dipangkatkan dua. + + Keesokannya dia bertanya kepada Toharun, yang ni- +lai Matematika-nya memang selalu lebih baik daripadanya. +Toharun membenarkan pendapat Sabari. Usai jam sekolah, +Sabari menyelinap lagi ke dalam kelas Lena. Ditambahinya +angka dua di atas notasi t sehingga rumus itu menjadi benar. +Sebelum pulang, diusap-usapnya rumus itu disertai harapan +semoga Lena dan Bogel Leboi sukses dalam ujian nanti. + +Ujian semester 5 adalah ujian yang penting sebab itulah uji- +an semester kedua terakhir sebelum siswa mengkhatamkan +SMA. Dan, tak terbilang girangnya Sabari sebab sebagian +besar soal geometri adalah tentang kerucut dan berbagai im- +plikasi rumusnya. Begitu soal dibagikan, sebagian murid ber- +teriak, bahkan histeris, karena tak menduga soal akan begitu. +Kerucut adalah topik kelas dua dulu. Yang terkecoh itu ter- +masuk Ukun, Tamat, dan Toharun. + + Sabari sendiri bersiul-siul tanpa suara. Dia bahagia bu- +kan hanya karena telah mendalami rumus kerucut—dan itu + Ayah ~ 85 + +terinspirasi sontekan Lena—Ah, Always, L, dan seluruh kebaikan +yang dibawanya—melainkan juga senang karena telah mem- +perbaiki rumus volume kerucut sontekan Lena itu. Satu perto- +longan kecil penuh rahasia yang mengandung nilai romansa. + + Dibayangkannya betapa sentosanya Lena dan Bogel Le- +boi di kelas sebelah menyontek rumus volume kerucut yang +benar itu. Sejahteralah mereka. Dibayangkannya kedua sejoli +itu terkikik mesra. Dia cemburu, tetapi bahagia untuk me­ +reka. + + Akan tetapi, di tengah kegembiraan itu, saat menulis ru- +mus volume kerucut di kertas jawabannya sendiri, Sabari ter- +cenung lalu panik karena mendadak dia sadar bahwa notasi +t pada rumus volume kerucut memang tidak dipangkatkan +dua. Dengan kata lain, rumus sontekan Lena itu sesungguh- +nya sudah benar, dibetulkannya malah menjadi salah. + + Ingin Sabari melompat lalu berlari ke kelas sebelah un- +tuk memberi tahu Lena, tetapi semuanya telah terlambat. +Apalagi, kemudian beberapa siswa dari kelas sebelah, terma- +suk Lena dan Bogel, telah keluar sambil tertawa-tawa karena +telah selesai mengerjakan soal dengan sukses. Sabari berkeri- +ngat dingin. + + Alhasil, ketika hasil ujian geometri diumumkan, nilai +Lena bebek berenang, atau 2. Nilai Ali Mahmud alias Bogel +Leboi juga bebek berenang. Nilai Ukun, bangku terbalik. Ni- +lai Tamat, bangku terbalik alias 4 koma bebek berenang. Nilai +Toharun, bebek berenang koma bebek berenang. + Amiru +dan Sepedanya + +AMIRU melamun menatap kantor pegadaian. Dadanya se- +sak membayangkan Mister Phillip, radio ayahnya, berada di +dalam kantor itu. Dia gundah mendengar orang bergunjing +bahwa acara yang mereka tunggu-tunggu itu, dan pasti di- +tunggu ayahnya juga, akan segera mengudara. + + “Tunggu saja, tak tahu esok, tak tahu lusa, minggu de- +pan atau bulan depan, pasang antena tinggi-tinggi, kunci ge- +lombang di RRI, jangan digeser, apa pun yang terjadi,” kata +Syarif Miskin. + + Saban malam Amiru susah tidur karena kesepian, tak +ada lagi bunyi kemerosok gelombang radio. Dia sedih kare- +na ayahnya telah kehilangan hiburan satu-satunya. Otaknya +berputar cepat dan sekonyong-konyong semangatnya mele- +tup. Dia seakan baru menemukan resolusi hidupnya, yaitu dia +ingin bekerja keras untuk mencari uang. Uang yang didapat- +nya bukan hanya untuk menebus radio ayahnya, melainkan + Ayah ~ 87 + +juga agar ibunya mendapat perawatan kesehatan yang lebih +baik. Diam-diam dia melihat kuitansi pegadaian yang diletak- +kan ayahnya di atas meja. Satu juta enam ratus ribu, itulah nilai +gadai Mister Phillip. + + Pulang dari sekolah esoknya, tak ambil tempo, naik se- +peda, Amiru segera berangkat ke pabrik tali rami. Dia masuk +kantor dan langsung bilang mau kerja. + + “Kerja apa?” tanya mandor. + “Apa saja, Pak.” + “Berapa umurmu?” + “Sepuluh, masuk sebelas tahun.” + “Masih sekolah?” + “Masih.” + “SD?” + “Ya.” + “Mengapa kau mau bekerja?” + “Untuk dapat uang agar dapat menebus radio ayahku di +kantor gadai dan untuk biaya ibuku berobat.” + Setelah setengah jam diceramahi mandor, Amiru disu- +ruh pulang. + Sesungguhnya, meski masih kecil, keadaan yang sulit +membuat Amiru tak asing dengan pekerjaan berat. Libur se- +kolah dia biasa bekerja musiman di perkebunan karet, kopi, +atau kepala sawit. Namun, dia harus mendapatkan uang de- +ngan cepat sebab dia mengejar siaran radio yang jadwalnya +semakin dekat. + 88 ~ Andrea Hirata + + “Saya mampu bekerja keras, Bu, sama seperti orang de- +wasa,” kata Amiru waktu melamar di pabrik obat nyamuk. + + “Risiko besar, Bujang, tak baik untuk anak kecil. Pekerja- +an itu berurusan dengan bahan kimia berbahaya.” + + “Aku sanggup menanggung risiko, Bu.” + “Aku tahu kau sanggup, tapi aku tidak sanggup.” + Ibu memberi Amiru ongkos pulang, Amiru menolak de- +ngan sopan. + Ternyata, tak mudah mencari pekerjaan meski hanya +ingin menjadi kuli. Amiru gelisah, kurang dari 47 hari dia ha- +rus sudah mengumpulkan uang minimal satu juta enam ratus +ribu rupiah untuk menebus radio ayahnya di kantor gadai, +kalau tidak, ayahnya akan melewatkan siaran radio itu. + Dicarinya pekerjaan yang orang hanya peduli pada te- +naga. Ditemukannya jabatan itu, kuli panggul di pasar. Na- +mun sayang, orang lebih suka kuli panggul berbadan besar. +Jika Amiru menawarkan diri, orang-orang tak tega melihat +tubuhnya yang kecil dan kurus. Akibatnya, Amiru tak laku. +Siaran radio itu tinggal 38 hari. + Amiru mutasi ke tugas kebersihan pasar karena upahnya +berdasarkan banyaknya pekerjaan, tetapi segera dia berhenti, +bukan karena pekerjaan itu keras dan jorok atau karena ha- +rus memikul keranjang sampah, melainkan karena berdasar- +kan perhitungannya, upah harian itu takkan mencapai sejuta +enam ratus ribu sampai batas waktu siaran radio. + Gelisah, hampir putus asa, ke sana kemari anak kecil itu +menawarkan diri, tetapi pintu tertutup untuknya. Dalam ke- + Ayah ~ 89 + +kecewaan yang dalam, dia berdoa dan terkabul. Di dinding +kantor dinas pasar dilihatnya pengumuman lomba balap se- +peda di ibu kota kabupaten. + + Amiru melonjak melihat hadiah ketiga untuk tingkat +remaja saja masing-masing lima juta rupiah. Itu jauh lebih +besar daripada yang diperlukannya untuk menebus radio, +bahkan tersisa banyak untuk biaya pengobatan ibunya. Ma- +laikat-malaikat turun untuk melihat niat yang baik, begitu +ayahnya selalu berkata. Perkataan itu benar. Amiru terharu. + + Hal lain yang membuat Amiru girang bukan hanya jum- +lah hadiahnya, melainkan dia juga yakin akan menang, pa- +ling tidak juara ketiga di tangan. Alasannya masuk akal, dia +terbiasa bekerja keras karena itu tenaganya jauh lebih besar +daripada rata-rata anak berusia sebelas tahun. Dia terbiasa +membantu ayahnya, mencari lalu membonceng kayu bakar, +paling tidak tiga puluh kilogram beratnya. Libur sekolah dia +bekerja menggerus pohon karet, bersepeda enam puluh ki- +lometer dari rumahnya, berarti 120 kilometer pergi pulang, +setiap hari. Dalam balap sepeda sesama anak kampung, dia +selalu meninggalkan kawan-kawannya jauh di belakang. Ba- +lap sepeda bukan barang baru baginya. + + Setiap hari Amiru berlatih keras, tak kenal lelah. Dia +menaiki tanjakan sambil membonceng kedua adiknya sekali- +gus. Amirta dan Amirna bersorak-sorak menyemangati sang +abang. Lain waktu Amiru membonceng ayah dan kedua adik- +nya. Ayah di boncengan belakang, si bungsu Amirna digen- +dong Ayah, si tengah Amirta duduk di bagian tengah sepeda. + 90 ~ Andrea Hirata + + Orang-orang di pasar sering terkejut melihat anak kecil +bersepeda dengan sangat cepat, bersiut-siut secepat angin se- +latan. Begitu cepat sehingga lepas kancing-kancing bajunya. +Bajunya berkibar-kibar. + +Pada hari perlombaan, Amiru minta izin kepada ayah dan +ibunya untuk mengajak adik-adiknya jalan-jalan ke ibu kota +kabupaten. Sebelum berangkat, dia mencium tangan ibunya +lama sekali. + + “Usahlah risau, Ibu, aku akan segera mengirim Ibu un- +tuk berobat di rumah sakit terbaik di ibu kota provinsi. Ada +dokter dan perawat khusus untuk Ibu. Setiap tiga puluh menit +perawat datang untuk melihat keadaan Ibu.” Ibunya tergelak +melihat Amiru bertingkah meniru suster dengan menempel- +kan tangan di kening ibunya. + + “Suhu, pernapasan, detak jantung, semua diperiksa. Ka- +mar Ibu nanti tidak panas karena ada AC. Ada juga meja de- +ngan vas bunga di samping tempat tidur Ibu nanti. Bunganya +akan kuganti setiap hari. Bunga ros, kan? Bunga kesayangan +Ibu, segar berair-air. Tak banyak orang di dalam kamar itu, +hanya Ibu sendiri. Tak ada orang membawa tikar, selimut, +termos, obat nyamuk, dan rantang macam kita lihat di rumah +sakit dulu. Ibu tenang saja, tunggu aku pulang, nanti malam +kita akan mendengar sandiwara radio Menantu Durhaka. Oke?” + Ayah ~ 91 + +Amiru tersenyum lebar, ibunya mengernyitkan dahi. Dia tak +paham sedikit pun apa yang dibicarakan anak lelakinya itu. + + Amiru minta diri lalu membonceng kedua adiknya naik +sepeda. Mereka bersepeda dengan riang gembira. Adik-adik +perempuannya berkicau-kicau, Amiru bernyanyi-nyanyi. Ini +adalah hari yang sangat menyenangkan. Kepada adik-adiknya +Amiru mengatakan bahwa dia akan ikut lomba balap sepeda. + + Mereka sampai di pusat kota. Dekat garis finis ada tem- +pat-tempat duduk. Amiru meminta adik-adiknya menunggu- +nya di situ. Amirta sudah bisa menjaga adiknya. Amiru mem- +beli bendera kecil. Amirta dan Amirna siap dengan bendera +kecil yang akan dikibar-kibarkan jika abangnya menjadi juara +nanti. + + Jika semuanya berjalan dengan baik, rencana Amiru +adalah, segera setelah menerima hadiah uang itu, dia akan +mengajak adik-adiknya menebus radio ke kantor gadai yang +tak jauh dari situ, setelah itu, sisa uang hadiah akan dipakai- +nya untuk membelikan adik-adiknya buku-buku dan mainan, +sisanya yang masih banyak untuk biaya pengobatan ibunya. +Dia pun akan pulang membawa kejutan untuk ayahnya. Be- +tapa manisnya rencana itu. Tak sabar Amiru mau memacu +sepedanya agar segera memenangkan lomba. + + Dia menuju garis start. Lima belas kilometer dari garis +finis tadi. Sampai di sana dia terkejut melihat begitu banyak +orang telah berkumpul di lokasi start. Ratusan pembalap re- +maja dan dewasa ada di sana, berwarna-warni meriah. Mere- + 92 ~ Andrea Hirata + +ka berkacamata, mengenakan helm khusus, mengenakan sa- +rung tangan, sepatu khusus juga, dan kostum pas badan yang +mentereng. + + Sepeda mereka adalah sepeda balap modern. Amiru se- +gera sadar bahwa dia hanya mengenakan sandal dan kemeja +biasa, dan sepedanya adalah sepeda kampung karatan yang +biasa dipakai untuk membawa kayu bakar. + + Amiru melihat sekeliling. Hanya dia sendiri yang berse- +peda seperti itu. Tibalah gilirannya, tetapi dia ragu mendekat +ke meja pendaftaran. Pembalap lain ingin cepat-cepat, dia +minggir. + + Amiru menatap para pembalap yang mengambil nomor +lomba. Setelah agak sepi, dia memberanikan diri untuk men- +daftar karena dia harus menebus radio ayahnya, dia memer- +lukan biaya untuk ibunya, lagi pula adik-adiknya menunggu- +nya di garis finis. + + Akan tetapi, yang dicemaskannya terjadi. Panitia tak +mengizinkannya ikut lomba sebab dia tak memenuhi syarat. +Amiru menuntun sepedanya, menjauh dari meja pendaftar- +an. Dia tersandar lesu di bawah pohon akasia sambil meme- +gangi sepedanya. Dalam pemikirannya, lomba balap sepeda +adalah lomba paling cepat naik sepeda. Siapa yang paling +cepat, selama sepedanya tidak pakai mesin, dialah juara. Na- +mun, rupanya dalam zaman modern ini, perlombaan olahra- +ga tidaklah sesederhana itu. + + Amiru terperanjat mendengar bunyi letusan. Dilihatnya +ratusan pembalap berlomba-lomba. Sejurus kemudian mere- + Ayah ~ 93 + +ka berkelebat dengan cepat, bak warna-warni yang disembur- +kan. Semangat Amiru meletup, ingin sekali dia berlomba me- +lawan mereka. Dia telah berlatih dengan keras, dia lebih dari +siap untuk bertarung. Namun, panitia tak membolehkannya. +Kakinya gemetar menahan perasaannya. + + Dalam waktu singkat lokasi start menjadi sepi. Orang- +orang bergegas menuju pusat kota untuk melihat para juara. +Amiru teringat kepada adik-adiknya. Dia pun berangkat ke +pusat kota. Dari jauh dia melihat adik-adiknya duduk me- +nunggu. Temangu-mangu memegangi bendera. + + Amiru menaikkan adik-adiknya ke boncengan sepeda. +Mereka pulang. Sepanjang jalan Amirta dan Amirna mengi- +bar-ngibarkan bendera kecil itu. Mereka melewati kantor pe- +gadaian. Pintu-pintunya sudah ditutup. + Terima Kasih + +KEPADA Ukun, Sabari bilang betapa dia menyesal atas insi- +den rumus kerucut itu. Dari cara mengatakannya, Ukun tahu +Sabari benar-benar menyesal. + + “Aku mau menebus kesalahanku.” + “Pada Lena dan Bogel?” + “Ya.” + “Bogel juga?!” + “Ya.” + “Ri! Kalau kau minta maaf sama Lena, aku maklum, +tapi sama Bogel?! Dia adalah manusia paling kejam padamu +di dunia ini!” + “Tapi, ini kesalahanku, Boi.” + Ukun mengaduk-aduk rambutnya. + Sabari mau minta maaf secara langsung kepada Lena, +tetapi takut kena semprot, Maaf ?! Enak saja kau bilang maaf, bi- + Ayah ~ 95 + +cara murah! Mulut tak nyewa! Yang tak lulus aku! Bukan kau! Ma- +jenun! Belum menghitung muntab-nya Bogel. + + “Bisa-bisa kau dibumihanguskan Leboi pakai korek gas +Zippo-nya,” kata Tamat. + + Mereka membicarakan hal itu di warung kopi Kutunggu +Jandamu. Saat itu radio di warung kopi sedang seru menyiar- +kan acara baru yang sangat diminati pendengar, yaitu pertun- +jukan organ tunggal langsung dari stasiun radio. + + Pemilik radio lokal itu paham budaya bahwa orang Me- +layu kampung umumnya berjiwa seni, selalu ingin tampil, +tetapi banyak yang malu-malu. Maka, jika ada kesempatan +memperdengarkan kebolehan pada dunia, tanpa harus de- +mam panggung atau dilempari penonton pakai sandal, itu +adalah kesempatan emas. + + Maka, setiap malam Minggu ramai orang antre di sta- +siun radio. Pria, wanita, tua, muda, penganggur, PNS, guru, +siswa, semua ingin bernyanyi lagu apa saja, lagu Melayu, +dangdut, rock, pop, lagu Barat, lagu India, kasidah, sambil +berkirim salam untuk kawan, kenalan, dan sanak saudara. +Betapa menyenangkan. Pakaian mereka necis seperti mau +naik panggung meski tak ada penontonnya, itulah kesempat- +an menjadi artis! + + Ukun menyarankan agar Sabari minta maaf kepada +Lena dan Bogel secara terbuka sekaligus mempersembahkan +sebuah lagu untuk Lena melalui acara organ tunggal live show +radio itu. + 96 ~ Andrea Hirata + + “Ide yang brilian!” kata Toharun. Sebab, dia pernah ikut +acara itu. Lagu pilihannya adalah lagu India. Gara-gara itu +dia dapat kenalan seorang perempuan hitam manis dari Gual. + + “Dan, aku tahu lagu kesayangan Lena, ‘Truly’ by Lionel +Ritchie, sedang top sekarang!” Tamat menyemangati. + + Sabari terperanjat. + “Yang benar saja, kau tahu aku tak bisa bernyanyi. Ber- +puisi mungkin aku bisa, tapi bernyanyi? Tak mungkin itu, bi- +cara saja aku sumbang.” + “Di situlah seninya,” kata Ukun. + “Aku pun tahu lagu ‘Truly’ itu, aduh, nadanya tinggi se- +kali, lebih tinggi daripada tiang bendera di kantor bupati!” + “Di situlah seninya,” kata Ukun lagi. + “Permohonan maaf secara terbuka adalah sikap yang +gentleman. Bahwa kau tak bisa bernyanyi, semua orang tahu +itu. Bicara saja kau sumbang, apalagi bernyanyi. Namun, kau +yang tak bisa bernyanyi, berusaha keras untuk bernyanyi de- +ngan baik, meski suaramu macam radio rusak, dan semua itu +demi minta maaf pada Lena, betapa tulus dan manisnya. Pas- +ti Lena terkesan!” Tamat meyakinkan. + Demi mendengar kata Lena terkesan, membawakan lagu +yang biasa dibawakan Luciano Pavarotti sekalipun Sabari +siap. + “Cerdas sekali pandangan saudara kita Tamat ini,” kata +Ukun. + Sabari menjadi yakin, ditambah lagi pengalaman kesuk- +sesan Toharun. Tamat belum selesai. + Ayah ~ 97 + + “Lagi pula, dengarlah liriknya, Ri, and forever I will be your +lover, dan selamanya aku akan menjadi kekasihmu ..., amboi.” + + Wajah Sabari merona-rona, blushed, istilah masa kini. + +Sebulan penuh Sabari berlatih. Agar tak mengganggu tetang- +ga, dia berlatih di pinggir laut. Lolongannya lindap ditelan +debur ombak Laut Jawa. + + Akhirnya, tibalah malam Minggu yang ditunggu-tunggu +itu. Tak mau kalah dengan peserta lain, Sabari berdandan +seronok. Dia mengantre di stasiun radio sejak pukul 19.30, +setelah lima belas peserta, tibalah gilirannya. Prime time. + + Penyiar memintanya bersiap-siap. Sabari mendekatkan +mulut ke mik. Dia gugup karena tahu seisi kampung akan +mendengar suaranya. + + “Siap?” + “Insya Allah, Bang.” + Ngeng, lampu merah bertulisan on air menyala. Penyiar +menyapa pendengar lalu menyapa Sabari. + “Jangan lupa kata kuncinya,” kata penyiar. + “DYSMDB.” + Grrr, tawa berderai dari sound effect. + “Ah, bukan itu maksudnya.” + “Oh, maaf, Bang, Radio Suara Cinta, ya suaranya, ya +cintanya.” + 98 ~ Andrea Hirata + + Grrr, ditambah efek tepuk tangan dan suitan. + “Ngomong-ngomong, apakah DYSMDB itu?” + “Itu nama sandiku, Bang.” + “Artinya? Kalau boleh tahu.” + “Dia yang selalu menunggu dengan berdebar-debar.” + Grrr. + “Nama Saudara, kalau boleh tahu?” + “Sabari, Bang.” + Lena yang sedang bersisir terpana. Dia selalu mendapat +kiriman lagu dari DYSMDB, dan selalu bertanya-tanya, sia- +pakah DYSMDB itu? Ternyata, Sabari gigi tupai! + “Kepada siapa lagu Bung akan dikirimkan? Kalau boleh +tahu.” + “Terkhusus untuk Saudari Marlena di Kelumbi dan +Saudara Bogel Leboi disertai satu permintaan maaf.” + “Oh, mengapa minta maaf ?” + “Karena satu kesalahan, Bang. Waktu itu aku membe- +tulkan sontekan rumus matematika Saudari Marlena dan +Saudara Bogel yang mereka tulis di bawah meja, ternyata ku- +betulkan malah salah, jadi Saudari Marlena mendapat nilai +dua.” + Grrrrrr, Lena terperangah, dibanting sisir di tangannya. +Bu Norma ternganga, guru Matematika terbelalak. + “Bagaimana dengan nilai Saudara Bogel Leboi, kalau +boleh tahu?” + “Dua juga.” + Ayah ~ 99 + + Grrrrrrrrr. Bogel membanting rokok. “Majenun!” + “Ojeh, ojeh, jadi Bung akan menyanyikan lagu ‘Truly’?” + “Benar, Bang.” + “Maksud Bung, ‘Truly’ dari Lionel Ritchie?” Penyiar +mengamati Sabari. Dia ragu karena tak ada sedikit pun bagi- +an dari Sabari yang cocok dengan bahasa Inggris. + “Tak lebih tak kurang, Bang.” + “Yakin?” + “Yakin.” + “Apakah Bung sudah berlatih? Kalau boleh tahu.” + “Sudah, Bang.” + “Berapa lama Bung berlatih? Mungkin para Pujangga +Cinta di seluruh penjuru Belitong ingin tahu.” + Pujangga Cinta, begitu panggilan untuk para pendengar. + “Hampir dua bulan.” + “Oh, cukup lama, tentu Bung sudah lihai membawakan- +nya.” + “Sila dicoba, Bang.” + Ukun, Tamat, Toharun, Zuraida, dan Izmi bertepuk ta- +ngan. + “Bagaimana, Bung organ tunggal, siap?” + Pemain organ tunggal memberi kode siap dengan jari- +nya. + “Ojeh, Ojeh, Pujangga Cinta, di mana pun Anda ber­ +ada, sambutlah suara emas Sabariii ....” + Satu, dua, tiga, empat, pemain organ tunggal menghi- +tung, berdenting bunyi piano, lalu masuklah suara Sabari, + 100 ~ Andrea Hirata + +agak terlambat, tetapi tak apa-apa. Lagu itu amat syahdu di +bagian depan, Sabari menyanyikannya dengan gaya campur- +an orang berdoa, menggerutu, dan beserdawa. + + Lolos dari bagian depan, Sabari bersiap-siap masuk ke +bagian yang paling dramatis, reffrain. Diambilnya ancang- +ancang, digenggamnya tangannya kuat-kuat, lalu dilolong- +kannya trulyyy .... Suaranya berubah dari orang menggerutu +menjadi anjing melolong melihat iblis. Dia begitu terpaku +pada usaha kerasnya mencapai nada tinggi, yang kenyataan- +nya dia tak sampai, yang berakibat nyanyiannya kacau balau. +Musik ke selatan, suaranya ke utara. Para pendengar terpana +kalau tak tertawa. Tukang nasi goreng menghentikan goreng- +annya, penjaga malam ternganga mulutnya, para penjaga +toko prihatin, para pengunjung warung kopi terpingkal-ping- +kal. + + Celaka bagi Sabari sebab lagu “Truly” mengandung +dua tingkat reffrain, modulasi, tingkat kedua lebih tinggi lagi. +Kejam sekali. Tak tahu apa yang ada dalam pikiran Mister +Ritchie. Menghadapi tingkat kedua itu, Sabari mengumpul- +kan tenaga dalam lalu ngegas sejadi-jadinya. Suara anjing +melolong berubah menjadi kucing kena cekik. Peserta lain +yang tengah mengantre dan para pendengar, termasuk Ukun, +Tamat, Toharun, Zuraida, dan Izmi, terbahak-bahak sambil +memegangi perut mereka. + + Tanpa tahu bagaimana lagu itu telah dimulai, tahu-tahu +lagu itu sudah selesai. Sabari bernyanyi dengan awal seolah + Ayah ~ 101 + +tak sengaja, lalu mengakhirinya dengan sukarela. Namun, +tanpa peduli bagaimana penampilan Sabari, operator radio +tetap mengudarakan efek tawa yang meriah grrrrrr disertai ge- +legar tepuk tangan dan suitan-suitan panjang. + + Sabari tersenyum puas dan bertepuk tangan, untuk diri- +nya sendiri. Ditatapnya penyiar lalu dikeluarkannya sepucuk +kertas dari sakunya. + + “Maaf, Bang, bolehkah aku menyampaikan sedikit +ucapan terima kasih kepada beberapa pihak yang telah berja- +sa dan akan berjasa dalam hidupku? Jarang-jarang aku men- +dapat kesempatan ini.” + + “Oh, sudah barang tentu, Bung, silakan.” + “Terima kasih banyak, Bang.” + Sabari mendekatkan mulutnya ke mik, dibukanya lipat­an +kertas tadi lalu diucapkannya ribuan terima kasih pada peme- +rintah, pemilik radio, penyiar, operator, dan para pendengar +yang budiman di mana pun berada, terutama kepada Lena +dan Bogel Leboi serta mereka yang selalu mendukungnya, +yaitu ayahnya tercinta, ibunya yang penyayang dan sedang +sakit—teriring ucapan agar cepat sembuh—saudara-saudara +kandung, bibi, paman, ipar, para sepupu, dua pupu, saudara +tiri, keponakan, tetangga, dan tentu Ukun, Tamat, Toharun, +dan Zuraida. + Ribuan terima kasih juga ditujukan kepada wali kelas, +Bu Norma, segenap gurunya, mulai dari SD sampai SMA, se- +genap kawan sekelas, ketua OSIS, orangtua-orangtua murid, + 102 ~ Andrea Hirata + +penjaga sekolah dan anjingnya, Senyorita, semua pedagang +kaki lima, utamanya Bang Syam Robet, seluruh pegawai Di- +nas Kebersihan, penyuluh keluarga berencana, seluruh PNS +dan pegawai honorer di Belitong, para ajudan bupati, pemilik +dan para pegawai warung kopi Kutunggu Jandamu dan wa- +rung kopi Usah Kau Kenang Lagi, seluruh pegawai warung +kopi di mana pun Anda berada, juga kepada pedagang sa- +yur dan sembako, jaga malam, suster, bidan, mantri, dokter, +bapak polisi, banpol, pak pos, mualim, kelasi, nakhoda, mar- +konis, penggali kubur, pandai besi, tukang satai, pendulang +timah, penjual timah, pembeli timah, tukang solder, anggo- +ta penggemar motor lawas, filatelis, pemimpin redaksi dan +wartawan koran lokal, para pemangku adat, para dukun dan +pawang, guru mengaji, kepala polisi pamong praja dan anak- +anak buahnya, kepala semua desa di Belitong, para juru tulis +kantor desa, para penjaga pintu air, anggota orkes Melayu, +juru taksir kantor gadai, penjual kupon judi buntut, teriring +salam semoga segera tobat, syahbandar, para penggemar dan +pencipta puisi di seluruh pelosok Tanah Air, ketua pasar ikan +dan koordinator pasar pagi, doktorandus dan doktoranda, +karyawan karyawati, pramugara pramugari, peragawan pera- +gawati, seniman seniwati, wartawan wartawati, olahragawan +olahragawati, orang Belitong yang telah tamat universitas atau +yang sedang membuat skripsi, para pemulung sampah, pemu- +lung besi, politisi, juru parkir, kuli bangunan, tukang bakso, +kuli serabutan, nelayan, sipir, mereka yang sedang mendekam + Ayah ~ 103 + +di dalam bui, sopir mobil omprengan, para kernet, keamanan +pasar, kuli panggul, tukang ojek, calo, rentenir, pemimpin dan +kader parpol, ketua KUA, ketua BKKBN, modin, penghulu, +juru sunat, bendahara RT, ketua dewan kemakmuran Masjid +Al-Hikmah, ketua kantor gadai, kapolsek, ketua karang taru- +na, ketua dan anggota Dharma Wanita semua instansi. + + Ucapan terima kasih ditutup dengan permohonan maaf +jika ada pihak yang tak sempat disebut namanya, karena ke- +terbatasan waktu. Sabari membolak-balik kertasnya. + + “Maaf, Bang, apa tadi aku sudah menyebut para pemain +organ tunggal?” + + “Belum.” + “Terima kasih tak terhingga untuk para pemain organ +tunggal di mana pun Anda berada, serta para biduan dan +biduanitanya, salam Yamaha elektun!” + Grrr .... + “Tentu terima kasih saya juga untuk penemu organ Ya- +maha elektun. Tak terkira besar jasa orang itu dalam membu- +ka lapangan kerja. Teriring doa semoga penemu organ Yama- +ha elektun masuk surga.” + Efek tepuk tangan dan suitan membahana. + “Oh, oh, hampir aku lupa, maaf, ada satu lagi, Bang!” + “Silakan, Bung, delapan puluh lima lagi juga tak apa- +apa.” + Grrrrrr. + “Tentu akan kualat kalau aku tak mencium tangan dari +jauh sembari meng-hatur terima kasih tiada terperi kepada + 104 ~ Andrea Hirata + +Mister Lionel Ritchie. Terima kasih, Mister Lionel, di mana +pun Mister berada.” + + Grrrrrr .... + Sabari tersenyum berbunga-bunga. Penyiar heran dan +bertanya, “Mengapa Bung begitu gembira dan bersemangat +malam ini? Kalau boleh tahu.” + “Sebab, tadinya saya perkirakan akan gagal membawa- +kan lagu ‘Truly’ itu. Saya sudah pesimis. Saya tahu lagu itu +sangat sulit, bahkan penyanyi sesungguhnya belum tentu bisa +membawakannya. Saya terharu karena ternyata saya bisa, ba- +gus lagi! Oh, saya tak menduga bisa bernyanyi sebagus itu!” + Grrrrrrrrrrrr .... + Cita-Cita Izmi +dan Amiru + +IZMI gembira, Amiru sedih. + Guru-guru juga gembira, bahkan takjub melihat nilai- + +nilai di rapor semester 5 Izmi. Untuk kali pertama selama +sekolah di SMA itu, Izmi berhasil memerdekakan dirinya +dari angka merah. Nilai-nilai mata pelajaran pokok, misal- +nya PMP, biru macam langit di pantai barat bulan Februari. +Bidang Olahraga dan Kesehatan: 6,6. Kualitas kepribadian, +kerajinan: sangat baik, kebersihan: sangat baik, budi pekerti: sa- +ngat baik. + + Matematika, maaf, 6,5. Fisika, silakan iri, 6. Kimia, +hmmm, 6. Biologi, melingkar indah angka 8. Izmi memang +memperhatikan Biologi secara khusus sebab ilmu itu bersang- +kut paut dengan cita-citanya. + + “Apa sih cita-citamu, Izmi?” tanya Bu Norma. Izmi ter- +cenung, tampak agak kesulitan menguasai dirinya. + + “Aku mau menjadi dokter hewan, Bu,” katanya pelan +dan hati-hati. + 106 ~ Andrea Hirata + + Dia sedikit limbung sebab telah enam tahun cita-citanya +itu pingsan. Dia mau menjadi dokter hewan sejak kelas enam +SD, sejak melihat seorang dokter hewan membantu sapi ber- +anak dalam buku komik. Waktu itu ayahnya masih berjaya. +Selama enam tahun itu, baru kali ini dia berani mengata- +kan lagi bahwa dia mau menjadi dokter hewan. Dia berani +mengatakannya karena Sabari mengatakan bahwa dia mau +menjadi guru Bahasa Indonesia. Tanpa diketahui Sabari, dia +telah membangkitkan lagi cita-cita Izmi. + + “Cita-citamu apa, Bujang?” tanya gurunya kepada +Amiru. + + Amiru juga tercenung. Dia sedih karena teringat akan +radio ayahnya di kantor gadai. + + “Aku ingin menjadi pencipta radio, Bu.” + “Maksudmu?” + “Aku ingin menciptakan radio yang hebat, radio yang +bisa menangkap siaran gelombang pendek dari seluruh du- +nia, dengan suara yang jernih.” + Sambil terbaring lelah setelah mencuci segunung cucian +di rumah tauke, Izmi memandangi rapornya. Rasa bahagia +menyelinap dalam hatinya. Angka-angka biru beruntai-untai, +berkilauan bak butir-butir mutiara. Memesona bak bait-bait +puisi Sabari. Pujangga kampung yang hebat itu, apakah yang sedang +dilakukannya? Apakah dia sedang menulis puisi? Apakah dia sedang me- +rindukan Marlena? Izmi teringat akan Sabari dan teringat akan +ayahnya yang telah bertahun-tahun di penjara. + Pahlawan + +AKHIRNYA, mereka menamatkan SMA. Sabari, Ukun, +Tamat, Toharun, Zuraida, Izmi, Lena, dan Bogel, semuanya +lulus. Usailah tiga tahun kiprah mereka di SMA. Acara per- +pisahan sekaligus penyerahan ijazah digelar Sabtu pagi. Izmi +datang bersama ibu dan adik-adiknya. Ayahnya tak bisa ikut +karena masih mendekam di penjara. Izmi sengaja datang le- +bih pagi karena ingin melihat Sabari. + + Ibu dan adik-adiknya telah duduk di bangku undangan. +Izmi berdiri sendiri di bawah pohon akasia, dekat gerbang +sekolah, tempat Sabari biasa menunggu Lena. Matanya tak +lepas memandang ke jalan raya di depan sana. Para siswa dan +keluarga mulai berdatangan. Semakin lama semakin ramai. +Semua gembira. + + Izmi tersenyum melihat sebuah mobil pikap. Baknya +yang terbuka disesaki siswa-siswa dari Belantik. Di antara me- +reka ada Sabari dan ayahnya. Sopir dan para siswa memban- + 108 ~ Andrea Hirata + +tu Sabari mengangkat kursi roda sekalian dengan ayahnya. +Sedih bercampur bangga Izmi melihat Sabari mendorong +kursi roda ayahnya menuju sekolah. + + Izmi kembali ke tempat duduk, bergabung lagi dengan +ibu dan adik-adiknya. Nama siswa mulai dipanggil satu per +satu untuk menerima ijazah di atas panggung. Izmi tak ber- +henti tersenyum, tetapi tak berhenti pula menghapus air mata. + + Namanya dipanggil. Melihat siswa yang paling terharu +itu, Bu Norma yang mau menyerahkan ijazahnya bertanya, +“Mengapa kau menangis, Mi?” + + Izmi diam saja. + “Mengapa?” + Izmi tersenyum. + “Tak tahulah aku, Bu.” + “Adakah yang ingin kau sampaikan?” Bu Norma me- +nunjuk mik di podium. + Izmi menggeleng. Sebenarnya, dia ingin sekali menga- +takan pada setiap orang bahwa Sabari adalah pahlawannya, +inspirasi terbesarnya. Orang yang diam-diam memberinya +kekuatan. Tanpa Sabari tak mungkin dia dapat menyelesai- +kan SMA. Sabari sendiri tak pernah tahu hal itu. + Izmi kembali ke tempat duduk. Tak lama kemudian +nama Sabari dipanggil dan riuhlah tepuk tangan untuknya. +Rupanya selama tiga tahun di SMA itu, Sabari cukup popu- +ler. Tak jelas karena apa, yang jelas bukan dari prestasi di bi- +dang pelajaran. + Ayah ~ 109 + + Sebelum naik panggung, Sabari mencium tangan ayah- +nya, satu tindakan yang kemudian mendapat tepuk tangan +yang riuh lagi. + + Sabari menerima ijazah dari Bu Norma. Ibu menyalami­ +nya kuat-kuat sambil tersenyum lebar. Melihat mik mengang- +gur di podium, Sabari sedikit berbisik kepada Bu Norma: + + “Bisa bicara sedikit, Bu?” + “Sila, Raskal 1.” + “Bolehkah kusampaikan sesuatu untuk kawan-kawan +pakai mik itu?” + Bu Norma, yang tahu kecenderungan dramatis Sabari, +ingat kejadian Sabari dengan guru Fisika saat dia mau ber- +henti sekolah tempo hari. Sabari di depan mik. Gawat. Segala +sesuatu bisa terjadi. Dia curiga. + “Menyampaikan apa, Ri?” + “Semacam puisi perpisahan.” + “Puisi perpisahan? Hanya puisi perpisahan?!” Bu Nor- +ma berbisik keras. + “Tentu, Bu.” + “Sungguh?! Jangan kau main-main, Ri, ini acara resmi! +Banyak tamu penting, Wakil Bupati, Kepala Dinas Pendidik- +an, Kepala Polisi Pamong Praja, Ketua KUA, Ketua BKK- +BN, jangan kau bikin teater dadakan, berpidato yang bukan- +bukan, awas kau, Boi!” + “Tenanglah, Bu, ini puisi perpisahan saja.” + Bu Norma menimbang-nimbang sebentar, sulit dia +mengambil keputusan, tetapi akhirnya dengan waswas dia + 110 ~ Andrea Hirata + +berjalan menghampiri mik, mengambilnya lalu menyerah- +kannya kepada Sabari. + + Sabari melangkah dengan tenang ke tengah panggung. +Mereka yang mengenalnya segera paham, pasti dia mau ber- +aksi dengan puisinya. Mereka bertepuk tangan. Sabari me- +nyapu pandang hadirin. Bu Norma tegang menunggu apa +yang akan terjadi. Sabari menghentikan pandangannya ke +arah pukul 4.00, tempat Lena berada. Bu Norma gemetar +dan langsung menyesal telah memberikan mik itu kepada Sa- +bari. Celaka! Tadi aku sudah curiga! Raskal! Dan, semuanya ter- +lambat sebab suara Sabari telah menggelegar. + + Datangkan seribu serdadu untuk membekukku! + Bidikkan seribu senapan, tepat ke ulu hatiku! + Langit menjadi saksiku bahwa aku di sini, untuk mencintaimu! + + Tiba-tiba Sabari diam, suasana senyap, sepi, hening, Sa- +bari menutup puisinya dengan syahdu. + + Dan biarkan aku mati dalam keharuman cintamu .... + + Gegap gempitalah acara perpisahan nan khidmat itu. +Hadirin berdiri dan bertepuk tangan panjang untuk Sabari. +Sabari tersenyum lebar. Lena menunduk dan menggeleng- +geleng. Bu Norma menutup wajahnya dengan tangan. Ayah +Sabari tak henti-henti bertepuk tangan untuk anaknya. + Tanjong Pandan + +SABARI telah mengawali SMA dengan sebuah puisi untuk +Lena, dan mengakhirinya dengan sebuah puisi, juga untuk +Lena. + + Dia melamun di bawah pohon akasia dekat gerbang se- +kolah, tempat dia biasa menunggu Lena dan kecanduan akan +kelebat ajaib perempuan itu naik sepeda. Lima detik tak le- +bih, lalu segala hal sepanjang hari itu akan berlinang madu. + + Senyorita mendekat ke pohon akasia untuk melakukan +ritual number two, satu tindakan teritorial tak senonoh, sama +sekali tak peduli bahwa Sabari sedang dilanda awan-awan +puisi. Sabari memandangi sekolah dan menoleh ke masa lalu +selama tiga tahun, sarat akan pengalaman berharga. Dalam +masa itu dia telah melambung setinggi langit dan terjerembap +karena cinta. Dia telah mengenal kawan-kawan yang baik, dia +telah menulis puisi yang dia sendiri tak tahu dari mana men- +dapat kata-katanya dan dia telah mengalami hal yang mus- + 112 ~ Andrea Hirata + +tahil, yakni menjadi seorang penyanyi, yang menurut peng- +akuannya sendiri, sangat sukses, tetapi menurut pengakuan +orang lain, jika mendengar Sabari menyanyikan lagu “Truly” +itu, Mister Lionel Ritchie pasti menyesal telah mengedarkan +kasetnya di Indonesia. + + Tanjong Pandan, ibu kota kabupaten, adalah babak +baru hidup Sabari. + + “Janganlah cemas, Ayahanda, aku akan pulang seming- +gu sekali, untuk mendorong kursi roda Ayah.” + + “Kau akan tinggal di mana?” + “Banyak kamar kontrakan. Aku akan tinggal dengan +Ukun dan Tamat. Semuanya Ayah kenal.” + “Mau apa kau di sana?” + “Seperti orang lainnya, mencari pekerjaan, aku bukan +anak-anak lagi. Aku harus merantau, malu aku bergantung +pada orangtua.” + Ayahnya sedih. + “Mengapa bersedih, Ayah?” + “Maaf, Ri, aku tak bisa menyekolahkanmu ke Jawa.” + “Aih, usahlah risau, SMA saja sudah ketinggian untuk- +ku. Orang sekolah untuk bekerja. Aku akan langsung bekerja +di Tanjong.” Bersusah payah Sabari membesarkan hati ayah- +nya. + Untuk membuat cerita panjang menjadi pendek, tak +lama kemudian Ukun, Tamat, dan Sabari sudah bekerja +di Tanjong Pandan. Ukun yang bercita-cita menjadi dok- + Ayah ~ 113 + +ter, mendapat pekerjaan sebagai tukang gulung dinamo di +bengkel listrik CV Pijar Jaya Abadi. Tamat yang bercita-cita +menjadi pilot diterima bekerja sebagai tukang kipas satai di +warung satai kambing muda Afrika. Adapun Sabari yang ber- +cita-cita menjadi guru Bahasa Indonesia SD diterima bekerja +di pabrik es. + + Toharun berpamitan kepada mereka, tetapi tak mem- +beri tahu mau merantau ke mana. Mungkin ke Bangka, Pa- +lembang, atau Jakarta untuk mengejar cita-citanya menjadi +Menteri Olahraga Republik Indonesia. Setelah berpamitan, +lelaki yang besar seperti lemari itu tak ada kabar beritanya. + + Sebenarnya, Sabari diterima bekerja sebagai penjaga +toko furnitur dan penjaga air mineral isi ulang, tetapi dia tak +mau. Dia mau kerja berat membanting tulang. Dia mau tu- +buhnya hancur setiap pulang kerja, lalu jatuh tertidur lupa +diri. Bangun tidur dan bekerja keras lagi. Semua itu karena +dia mulai bertekad untuk melupakan Lena. Ini kemajuan. Ba- +rangkali semakin dewasa dia semakin bijak. + + Dia makin bertekad karena mendengar kabar Lena se- +makin binal. Buncai, tukang kredit sekaligus biang gosip dari +pintu ke pintu itu mengatakan bahwa Lena sudah pacaran +dengan semua lelaki di kantor pelabuhan. Tak jelas apakah +Buncai, yang sudah punya anak empat, bergunjing begitu +lantaran dia naksir Lena dan pernah kena tampar perempu- +an itu di muka kantor camat, sebab bicara seenak jambulnya +di muka umum. + 114 ~ Andrea Hirata + + Maka, bekerjalah Sabari sebagai kuli bangunan dan +sungguh tinggi dedikasinya. Tak kenal lelah dia. Kuli lain +mencuri-curi waktu agar bisa bermalas-malasan, dia sebalik- +nya. Yang tak disuruh dikerjakannya, apalagi yang disuruh. +Orang lain minta libur, dia minta masuk kerja. Kerap mandor +menyetopnya karena terlalu banyak mengaduk semen, me- +maku sesuatu yang seharusnya tak dipaku, memasang yang +bukan untuk dipasang, dan mengangkat yang seharusnya tak +diangkat. + + Jika diperintah, dengan sigap dia menjawab, “Beres, +Dor!” bahkan sebelum mandor selesai bicara. + + Pulang kerja, tubuhnya remuk redam seakan telah di- +hantam seribu gada. Sendi-sendinya nyeri, tulang-tulangnya +ngilu. Dilewatkannya malam dengan duduk sendiri sambil +memegang pensil dan memandangi ilalang yang berkilauan +disinari bulan. Angin selatan berembus pelan, senyap dan +sepi. Air mata lelaki kuli yang lugu itu mengalir pelan. Dia +rindu kepada Marlena. + +Bangunan yang dikerjakan Sabari sudah selesai. Sabari me- +ngatakan kepada mandor bahwa jika ada proyek lagi, dia mau +ikut. Mandor tersenyum dan mengangguk dengan seribu kata +tidak dalam dadanya. + + Tunggu punya tunggu, mandor tak memanggil, Sabari +mencari kerja lain. Kalau dia mau, sebenarnya dia diterima + Ayah ~ 115 + +di bagian cleaning service SMEA atau jaga malam di gudang +milik tauke beras. Namun, dia tetap mencari pekerjaan yang +lebih berat. Agar dapat menipu badan dan pikirannya untuk +terlepas dari bayangan Lena selalu, jadilah dia kuli di pab­- +rik es. + + “Ri, sebenarnya ada cara untuk melupakan perempu- +an,” kata Ukun. + + “Yaitu?” + “Melalui gerak badan, olahraga.” + “Benarkah?” + “Nah, sebentar lagi ada lomba maraton Piala Kemerde- +kaan, ikut saja.” + “Mengapa maraton dapat membuat lupa pada perem- +puan?” + “Karena maraton adalah olahraga yang sangat spiritu- +al,” kata Tamat. + “Maksudnya?” + “Maraton menyediakan waktu yang sangat lama bagi se- +orang atlet untuk merenung. Sambil maraton kau dapat me- +renungkan wajahmu yang mengharukan, nasibmu yang sial, +dan hidupmu yang tak berguna itu. Lihatlah, pelari maraton +jika berlari seperti sedang memikirkan sesuatu, wajah mere- +ka tak pernah hampa. Kepala mereka penuh pikiran tentang +masa lalu, masa depan, keberhasilan, kegagalan, utang piu- +tang, kebajikan, dan kejahatan yang pernah mereka perbuat, +dan dari seluruh persoalan yang menjepit mereka itu, mereka + 116 ~ Andrea Hirata + +tetap harus berjuang untuk mengalahkan lawan dan menca- +pai finis. Semua itu sangat spiritual!” + + “Oh, Mat, tak kusangka kau secerdas itu!” Ukun kagum. + “Kalau ditengok secara rengking, kau dulu memang jauh +di bawahku, Kun.” + “Baiklah, Mat.” + Sekadar catatan, waktu kelas tiga SMA, di kelas mereka +ada 47 siswa. Bu Norma pernah mengurutkan rengking-nya. +Tamat rengking 45, Toharun 46, Ukun 47 alias juru kunci. Me- +reka selalu bertengkar, yang paling sengit selalu Ukun, tetapi +dia mati kutu jika Tamat mengungkit-ungkit soal rengking. Itu- +lah senjata pamungkas Tamat. + “Waktu SMA dulu kau pernah jadi juara maraton, kau +adalah seorang pelari, peluangmu besar, Ri! Selain itu, ba- +nyak hadiahnya!” Ukun mencoba mengalihkan pembicaraan +dari soal rengking. + “Juara pertama akan mendapat radio transistor, termos, +mangkuk selusin, pinggan setengah lusin, jam beker yang +ada alarmnya, bibit kelapa hibrida, dua kaleng biskuit Khing +Khong, almanak, semprong lampu petromaks, lampu petro- +maksnya juga, sajadah, kaus kaki!” + Ukun berusaha mengingat-ingat. + Sabari terpana. Dia tak begitu mengerti maksud Tamat +soal spiritualitas maraton, tetapi hadiah-hadiah itu memberi- +nya sebuah inspirasi. + Keesokannya, usai shalat Shubuh, Sabari langsung ber- +lari menuju lapangan balai kota, berbalik arah ke kantor pos, + Ayah ~ 117 + +lalu menerabas ilalang di pekarangan perumnas, tersembul +dia di samping warung bakso, masuk ke kompleks polisi, ber- +belok lagi lalu meliuk-liuk di antara nisan kuburan Tionghoa, +lalu masuk lagi ke jalan dan menantang belasan ekor anjing +gelandangan di pasar pagi. + + Sambil berlari terpontal-pontal dikejar anjing, dia me- +nengadah ke langit dan bertanya kepada Tuhan, mengapa +Tuhan menciptakan satu manusia bernama Marlena di dunia +ini dan mengapa dia harus menanggung rindu yang pahit ke- +pada perempuan itu. Pertanyaan yang tak terjawab itu mem- +buatnya berlari macam orang sakit ingatan. + + Akhirnya, dia sampai di dermaga. Laut, hanya laut yang +dapat menghentikannya. Demikian saban pagi dia latihan. +meski hujan lebat, meski angin ribut, dia tak pernah berhenti +berlari. Karena Lena dan satu rencana manis dengan hadiah- +hadiah itu, Sabari merasa tenaganya tak terbatas. + + Pada saat perlombaan, Sabari mendapat nomor dada +1231. Dia terkejut. Karena jumlah hari sejak kali pertama dia +melihat Lena saat ujian masuk SMA sampai dia ikut lomba +itu lebih kurang 1231 hari, alias hampir empat tahun. Saat itu +Sabari langsung tahu bahwa dia takkan mudah dikalahkan. + + Benar saja. Sejak start Sabari langsung memelesat. Dia +berlari sejadi-jadinya. Kecepatannya empat puluh kilometer +per jam, melebihi kecepatan musang yang paling sehat seka- +lipun. Dia tak memperhatikan ratusan pelari lain yang ber- +lomba-lomba. Yang dia tahu adalah semakin lama semakin + 118 ~ Andrea Hirata + +banyak penonton di pinggir jalan dan semakin riuh orang +bertepuk tangan untuknya. Tahu-tahu dia sudah menerabas +pita di garis finis. Dilihatnya sekeliling, tak ada pelari lain. +Dinamut, pelari legendaris, yang dijagokan dalam lomba itu, +juara bertahan yang dicurigai banyak pihak punya ilmu pe- +landuk, tak tampak batang hidungnya. Sabari juara. + + Dinamut sangat terpukul akan kekalahan yang tak di- +duganya dari seorang kuli pabrik es. Dengan wajah sembap +dipukulnya dadanya sendiri berulang-ulang, matanya basah, +susah payah bupati membujuknya. + + Ukun dan Tamat kewalahan membawa pulang hadiah +yang banyak. Apalagi, tahun ini ada hadiah bonus, yakni dua +kaleng susu kental manis, pacul, dan alat pembunuh nyamuk +pakai listrik, kejam sekali. + + Sabari tak terlalu peduli dengan namanya yang tiba-tiba +tenar dan fotonya yang terpampang di koran lokal. Dia ha- +nya memikirkan rencana manisnya untuk mengikuti lomba +itu, yaitu mempersembahkan piala dan hadiah-hadiahnya +untuk Lena. + + Dengan menumpang truk, sesuai kemauan Sabari, +Ukun dan Tamat membawa piala dan hadiah-hadiah itu ke- +pada Lena. Bukan main repotnya mereka. Beragam hadiah +bergelantungan di tubuh mereka sehingga mereka mirip pi- +nang yang dipanjat dalam lomba peringatan kemerdekaan. + + Sampailah mereka ke rumah Lena. + “Marlena ...,” kata Ukun baik-baik kepada Lena yang +curiga. + Ayah ~ 119 + + “Sudahkah kau lihat surat kabar?” + “Surat kabar apa?” + “Tak tahukah kau? Sabari sudah jadi orang tenar! Orang +besar! Dia juara maraton!” + “Apa peduliku!? Dia mau jadi juara maraton, mau jadi +juara menulis indah, tak ada urusan denganku!” + “Baiklah, dan Sabari ingin mempersembahkan hadiah- +hadiah ini untukmu. Begitu amanahnya.” + Yang terjadi adalah Lena marah-marah. Diliriknya ha- +diah-hadiah itu, segala lampu petromaks, rantang, gelas, pi- +ring, jam dinding. Tak sudi dia menerimanya. + “Bawa pulang sana! Jangan lupa kau sampaikan pada +Sabari! Teriakkan di telinga wajannya itu keras-keras! Dia itu +sudah majenun!” + Keesokannya Ukun dan Tamat kembali ke Tanjong +Pandan. Mereka mengembalikan semua hadiah itu kepada +Sabari sambil mengatakan bahwa Marlena tak mau mene- +rimanya. Lalu, Ukun bangkit dan bersorak sekeras-kerasnya +dekat telinga Sabari, “Lena berpesan pula agar aku tak lupa +meneriakkan di telinga wajanmu! Bahwa kau sudah ma- +jenun!” + +Berakhirlah bab maraton dalam hidup Sabari. Kejayaan itu +tiba begitu cepat, lalu lenyap sekedip mata. Bak bintang jatuh, + 120 ~ Andrea Hirata + +tanpa dia benar-benar sempat menyelami spiritualitas lari ja- +rak jauh itu. Namun, tak sedikit pun surut semangatnya untuk +melupakan Lena, sekuat semangatnya untuk mendapatkan- +nya. Cinta memang sangat membingungkan. + + Semula Ukun menduga apa yang terjadi dengan Sabari +dulu hanyalah euforia anak SMA, tetapi seiring waktu, Sabari +semakin terpaku kepada Lena. Inikah yang disebut orang cin- +ta sejati? + + Sabari kerap melihat dirinya di depan kaca lalu me- +ngumpulkan seluruh tenaga alam semesta, dan dia berkata +dari dalam perutnya bahwa mulai hari itu dia takkan lagi +memikirkan Lena. Namun, baru saja berjanji kepada diri- +nya sendiri, jika dia mendengar sedikit saja Ukun atau Tamat +menyebut nama Marlena atau sesuatu yang berbunyi seperti +Marlena, misalnya terlena, terkena, berkelana, terpana, bercelana, me- +lamar, markisa, periksa, penyuluhan, pegadaian, pembangunan, telinga +lambing Sabari langsung berdiri, gerak geriknya seperti dia +ketinggalan sesuatu di sebuah tempat. + + Jika Ukun salah bicara sedikit saja soal Marlena, dia ter- +singgung dan menjadi dramatis. + + “Aku tadi melihat Marlena, lagi antre minyak solar.” + “Siapa katamu, Kun? Marlena? Di mana?” Sabari me- +lompat dari bangku, bergegas mau menyambar sepeda. + “Ai, maaf, Ri, maksudku Mahmudin, bukan Marlena.” +Sabari berbalik. + Ayah ~ 121 + + “Hati-hati kalau bicara, Kun! Banyak orang masuk pen- +jara gara-gara saksi salah menyebut nama! Lain waktu teliti +dulu baru bicara!” + + “Baiklah, Ri, nanti kuperiksa dulu.” + “Apa katamu? Marlena?” + Setiap Sabtu sore Sabari menghabiskan waktu di taman +balai kota karena kata orang Sabtu sore Marlena dan sekong- +kol-sekongkolnya suka nongkrong di taman balai kota. Se- +perti ketika masih SMA dulu, Ukun dan Tamat gemas, benci +sekaligus kasihan dengan Sabari. Adakalanya Ukun mengan- +cam, “Jiwamu sudah dikecoh cinta. Waspada, Ri, bisa-bisa +kau kena gangguan jiwa, masuk Panti Amanah pimpinan +Doktoranda Ida Nuraini!” + Sabari pucat. Itulah yang paling ditakutkannya. + “Mau?!” + “Tidak mau, Kun.” + “Maka, perbaiki dirimu! Lihatlah, Lena telah membuat- +mu opsedon!” + Barangkali maksudnya up side down, jungkir balik. + “Baiklah, Kun.” + “Kalau masih kau sebut-sebut nama perempuan itu, ku- +laporkan kau sama Doktoranda Ida Nuraini!” + “Jangan, Kun.” + “Mulai sekarang hapus nama perempuan itu!” Sabari +ragu, Ukun geram. + “Hapus nama perempuan itu!” Ukun tak main-main. + 122 ~ Andrea Hirata + + “Akan kuhapus, Kun.” + “Tekadkan niatmu!” + “Aku bertekad, Kun.” + “Janji?!” + “Janji, Kun.” + Sabari tampak muak kepada dirinya sendiri, wajahnya +penuh tekad. Dia ingin menyudahi dominasi Marlena dalam +hidupnya. + “Buang puisi-puisi konyol itu!” + “Akan kubuang!” + “Hancurkan fotonya!” + “Akan kubumihanguskan!” + “Jangan biarkan seorang perempuan membuatmu ter- +lena!” + Sabari terpaku. + “Apa katamu? Marlena ...?” + Puisi + +MESKI tak henti-henti mencemooh Sabari, kisah cinta Ukun +dan Tamat juga sesungguhnya tak seindah kisah cinta dalam +sandiwara radio. + + Sejak dulu Ukun menyukai banyak perempuan. Namun, +perempuan yang tidak menyukainya lebih banyak lagi. Waktu +masih SD, dia suka sama Sita, Mawar, Anisa, Laila, Nurma- +la, Aini, Indra, Deli, Lili, Mumun, Nizam, Latifah, Salamah, +Fatimah, Hasanah, Sasha, Zasa, Zaza, dan Shasya. Sampai +sekarang pun dia masih suka, dan hanya dia yang suka, orang +lain tidak. + + Ukun melirik Mbak Yu, tukang jamu gendong yang suka +berjualan jamu di muka bank BRI. Sayangnya Mbak Yu ku- +rang respons. Jika berbicara dengannya, Ukun komat-kamit +sendiri. Mbak Yu sibuk mencampur jamu. + + Ukun beralih ke Yuyun, penjaga kebun binatang. Te- +rang-terangan Yuyun bilang bahwa dia tak mau pacaran de- + 124 ~ Andrea Hirata + +ngan lelaki yang wajahnya macam penjahat dalam pelem Si +Buta dari Gua Hantu. + + “Aku mengerti perasaanmu, Yun,” Ukun pasrah. + Ukun melirik lagi seorang perempuan yang suka duduk +sendiri di taman balai kota. Perempuan itu berparas lumayan, +kulitnya bersih. Rambutnya lebat. Pakaiannya seperti sera- +gam pegawai PDAM. Dia pendiam, tetapi selalu tersenyum. +Ukun tak jadi mendekatinya karena curiga. + Soal Tamat adalah pelik. Dia dinamai Tamat oleh ayah- +nya dengan satu maksud agar menamatkan perguruan tinggi +dulu baru berkenalan dengan perempuan. Kesulitan ekono- +mi membuatnya tidak bisa kuliah dan sekarang ayahnya te- +lah meninggal sehingga tak bisa dimintai pendapat. Dia mau +menganulir pesan ayahnya, tetapi takut kualat. Tamat serba- +salah. Yang bisa dilakukannya hanya menunggu wangsit atau +tanda-tanda yang menunjukkan bahwa ayahnya memberi +restu kepadanya untuk pacaran. + Ukun tak patah semangat. Berbagai cara sudah dicoba, +tetapi cinta belum berpihak. Usia bertambah, dia gelisah. +Kata orang, untuk melipur sial asmara, dia harus ke pantai +barat pada Februari untuk melihat saat langit menjadi biru. Ko- +non, jika bisa menahan napas selama langit menjadi biru itu, jo- +doh akan enteng. Ukun tak pernah percaya dengan dongeng +kampung itu. + Ayah ~ 125 + +Tiada jeda dirundung derita cinta sebelah mata, Sabari mulai +suka bicara sendiri. Ukun dan Tamat cemas. + + “Terlalu sentimental.” Begitu pendapat Tamat tentang +Sabari. + + “Sikapmu itu merupakan kombinasi antara gizi buruk +dan terlalu banyak membaca novel, berbahaya, bisa berla- +rut-larut. Untuk menyelesaikannya harus ditempuh satu cara +yang ekstrem, yaitu berkenalan dengan perempuan lain.” + + Ukun menggeleng-geleng kagum sambil menatap Ta- +mat. + + “Mengapa kau bisa begitu cerdas, Boi? Padahal, waktu +kita kecil dulu kau bebal minta ampun.” + + “Aku pun tak tahu apa yang terjadi denganku, Kun, seti- +ap bangun pagi aku merasa semakin cerdas!” + + Ngomong-ngomong, berkenalan dengan perempuan lain +sangat dihindari Sabari. Memandang artis India di baliho +film di Bioskop Serodja saja sering membuatnya merasa telah +mengkhianati Lena (siapa bilang Sabari obsesif ?). + + “Diam-diam, kau sudah kukenalkan dengan tukang +jamu gendong yang suka berjualan di muka bank BRI, ber- +minatkah kau, Ri?” + + Sabari menggeleng. + “Kuceritakan soal kau padanya. Kubilang jangan terke- +jut kalau berjumpa denganmu, sebab kau jelek sekali. Tapi, +kubilang juga hatimu baik, pintar membuat puisi, dan sudah +punya pekerjaan tetap di pabrik es. Dia tersenyum, Ri! Dia +putar-putar cincinnya!” + 126 ~ Andrea Hirata + + Sabari menggeleng. + “Mbak Yu, kataku,” Ukun menggambarkan pembicara- +annya dengan Mbak Yu, “selama lampu PLN masih sering +mati, lelaki tampan dan jelek tak ada bedanya! Dia tertawa, +Ri! Ai, berderai-derai tawanya, Boi!” + Ukun pun tertawa, Tamat tertawa, Sabari menggeleng. + “Dari gerak lakunya, aku tahu dia tertarik!” + Sabari menggeleng-geleng. + “Kau tahu artinya kalau perempuan memutar-mutar +cincinnya?” tanya Tamat. Sabari menggeleng. + “Itu artinya dia ingin tahu!” + “Begitukah?” + “Ya.” + “Kau tahu artinya kalau pria memutar-mutar cincin- +nya?” tanya Tamat lagi. + “Tidak.” + “Artinya tunggulah kehadiran pria itu di pegadaian.” + Ukun tertawa, Tamat tertawa, Sabari menggeleng. + Dan, berkenalanlah Sabari dengan Mbak Yu. Namun, +hanya sebentar sebab hampir muka Sabari kena siram jamu +kuat lelaki rasa jahe lantaran berulang-ulang memanggil tu- +kang jamu itu Marlena, padahal namanya Suminem. Kalau +diselidiki secara saksama melalui ilmu linguistik, memang su- +sah melihat kemiripan antara dua nama itu. Dalam kaitan itu, +ke-muntab-an Mbak Yu sangatlah bisa dimaklumi. + Melalui Ukun juga, Sabari berkenalan lagi dengan Yu- +yun, penjaga kebun binatang kabupaten di bagian hewan + Ayah ~ 127 + +merayap. Yuyun juga jengkel sebab Sabari tak henti-henti +bercerita bahwa Lena punya tas plastik bermotif kulit buaya. +Mereka putus. Pada atasannya, Nuraini, dia minta dipindah +ke bagian unggas. + + Akhirnya, Ukun mengenalkan Sabari dengan seorang +perempuan yang suka duduk sendiri di taman balai kota, ber- +pakaian rapi seperti mau ke kantor, jarang bicara, tetapi sela- +lu tersenyum. Sabari menemui perempuan itu. Hampir dua +jam Sabari bercakap terus, mulai soal musim sampai soal cara +menambal ban sepeda dengan getah pohon karet. Perempu- +an itu tak bicara sepatah kata pun, tidak mengiyakan, tidak +menidakkan, tidak membantah, tidak juga setuju, tidak benci, +tidak juga suka. Dia hanya tersenyum-senyum. Sabari curiga. + +Saban hari Sabari menanti keajaiban. Misalnya, ada seseo- +rang dari Belantik tergopoh-gopoh datang kepadanya dan +berkata bahwa Lena rindu kepadanya. Sampai tak bisa tidur +gara-gara rindu itu. Atau datang sepucuk surat dari Lena, da- +lam surat itu Lena menulis bahwa setelah sekian lama waktu +berlalu baru dia teringat akan kejadian waktu ujian masuk +SMA dulu, dan betapa dia berterima kasih serta jatuh hati +kepada pemuda tampan yang membuat nilai ujian Bahasa +Indonesia­-nya 10 itu, sehingga dia diterima di SMA. + + Akan tetapi, surat-surat semacam itu tak pernah datang. +Karena itu, Sabari menulis surat yang indah, memasukkan- + 128 ~ Andrea Hirata + +nya ke amplop, membawanya ke kantor pos, menempelinya +prangko kilat, dan mengirimkannya, kepada dirinya sendiri. +Ukun tahu kelakuan sinting Sabari itu. + + “Mengapa, Ri? Mengapa Lena? Mengapa seakan tak +ada perempuan lain di dunia ini?” + + “Aku pun tak tahu, Boi. Kalau melihat Lena, aku merasa +seakan sayap-sayap tumbuh di bawah ketiakku.” + + Karena sikap Sabari yang keras kepala, Ukun dan Ta- +mat jengkel. Mereka tak mau mendengar soal Sabari dan +Lena. Tanpa tempat mengadu, Sabari hanya mengadu pada +puisi. Jika dia rindu kepada Lena, berlembar-lembar puisi di- +tulisnya. + + Rindu yang kutitipkan melalui kawan + Rindu yang kutinggalkan di bangku taman + Rindu yang kulayangkan ke awan-awan + Rindu yang kutambatkan di pelabuhan + Rindu yang kuletakkan di atas nampan + Rindu yang kuratapi dengan tangisan + Rindu yang kulirikkan dalam nyanyian + Rindu yang kusembunyikan dalam lukisan + Rindu yang kusiratkan dalam tulisan + Sudahkah kau temukan? + Amiru +dan Kantor Gadai + +AMIRU telah menghabiskan waktu yang berharga untuk +balap sepeda itu. Dia yakin akan menang, paling tidak juara +ketiga, tetapi mendaftar lomba saja tak boleh. Dia semakin +gelisah karena hanya tinggal tiga minggu siaran radio yang +ditunggu ayahnya itu akan mengudara. Pedih hatinya meng- +hitung jumlah uang yang ada padanya. Meski telah bekerja +keras, jumlahnya jauh dari sejuta enam ratus ribu. + + Amiru tak mau menyerah demi ayah dan ibunya. Dia +meminta pekerjaan apa saja, dari siapa saja, di mana saja, +bahkan pekerjaan yang orang dewasa sendiri berat menger- +jakannya, misalnya menggali sumur atau menjadi kuli harian +menambal jalan raya. + + Sabtu itu, pagi-pagi benar dia ke pasar. Kabut belum +beranjak dari pucuk ilalang. Dalam hati dia berdoa mudah- +mudahan mendapat banyak pekerjaan hari itu. Mudah- +mudahan banyak orang berbelanja dan memerlukan ban- + 130 ~ Andrea Hirata + +tuannya untuk memanggul belanjaan. Namun, hingga siang +berdiri menunggu, tak seorang pun memerlukan bantuannya. + + Hampir tengah hari, panas, Amiru haus dan lapar. Bu- +nyi trompet tukang es membuatnya semakin haus. Nun di +sana dilihatnya bus mini berhenti di depan sebuah toko. Dari +bus itu keluar gadis-gadis muda bertopi lebar, berkacamata +hitam, berkaus tipis, bercelana pendek. Mereka adalah turis, +dan mendadak Amiru terpikir akan sesuatu. + + Dia pergi ke toko itu. Kakak-kakak penjaga toko suvenir +itu telah dikenalnya. Kata mereka, juragan toko itu menerima +siapa pun yang mau bekerja membuat suvenir. Upahnya ber- +dasarkan jumlah suvenir yang dibuat. + + Amiru melonjak. Dia telah menemukan pekerjaan yang +ditunggu-tunggunya. Siang itu pula dia langsung bekerja. Da- +lam satu jam dia bisa membuat dua puluh gantungan kunci, +padahal pegawai yang sudah lama bekerja di situ jarang da- +pat membuat lebih dari sepuluh. + + Amiru pulang mengayuh sepeda sambil bersiul-siul. Se- +nin nanti sekolahnya mulai libur, dia dapat bekerja seharian. +Benar kata ayahnya, malaikat-malaikat turun untuk melihat niat +yang baik. + + Amiru menghitung, jika dalam sehari dia bisa membuat +tiga ratus gantungan kunci, jumlah upahnya tepat pada hari +siaran radio yang ditunggu ayahnya nanti, akan cukup untuk +menebus radio ayahnya di kantor gadai. + + Amiru bekerja dengan kecepatan yang membuat jura- +gannya tercengang. Tak pernah ada orang bekerja sekeras + Ayah ~ 131 + +Amiru. Pada hari pertama dia tak bisa mencapai angka tiga +ratus, tetapi hari-hari berikutnya dia melampauinya. + + Membuat gantungan kunci meliputi pekerjaan memo- +tong, mengikir, melubangi, dan mengasah berbagai benda, +mulai dari tempurung kelapa sampai pelat besi. Amiru me- +ngerjakan semuanya dengan cepat dan teliti. Jari-jarinya me- +lepuh. Tangannya penuh balutan plester. + + Pada hari siaran radio itu, diam-diam Amiru mengambil +kuitansi gadai. Usai bekerja sepanjang siang dan menerima +upah terakhir, langsung dia ngebut bersepeda ke ibu kota ka- +bupaten. + + Angin kencang melawan laju sepeda sehingga kancing- +kancing bajunya terlepas. Berkali-kali dipegangnya tas yang +disandangnya, untuk memastikan uang hasil kerja kerasnya +masih ada di situ. Senyumnya tak henti mengembang karena +membayangkan apa yang akan dialami ayahnya nanti ma- +lam. + + Akhirnya, dia sampai ke kantor gadai. Diparkirnya sepe- +da lalu berjalan menuju pintu masuk. Kasir terkejut melihat +uang-uang kertas yang kumal dan segunung uang logam di- +tumpahkan anak kecil itu ke atas meja. + + “Maaf, Ibu, kalau aku tak salah hitung, semuanya sejuta +enam ratus ribu rupiah, jika kurang, kabari aku, jika lebih, +biarlah, kelebihannya kusumbangkan pada negara.” Amiru +tersenyum sambil menyerahkan kuitansi gadai. + + Ibu kasir terpana melihat jari-jarinya terbalut plester. +Diamatinya lengan Amiru yang keras, urat-uratnya bertim- + 132 ~ Andrea Hirata + +bulan. Lengan itu seharusnya bukan lengan anak kecil, itu +lengan orang dewasa, kuli kasar. + + “Kau mau menebus radio?” + “Iya, Bu, radio ayahku.” + Ibu kasir segera tahu apa yang telah dialami anak kecil +di depannya, untuk menebus radio ayahnya. + “Ayahmu senang mendengar radiokah, Bujang?” + “Senang sekali, Bu.” + “Kau bekerja untuk menebus radio ayahmu, ya?” + Amiru tersenyum. + “Bekerja apa?” + Amiru tersenyum lagi. + “Aku pun senang mendengar radio.” Ibu kasir terharu. +Mungkin dia punya anak seusia Amiru. Dibawanya kuitan- +si itu ke ruang di belakang. Tak lama kemudian dia kembali +membawa sebuah radio. Amiru gemetar. + Ibu menyerahkan radio itu, Amiru langsung menyam- +bar dan memeluk radio itu. Tak hirau dia akan orang-orang +yang heran. Ibu terhenyak karena haru. + Amiru bergegas ke tempat parkir. Diikatnya radio itu +di boncengan sepeda lalu dikayuhnya sepeda dengan cepat. +Sepeda meluncur melewati pasar dan jajaran panjang para +pedagang kaki lima. Amiru tak mau menoleh ke belakang. + Dilewatinya kampung demi kampung dan tibalah dia di +jalan yang panjang. Sepi, hanya padang di kiri-kanan jalan. +Amiru melepaskan tangan dari setang sepeda dan memben- + Ayah ~ 133 + +tangkan tangannya lebar-lebar. Angin menerpa wajahnya. +Dia menoleh ke belakang dan tersenyum melihat radio itu. +Radio itu pun tersenyum kepadanya. + + “Maafkan aku, Mister Phillip, lama sekali baru menjemputmu.” + “Ah, tak apa-apa, Amiru.” + “Mencari pekerjaan susah, hanya orang sekolah tinggi yang dapat +pekerjaan.” + “Aku mengerti, tapi aku tahu, kau pasti datang menjemputku.” + Malam itu, azan Isya sambung-menyambung dari surau +ke surau, setelah itu tak terdengar lagi suara. Kampung sepi, +lalu senyap. + Malam merayap, semakin senyap. Amiru terbaring me- +natap langit-langit kamar, tergeletak lemah dan lelah, seakan +tulang belulangnya telah patah, tetapi telinganya terpasang. +Tegang dia menunggu pukul 9.00 malam tiba. Itulah saat si- +aran yang sangat ditunggu ayahnya. + Tak berkedip Amiru menatap detak jarum panjang di +jam dinding, setiap detik bak sehari. Akhirnya, pukul 9.00 +malam tiba. Terdengar langkah ayahnya menuju radio. Be- +berapa saat lenyap lalu perlahan menguar bunyi kemerosok. +Oh, betapa Amiru merindukan bunyi itu. + Melalui celah dinding papan, Amiru melihat ayahnya +memutar-mutar tombol tuning lalu hinggap di siaran RRI. +Lagu Kebangsaan “Indonesia Raya” berkumandang. Amiru +tersenyum melihat ayahnya bangkit dan berdiri tegak. + 134 ~ Andrea Hirata + + Amiru kembali berbaring. Setelah Lagu Kebangsaan, +akan mengudara siaran yang ditunggu ayahnya itu. Berde- +bar-debar dada Amiru menunggu detik-detik siaran. Tak +lama kemudian terdengar suara penyiar: + + Para pendengar yang budiman, di mana pun Anda berada di se- +luruh pesolok Tanah Air, sekali merdeka, tetap merdeka, inilah Radio +Republik Indonesia brrrhhhbbb ... nguing ... pukul sepuluh pagi waktu +setempat, pukul ... nguing ... berebhhh ... dengan bangga kami udarakan +kunjungan Lady Diana ... nguing ... Nepal ... nguinggg ... oh anggun +sekali, memakai ... di ... dunia ... srok ... para pemimpin negara ... anak- +anak melambai ... taaa ... nguing ... Lady Diana ... srok tersenyum ... oh +... nguingg ... nginggg ... nguiiiiiing .... + Saat Langit +Menjadi Biru + +SETELAH hujan lebat, matahari bersinar lagi. Bersama +angin yang tenang, ombak terlempar ke pesisir dalam ben- +tuk gulungan-gulungan kecil, semakin lama, semakin pelan, +semakin lemah, laksana armada yang lelah bertempur di te- +ngah samudra, kalah, lalu pulang. + + Batu-batu granit sebesar rumah, yang telah tertanam di +pesisir sejak masa jura—berarti paling tidak 150 juta tahun— +termangu-mangu. Di punggungnya hinggap beberapa ekor +burung camar, gesit mematuki teritip, ribut berebut sisa-sisa +makanan dan bermain-main dengan bungkus plastik yang +ditinggalkan turis lokal. Sesekali menjerit, nyaring, panjang, +dan sepi. + + Perahu-perahu nelayan yang ditambatkan di dermaga +dimain-mainkan ombak, bunyi mereka saling terantuk me- +nambah sepi. Pohon ketapang menunduk saja. Angin, sang + 136 ~ Andrea Hirata + +laksamana, bahkan tak dapat menggerakkan selembar pun +daunnya. + + Sepasang burung terakup yang tadi kehujanan berteng- +ger malas di dahan pohon santigi. Burung yang berpembawa- +an murung itu tampak semakin melankolis karena sayapnya +basah. Para pegawai warung duduk menatap laut dengan +wajah kuyu, mengutuki hujan dalam hati, bosan seharian me- +nunggu pembeli es kelapa muda yang datang satu-dua, dan +mereka, burung camar dan terakup tadi, serta siapa pun yang +berada di pantai, sama sekali tak menduga sesuatu yang luar +biasa akan terjadi. + + Tiba-tiba langit berubah menjadi biru, pantai menjadi +biru, pasir dan batu-batu menjadi biru. Bahkan, kambing- +kambing di padang dekat pesisir menjadi biru, rumputnya +juga, gembalanya juga. Semuanya biru, megah, memesona, +misterius. + + Sesekali keajaiban alam yang menakjubkan itu terjadi +di pantai barat Belitong. Namun, hanya sekitar Februari dan +hanya sekejap, tak lebih dari satu menit. Menurut para ahli, +fenomena itu—mereka menyebutnya blue moment—terjadi ka- +rena posisi matahari, rotasi bumi, lapisan uap air di udara +setelah hujan, temperatur, pembiasan cahaya, dan hal-hal +yang semakin kujelaskan, kau akan semakin bingung, Kawan, +sebab sebenarnya aku tak begitu mengerti. + + Orang kampung menyebutnya saat langit menjadi biru, +konon telah berusia lebih tua daripada usia umat manusia + Ayah ~ 137 + +dan di dunia ini hanya terjadi di pantai barat itu. Terbitlah +kepercayaan, jika saat langit menjadi biru itu muncul, tahun itu +akan menjadi tahun yang baik. Musim hujan takkan berke- +panjangan, musim kemarau takkan keterlaluan. Timah akan +lebih mudah didapat, ikan lebih gampang dipukat, lada ber- +buah lebat. Dan, ini yang seru, barang siapa yang mampu +menahan napas selama saat langit menjadi biru itu berlangsung, +berarti paling tidak enam puluh detik, akan gampang dapat +jodoh. + + Karena itu, Februari adalah bulan yang paling mende- +barkan bagi para bujang lapuk di kampung kami. Jika Feb- +ruari tiba, berbondong-bondonglah mereka ke pantai barat. + + Sabari tak pernah percaya, tetapi tahun ini dia berniat +ke pantai barat. + + “Apa? Kau juga mau ikut-ikutan ke pantai?” Ukun men- +cibir. + + “Ya, dan harusnya kau dan Tamat juga ikut.” + “Tak sudi!” kata Tamat. “Mengapa kau percaya sama +dongeng?” + “Tapi, ada buktinya.” + “Bukti apa?” + “Karena sering ke pantai barat, Muharam dapat istri +PNS.” + “Itu bukan karena langit menjadi biru, itu karena perempu- +an itu kena tipu Muharam!” + “Mereka yang ke pantai itu adalah orang-orang yang tak +laku!” bentak Ukun. + 138 ~ Andrea Hirata + + “Lihatlah kita-kita ini,” tangkis Sabari. + “Orang-orang yang putus asa karena cinta!” Ukun me- +mihak Tamat. + “Lihatlah kita-kita ini.” + Sahut-menyahut Ukun dan Tamat mencemooh Sabari. + Subuh keesokannya, Sabari menyelam ke dalam tong +berisi air sambil membawa jeriken kosong lima liter. Dia tak +muncul sebelum jeriken itu penuh. Dia melatih diri untuk me- +nahan napas sebab legenda mengatakan, jika ingin harapan +terkabul, harus mampu menahan napas paling tidak enam +puluh detik selama langit menjadi biru berlangsung. + Tentu tiap hari dia jadi bulan-bulanan Ukun dan Tamat. +Sabari tak hirau, tetap tekun berlatih. Setelah berminggu- +minggu dia bisa mengisi jeriken minyak tanah sepuluh liter, +artinya dia mampu tak bernapas hampir selama 150 detik! +Hampir tiga menit, fantastis. Sedikit lagi dia bisa mengalah- +kan anak buaya muara. + Pendamba Cinta + +TANGGAL 1 Februari, pulang kerja, Sabari langsung berse- +peda ke pantai barat. + + Bukan main terkejutnya dia melihat keramaian di sana. +Orang-orang datang dari berbagai penjuru kampung, bahkan +ada yang datang dari pulau-pulau sekitar Belitong. Mereka +datang naik perahu, naik sepeda, naik motor, dan menyewa +bus. + + Merekalah para pendamba cinta, pria maupun wanita. +Ada yang telah diperlakukan dengan buruk oleh cinta, ada +yang memupuk harapan untuk memulai babak baru dalam +hidupnya, dan yang mengais semangat untuk mencoba ke- +sempatan kedua. Semuanya berharap jodoh, tetapi Sabari +hanya mau jodoh yang khusus, yaitu Lena. Hanya Lena. + + Sayangnya saat langit menjadi biru tidaklah terjadi setiap +tahun. Sebulan penuh selama Februari, setiap sore Sabari ke +pantai barat, tak terjadi apa-apa di sana. Pada hari terakhir + 140 ~ Andrea Hirata + +Februari dia melihat senja yang megah. Warna merah dan +jingga pecah di angkasa. + + Malam pertama Maret, Sabari tak bisa tidur. Semua +upaya untuk mendapatkan dan melupakan Lena telah gagal. +Akankah nasibnya berakhir seperti nasib Florentino Ariza? +Harus menunggu 52 tahun baru mendapat cinta Fermina +Daza. Sabari miris. Marlena telanjur lekat dalam benaknya +seperti nyawa lekat pada tubuhnya. Dipertimbangkannya se- +buah rencana terakhir, akankah gagal lagi? + + Malam kian larut. Sabari memegang pensil. Dadanya +sesak. Dia rindu kepada Lena. + +Setelah menimbang segala hal, akhirnya Sabari memutuskan +untuk menempuh rencana terakhir itu. Orang-orang bisa +menduga dia mau bunuh diri karena tak sanggup menang- +gung durjana cinta, oh, tidak, tidak ada sifat-sifat berkecil hati +seperti itu dalam diri tokoh kita. + + Rencana terakhir itu adalah dia akan pulang ke Belan- +tik lalu melamar kerja di pabrik percetakan batako punya +Markoni, ayah Marlena, yang dia tahu pabrik itu berada di +samping rumah keluarga Markoni. Maksudnya, meski hanya +melihat sandal jepit Lena yang sudah putus, jauh lebih baik +ketimbang dia tinggal jauh di Tanjong Pandan dan menderi- + Ayah ~ 141 + +ta setiap hari disiksa rindu. Sudah kukatakan kepadamu, Ka- +wan, tak ada sifat-sifat berkecil hati dalam diri Sabari. + + Sabari senang bekerja di pabrik es. Juragan dan kawan- +kawan sesama kuli sudah seperti saudara baginya. Maka, +secara bersungguh-sungguh, sebagai satu sikap hormat dan +sayang kepada mereka, dia membuat tiga lembar surat peng- +unduran diri, yang bolehlah dikatakan amat puitis. + + Meski tak sekolah + Tapi kambing bangun pagi + Sapi bangun lebih pagi lagi + Dengan penuh kerendahan hati + Aku Sabari bin Insyafi + Menulis surat ini untuk mohon diri + + Begitu perihal dalam suratnya. Dikatakannya pula da- +lam surat itu bahwasanya pekerjaan di pabrik es telah mem- +berinya pencerahan dan satu cara pandang yang berbeda me- +ngenai manusia sebagai ciptaan Tuhan yang Agung. + + Bahwa es bukanlah sekadar benda biasa, tetapi juga ber- +jasa dalam mengurangi penderitaan ikan-ikan yang meregang +nyawa dengan mata memelotot di pasar ikan sana. Bahwa es +sudah ada dalam peri kehidupan manusia sejak mula pera- +daban. Bahwa es bukanlah sekadar benda mati yang dingin +jika disentuh, melainkan sebuah benda besar faedah yang ba- +nyak sekali membuka lapangan kerja bagi orang susah. Bah- + 142 ~ Andrea Hirata + +wa tak terbilang banyaknya kebaikan, prestasi, dan pemikiran +cemerlang umat manusia dihasilkan saat sedang duduk sendi- +ri sambil minum teh. + + Dan tahukah kau, Kawan, apa yang ada dalam teh itu? + + Sabari bertanya secara retorik dalam suratnya. + + Tahukah? + Es. + Itulah benda yang ada di dalam gelas teh itu. + Es, tak lain tak bukan, es. + Oleh karena itu, menurut hematku, para pemilik pabrik es dan +karyawannya adalah orang-orang yang disayangi Tuhan. + + Sabari mengakhiri surat dengan satu puisi. + + Persahabatan kita indah tak terperi, sehingga rembulan menjadi iri + Salam tangan memeluk badan (karena dinginnya gudang es) + Dalam dekapan rindu, kawanmu selalu, + S, dan A, B, R, dan I + + Tentu berat juragan melepas pegawai yang berseni ting- +gi, pintar berpuisi, jujur, rajin, dan penyabar. + + “Mengapa harus berhenti, Ri?” + “Karena saya ingin memulai hidup baru, Nya.” + Ayah ~ 143 + + “Oh, mau menikah?” + Sabari tersipu. + “Kurang lebih begitulah, Nya.” + “Susah mencari pegawai macam kau, Boi, tapi kalau +mau menempuh hidup baru, apa hendak dikata. Itu lingkar- +an nasib, tak dapat dihalangi, takdir, aku maklum, maklum +sekali.” + “Terima kasih, Nya.” + “Siapakah perempuan yang berbahagia itu?” + “Beruntung, Nya.” + Nyonya agak bingung. + “Maksudnya?” + “Saya yang berbahagia, dia yang beruntung.” + “Oh, ojeh, maksudku, siapakah perempuan yang berun- +tung itu?” + Sabari tersipu lagi. + “Namanya Marlena, Nya.” + Wawancara + +HANYA sehari setelah mengundurkan diri dari pabrik es di +Tanjong Pandan, Sabari telah berada di Kelumbi, tepatnya +di kantor Markoni. Bukan satu-dua orang yang mengingat- +kan tokoh kita itu soal watak Markoni, bahwa dia memang +orang jujur, tetapi berkepala batu, pemberang bukan buatan. +Kalau bicara sekehendak mulutnya. Ungkapan bahwa kata- +kata tidak meminjam, cuma-cuma, dan barang siapa yang +banyak bicara akan selamat dapat dilihat dalam diri Marko- +ni. Namun, Sabari tak gentar. Kiranya satu batalion tentara +Napoleon pun tak dapat menghalangi langkahnya menuju +Marlena. Menghadapi Markoni, Sabari sadar betul bahwa +dia memasukkan kepala bola bekelnya itu ke mulut singa. + + “Apa maksud kedatangan Saudara?!” tanya Markoni. + “Mencari kerja, Bang.” + “Pertama-tama!” Tak ada angin tak ada ombak, Marko- +ni langsung naik tensi. “Saudara datang ke sini mencari kerja, + Ayah ~ 145 + +jangan pernah lupakan itu! Bahwasanya, bukan saya, Marko- +ni, yang mengajak Saudara bekerja! Tapi, Saudara sendiri, +yang kampungan ini, menunduk-nunduk datang kepada saya +untuk mencari kerja! Camkan itu! Digarisbawahi itu! Jangan +pernah Saudara lupa, bahwa Saudara yang datang pada saya! +Markoni! Bukan saya yang datang pada Saudara!” + + “Ya, Bang.” + “Kedua!” Suara Markoni makin tinggi. “Saya bukan +abangmu! Saya tidak pernah dilahirkan ibumu! Ibu saya tak +pernah menikah dengan ayahmu, sehingga saya adalah abang +tirimu. Kalaupun itu terjadi, saya tak sudi menjadi abang dari +orang tengik macam Saudara ni!” + “Iya, Ba ... Ba ....” + “Pak! Itulah panggilan sopan santun orang di sebuah +perusahaan yang modern!” + “Iya, Pak.” + Sekarang terungkap mengapa Markoni tadi muntab. + “Nama Saudara?!” + “Sabari bin Insyafi.” + “Kalau menjawab, tegas! Jangan seperti orang kurang +vitamin E begitu!” + “Sabari bin Insyafi!” + “Mencetak batako perlu ketegasan! Sikap pasti, teliti, ce- +pat, waspada, bijaksana, tidak ragu! Orang-orang yang ber- +jiwa lemah dan tidak punya pandangan jauh ke depan tidak +bisa bekerja mencetak batako!” + 146 ~ Andrea Hirata + + “Baik, Pak.” + “Apakah Saudara pernah mendengar kata opportunity?!” + “Belum pernah, Pak.” + “Opportunity! Artinya, kesempatan emas! Batako saya di- +pakai untuk membangun sekolah. Maka, ini adalah kesempat- +an emas bagi Saudara untuk membuat hidup Saudara yang +tak berguna itu menjadi berguna. Bekerja di pabrik saya ber- +arti membantu pemerintah mencerdaskan kehidupan bangsa. +Jangan Saudara sepelekan itu! Apakah Saudara mengerti apa +yang saya bicarakan ini?!” + “Mengerti, Pak.” + “Asal Saudara?!” + “Belantik.” + “Oh, Belantik!?” Markoni muntab lagi karena teringat +usaha rental alat-alat musiknya yang diperlakukan semena- +mena oleh para musisi amatir dari Belantik. + “Apakah Saudara seorang pemain musik?!” + “Bukan, Pak.” + Markoni tenang sedikit. + “Saudara tahu lagu-lagu?” + “Lumayan, Pak.” + “Lagu apa yang hafal?” + “‘Terajana’, Pak.” + “Saya juga hafal lagu itu. Hafal lagu ‘Minar Com­ +blangku’?” + “Tidak, Pak.” + Ayah ~ 147 + + “Pernah sekolah?” + “Pernah.” + “Ijazah terakhir?” + “SMA.” + “Nilai Matematika di ijazah terakhir?” + “Enam.” + “Saya dulu delapan.” + Siapa yang bertanya? + “Bisa bahasa Inggris?” + “Sedikit.” + “Apa benar kudengar kabar orang Belantik kalau makan +berkeringat kalau bekerja tidak?” + “Benar, Pak.” + “Punya hobi?” + “Punya, Pak” + “Apa?” + “Membuat puisi.” + “Hobi macam apa itu?!” + Sabari tersenyum. + “Kalau melihat muka Saudara, sebenarnya saya tidak +mau menerima Saudara. Tertekan batin saya melihat muka +Saudara.” + Sabari tersenyum lagi. + Sejak itu bekerjalah Sabari di pabrik Markoni. + Kue Satu + +NUN terpojok di Pasar Manggar, di kios jahit Serasi, meneri- +ma jahitan baju lelaki, perempuan, anak-anak, dewasa, baju +tradisi, baju masa kini, Izmi, sang pemilik kios, tahu sepak +terjang Sabari di Tanjong Pandan, dan tahu bahwa dia telah +kembali ke Belantik, demi cinta sebelah tangannya kepada +Lena. + + Setelah Tamat dari SMA, Izmi tak pernah mening- +galkan Belantik. Cita-citanya untuk menjadi dokter hewan +belum mati, hanya pingsan lagi. Namun, dia tetap optimis. +Untuk sementara dia menjadi tukang jahit. Sabari terus men- +jadi inspirasinya. Dia belajar dengan tekun untuk menjadi +penjahit jempolan. Dalam waktu singkat dia menjadi sangat +terampil. Dia adalah Isaac Newton dalam bidang menjahit. + + Tak pernah Izmi berbicara dengan Sabari, bahkan tak +pernah bertegur sapa. Namun, baginya Sabari telah mengu- + Ayah ~ 149 + +capkan banyak hal untuknya, tanpa harus membuka mulut +dan memperlihatkan gigi tupainya itu. + + Sesekali Izmi mengunjungi Zuraida, yang dulu bercita- +cita menjadi pramugari dan sekarang menjadi tukang kue +satu. Selalu ditanyakannya kabar Sabari dan terpana Izmi +mendengar kisah hidup lelaki bak sandiwara radio itu. Kalau +ada orang di dunia ini yang dapat membuatnya menjadi dok- +ter hewan, orang itu adalah Sabari. + + Adapun Sabari sendiri riang sentosa di pabrik batako +Markoni. Dia bekerja sambil bersiul-siul dan bersisir setiap +ada kesempatan. Pekerjaan berat, ringan saja baginya. Si- +kapnya yang polos, periang, auranya yang sangat positif, dan +tingkahnya yang agak eksentrik, telah membawa suasana +baru di dalam pabrik sehingga dengan cepat dia disenangi +rekan-rekan sesama kuli. Kehadirannya membuat pabrik per- +cetakan batako meriah. + + Sabari begitu gembira, apakah lantaran dia menerima +upah yang besar? Tidak juga. Apakah lantaran dia tiba-tiba +menjadi tampan? Mustahil. Semuanya tak lain tak bukan ka- +rena Lena. Yaitu, sesuai dengan apa yang dibayangkannya +sebelum bekerja di pabrik itu, di sela-sela pekerjaannya, se- +kali-sekali, meski hanya berkelebat sepintas, macam tikus +diuber meong, dia bisa melihat Lena, dan hal itu lebih dari +cukup untuk membuatnya berangkat tidur dalam keadaan +tersenyum simpul, tidur dalam keadaan tersenyum lebar, dan +bangun tertawa. Sebaliknya, Lena yang kemudian tahu Sa- + 150 ~ Andrea Hirata + +bari bekerja di pabrik ayahnya di samping rumah mereka, +dan tahu strategi udang di balik batu yang tengah diluncur- +kannya, memuncak bencinya kepada si Gigi Tupai itu. + + Dalam waktu singkat, Sabari segera hafal sepak terjang +Lena, misalnya pukul berapa dia keluar rumah, pukul berapa +dia pulang, hari apa dia tidak pulang, serta lelaki mana saja +yang mengantarnya pulang. Sabari juga tahu bahwa hanya +berselang sebentar setelah Lena sampai di rumah, pasti me- +letus pertengkaran sengit antara dia dan ayahnya. Teriakan- +teriakan mereka terdengar sampai ke pabrik dan rumah- +rumah tetangga. Semula Sabari terkejut, tetapi karena hal itu +selalu terjadi, lama-lama dia terbiasa. + + Kata Sabari kepada Ukun dan Tamat, setiap pukul 5.00 +sore, dia bersiap-siap di pekarangan pabrik. + + “Rupanya telah terjalin hubungan batin antara aku dan +Lena.” + + “Maksudmu?” + “Kalau kudengar bunyi motor dari jauh, kutempelkan +telingaku ke tanah dan aku tahu berapa motor yang meng- +antar Lena pulang. Aku juga tahu Lena membonceng motor +siapa.” + “Yang benar?” Alis Tamat naik. + “Ya, dengan menempelkan telingaku di tanah aku pun +tahu merek motor yang memboncengkan Lena. Senin, Lena +diantar pria naik motor Honda bebek Super Cub. Selasa, Ya- +maha L2G. Rabu, Kawasaki Binter. Kamis, Honda CG 100. +Jumat, Vespa VX150. Sabtu, sepeda keranjang.” + Ayah ~ 151 + + “Minggu?” tanya Ukun. + “Aku tak tahu.” + “Mengapa tak tahu?” + “Karena aku libur.” + “Oh.” + “Bahkan, aku tahu warna baju yang sedang dipakai +Lena.” + “Hanya dengan menempelkan telinga wajanmu itu ke +tanah?” Tamat mulai jengkel. + “Ya.” + “Mungkin kau bisa tahu berapa liter bensin yang ada da- +lam tangki-tangki motor itu, Ri! Atau kau tahu jumlah uang +dalam dompet Lena.” Tak tahan Tamat mendengar omong +kosong itu. + “Yang jelas lebih banyak daripada jumlah uang dalam +dompetmu, Mat.” + Tamat panas. + “Dapatkah kau tahu bahwa Dra. Ida Nuraini sedang me- +nuju arahmu untuk membawamu ke panti rehab kejiwaan?!” + Sabari tak berkutik. + Biru +Karena Rindu + +LIHAINYA waktu menipu. Tak terasa setahun cincai. Sabari +telah bekerja di pabrik Markoni. Pulang kerja, dia senang +karena kembali ke kebiasaan lama, yaitu mendorong kursi +roda ayahnya, keliling kampung, saling berkisah, menyitir pu- +isi sambil memandangi matahari terbenam di muara Sungai +Lenggang. + + Ayahnya yang berjiwa seni, melihat apa pun selalu terin- +spirasi. Kawanan burung punai melintas menyerbu bakung, +ayahnya berseru: + + Wahai warna-warni yang berkelebat! + Tak sudikah singgah sebentar? + Hinggap di hatiku yang biru + Mengharu biru karena rindu + Ayah ~ 153 + + Sabari tersipu, dia tahu, ayahnya menyindirnya melalui +puisi, direka-rekanya puisi balasan: + + Wahai Punai yang berkelabat + Terbang-terbanglah terus ke barat + Karena aku sedang ingin sendiri + Sendiri, rindu, indah terperi + + Sabari mensyukuri keputusannya pulang ke Belantik. +Dia merasa jauh lebih gembira ketimbang tinggal di Tanjong +Pandan. Dia senang bisa dekat dengan ayah dan ibunya dan +bahagia bisa melihat Lena, meski Lena selalu bersama orang +lain. Sesungguhnya tak banyak yang diminta lelaki lugu itu +dari hidup ini. + + Sabari menambah kesibukan dengan memelihara kam- +bing. Kambing-kambing itu adalah bantuan pemerintah +untuk orang melarat. Jadilah dia peternak kecil. Ternyata, +Sabari tak hanya punya bakat terpendam di bidang menulis +puisi, tetapi juga di bidang memelihara kambing. + + Berbeda dari kambing orang lain, kambing dalam na- +ungan, bimbingan, dan pengayoman lelaki penyabar itu lebih +sehat dan cepat hamil. Petugas dari Departemen Peternakan +pusat datang meninjau dan memuji Sabari habis-habisan se- +hingga Sabari merasa celananya kekecilan. Peternak kambing +teladan, kata mereka menjuluki Sabari. Penyuluh tersenyum, +Sabari tersenyum, Menteri Pertanian tersenyum, kambing- + 154 ~ Andrea Hirata + +kambing juga tersenyum. Orang-orang bertanya kepada Sa- +bari bagaimana kambingnya bisa hamil dengan cepat. Ada +saja teorinya, sebagian besar tak masuk akal dan mencakup +hal-hal yang tidak sopan jika ditulis dalam sebuah novel. + + Maka, ironi kembali terjadi dalam hidup Sabari. Dia +yang mengalami paceklik berkepanjangan, kemarau kering +kerontang, dalam hal cinta, tiba-tiba menjadi konsultan as- +mara bagi kaum kambing. Dan, dia sangat menikmati pro- +fesi sampingan itu. Rela dia mendatangi kampung yang jauh +demi membantu seorang peternak. Kenyataannya, setelah +ditanganinya, dia menyebutnya terapi puisi kambing, embek- +embek itu pada hamil. + +Adapun Markoni merasa beruntung telah menerima orang +yang sempat dipandangnya sebelah mata, tetapi ternyata dia +keliru. Sabari ternyata sangat rajin dan berdisiplin. Setiap ta- +hun CV Nuansa Harmoni, punya Markoni, yang bergerak +di bidang konstruksi, khususnya penyedia bahan bangunan, +terkhusus lagi batako berkualitas tinggi, mengadakan acara +penganugerahan penghargaan bagi karyawan teladan. Ta- +hun ini Sabari terpilih. + + Acara digelar di dalam pabrik. Telah disediakan podi- +um di situ. Markoni menghadapi mik. Mik menguik sedikit. +Diberinya kode dengan tangan, sekretaris mendekatinya dan + Ayah ~ 155 + +menyerahkan sebuah map. Pasti berisi naskah pidato. Gaya +Markoni mirip inspektur upacara. + + Markoni meminta Sabari berdiri di sampingnya. + “Seperti telah Saudara-Saudara maklumi, saya Mar- +koni, ayah saya Razak, istri saya Maryati, anak saya empat, +adalah pemilik, sekaligus komisaris, sekaligus direktur utama, +sekaligus direktur operasi, sekaligus mandor kawat di pabrik +ini.” + Puluhan karyawan tertib menyimak. + “Kalau boleh saya minta tepuk tangannya?” + Meriahlah tepuk tangan. Kemudian, semua karyawan +sudah tahu karena selalu terjadi setiap tahun, yakni Markoni +akan berpidato panjang lebar soal perjuangan masa lalunya, +kesialan yang dialaminya akibat durhaka kepada ayahnya, se- +runya dia diuber-uber polisi pamong praja waktu masih jadi +pedagang kaki lima, lalu wajahnya akan terharu mengenang +bahwa di puncak penderitaan hidupnya, dia mendapat ilham +dari melihat anak-anak pulang dari sekolah, kemudian dia +punya pabrik batako, bolehlah disebut sebagai pabrik yang +terpandang di Belitong. Tak lupa bahwa dia telah mendapat +penghargaan dari Dinas Koperasi Daerah sebagai wiraswas- +tawan panutan. + Tak tampak Markoni membaca naskah pidato yang di- +serahkan sekretaris tadi. Maka, tak jelas kertas apakah yang +ada di depannya itu. Pidato setengah jam itu sesekali diselingi +kalimat, “Kalau boleh saya minta tepuk tangannya?”. + 156 ~ Andrea Hirata + + Tepuk tangan meriah lagi. + “Kesimpulannya, pertama, dengar baik-baik nasihat +ayahmu. Kedua, pabrik batako kita ini adalah tulang pung­ +gung pembangunan sekolah. Maka, buatlah batako yang kuat, +liat, tangguh, macam kawan kita kuli mentah Sabari ini.” + Sabari tersenyum bangga. + “Ketiga, juga seperti Sabari, jujur! Jangan kau kurangi +takaran semen jika mencetak batako. Batako kita harus ta- +han gempa bumi minimal tujuh skala Richter. Kalau kau cu- +rang, akibatnya bisa fatal. Sekolah bisa roboh, murid-murid +dan guru-guru yang mulia bisa celaka. Biarlah orang-orang di +luar sana makmur sentosa karena mencuri, kita jangan! Meski +susah, kita harus jujur.” + Tepuk tangan bergema lagi. Markoni terkenal keras, +tetapi sangat adil kepada karyawannya, karena itu dia amat +dicintai. + “Cerdik cendekia berkata, kejujuran bermula dari pela- +jaran di sekolah, mereka tak keliru, tapi kurasa perlu ditam- +bah bahwa kejujuran bermula dari kejujuran membangun +sekolah. Apakah kalian para kuli setuju?” + Teriakan setuju gegap gempita. + Markoni memberi kode lagi, sekretaris mendekati dan +menyerahkan sebuah medali. Jauh-jauh di Pangkal Pinang, +Markoni memesan medali besar dengan sepuhan warna ku- +ning, demi mengapresiasi karyawan terbaiknya. + Ayah ~ 157 + + Sabari menunduk takzim waktu Markoni mengalungi- +nya medali. Dia merasa seperti atlet Olimpiade peraih medali +emas cabang loncat indah. Tepuk tangan tak henti-henti un- +tuk tokoh kita itu. + Medali Keemasan + +SEMANGAT Sabari melambung gara-gara penghargaan itu. +Sebagaimana biasa, fokusnya tetaplah Lena. Dengan berba- +gai cara, dia berupaya agar Lena tahu bahwa dia telah terpi- +lih sebagai karyawan teladan. + + Kepada sekretaris Markoni, seandainya sempat ngobrol +dengan Lena, Sabari berpesan supaya membawa-bawa bica- +ra soal karyawan teladan tahun ini. Jika lewat di depan ru- +mah Lena, Sabari memakai medali yang besar itu. Melirik +pun Lena tidak. + + Melalui Zuraida, Sabari minta tolong disampaikan ke- +pada Lena bahwa dia adalah karyawan teladan dan telah +mendapat medali yang hebat. + + “Rai, tolong bilang padanya betapa tak mudahnya, be- +tapa ketat persaingan untuk mendapat medali itu. Aku pun +tak menyangka bisa terpilih.” + Ayah ~ 159 + + “Ojeh, Boi.” + “Bilang juga, kalau dia mau melihat medali itu, silakan +saja, dengan senang hati akan kutunjukkan padanya. Tak ada +keberatan sama sekali.” + “Ojeh, Boi.” + Berikutnya, Zuraida pening karena Sabari bertanya te- +rus bagaimana tanggapan Lena soal medalinya itu. + “Belum ada jawaban!” Zuraida jengkel. “Kalau ada ja- +waban, nanti kusampaikan padamu, tunggu saja!” + Seminggu kemudian Zuraida tersenyum kepada Sabari. +Tergopoh-gopoh Sabari menghampirinya. + “Pasti Lena sudah menjawab, ya.” + “Sudah.” + Sabari gugup. + “Apa jawabannya, Boi?” + “Jawabannya, no comment!” + Tak habis akal, Sabari menempuh jalan yang pasti ber- +hasil menarik perhatian belahan jiwanya itu, yaitu, dia sudah +tahu Lena suka lewat jalan sebelah mana di pekarangan ru- +mahnya, dia pun sudah hafal jadwalnya. Diletakkannya me- +dali itu di tengah jalan, seolah-olah telah terjatuh dari saku- +nya. + Sabari bersembunyi di balik pohon mengkudu, berde- +bar-debar menunggu Lena lewat. Namun, yang lewat ter- +bungkuk-bungkuk adalah nenek Lena. Dilihatnya medali itu, +dipungutnya. Bingung dia melihat benda berkilauan, kalau + 160 ~ Andrea Hirata + +tak buru-buru dicegah Sabari, hampir saja nenek melempar- +kan medali itu ke dalam parit. + + Berbagai upaya untuk menarik perhatian Lena soal me- +dali itu telah gagal. Namun, Sabari tak berkecil hati. Tahun +depan dia ingin menjadi karyawan teladan lagi, begitu pula +tahun depannya, dan tahun depannya lagi. Kalau dia bisa +menjadi karyawan teladan selama tujuh tahun berturut-turut, +tak mungkin Lena tak tahu. + +Selebihnya, semua berlangsung seperti sediakala. Sabari +bangun subuh, mengurus kambing, bekerja, merasa berun- +tung jika sekilas saja dapat melihat Lena, pulang, mengurus +kambing lagi, ngobrol dengan ibunya, mendorong kursi roda +ayahnya ke dermaga, saling bercerita dan berbalas puisi sam- +bil menyaksikan matahari terbenam di muara, malamnya du- +duk di beranda, menyaksikan cahaya bulan jatuh di padang +ilalang. Dia merindukan Lena hingga jatuh tertidur sambil +menggenggam pensil. Keesokannya terbangun, dia masih +menggenggam pensil itu. + + Hari berganti minggu, minggu menjadi bulan, lancar +dan tenteram, tak terjadi hal luar biasa sampai suatu hari +Markoni dibisiki Buncai di warung kopi Kutunggu Jandamu, +tentang siapa sebenarnya lelaki buruk rupa, berkening lutung, +bergigi tupai, bernama Sabari itu. + Ayah ~ 161 + + “Waspada, Pak Cik, berbahaya!” + “Maksudmu?” + “Sabari itu leboi cap belacan!” + “Leboi?” + “Istilah masa kini, artinya laki-laki mata keranjang! Tiap +tikungan dia punya pacar! Tak terbilang banyak korbannya!” + “Yang benar kau, Cai.” + “Shasya sampai mau bunuh diri, menceburkan diri di +bendungan, dibuatnya. A Moi hampir minum air aki, untung +ketahuan Baba Liong.” + Terperanjat Markoni. + “Maksud Sabari bekerja di pabrik Pak Cik, sebenarnya +dia mengincar anak bungsu Pak Cik.” + Berdiri bulu tengkuk Markoni. + “Lena?” + “Kecuali Pak Cik punya anak bungsu di tempat lain.” + “Jangan kau sembarang bicara, Cai! Istriku Maryati dan +hanya Maryati. Satu pun aku repot mengurusinya!” + “Tentu Lena, siapa lagi?” + Buncai mendekatkan bangkunya ke Markoni dan berbi- +sik, “Sabari biasa merayu lewat puisi, itulah modalnya. Lihai +sekali dia memakai puisi untuk melampiaskan nafsu hewani- +nya! Dia itu penyalah guna puisi! Waspada, Pak Cik, puisinya +penuh racun!” + Markoni memukul meja. + “Sialan!” + 162 ~ Andrea Hirata + +Tak ambil tempo, keesokannya Markoni langsung mengon- +frontasi Sabari. + + “Ri! Apakah kau tahu maksudku memanggilmu?!” + Kena labrak pagi-pagi, bahkan belum sempat ngopi, Sa- +bari kalang kabut. + “Ti ... tidak, Pak.” + “Apakah kau merasa ada yang salah?!” + Sabari mengamati dirinya sendiri, dari atas ke bawah, +lalu memasukkan bajunya. + “Ini bukan soal baju kulimu itu!” + “Baiklah, Pak.” + “Jadi, kau tak tahu mengapa aku memanggilmu?!” + “Tidak, Pak.” + “Aku memanggilmu karena Lena!” + Sabari kaget. + “Mengapa Lena, Pak?” + “Jangan kura-kura dalam perahu!” + “Baiklah, Pak.” + “Kau suka sama Lena, ya?!” + Sabari kaget lagi, tetapi dengan cepat menguasai diri. + “Ya, Pak.” + “Nah, ketahuan belangmu!” + “Ya, Pak.” + Ayah ~ 163 + + “Kau bekerja di sini karena mau bertemu dengan +Lena?!” + + “Ya, Pak.” + “Tertangkap basah kau!” + “Ya, Pak.” + “Aih, licin sekali muslihatmu ya, sampai terpilih menja- +di karyawan teladan segala. Kau itu serigala berbulu domba, +lihai macam intel Melayu, tapi aku adalah mata-mata KGB! +Aku lebih lihai daripada kau! Kau sangka bisa mengelabuiku, +Boi?!” + “Tidak bisa, Pak.” + “Apa benar kau sering merayu Lena pakai puisi racun- +mu itu?!” + “Aku memang banyak membuat puisi untuk dia, Pak.” + Peringatan Buncai ternyata bukan isapan jempol, Mar- +koni naik pitam. + “Begitu, ya?! Kalau begitu, akan kuusulkan pada peme- +rintah agar membuat kantor yang mengeluarkan izin orang +berpuisi! Lalu, kumintakan tanda tangan penduduk seluruh +Belitong ini agar kantor itu tidak mengeluarkan sertifikat ber- +puisi untuk kau! Agar orang bejat macam kau dapat dihenti- +kan!” + “Ya, Pak.” + Turun-naik dada Markoni karena muntab. Matanya me- +rah macam buah saga, urat-urat leher betonnya bertimbulan, +dan dia heran melihat Sabari yang pasrah saja. + 164 ~ Andrea Hirata + + “Mengapa kau tidak membela diri?! Ayo, Boi! Kita ber- +tengkar! Aku sedang ingin bertengkar! Mana puisi pembela- +anmu?!” + + Sabari menunduk. + “Sebelum minum kopi aku tak bisa membuat puisi, Pak.” + “Oh, ini kopiku!” Markoni mengambil gelas kopi di me- +janya, diberikannya kepada Sabari. “Minum! Minum!” + Sabari mengambil gelas itu dan minum, wajahnya me- +ngerut. “Telalu pahit, Pak.” + Markoni menggeleng-geleng. “Maksudmu, kau tak bisa +membuat puisi karena kopi itu terlalu pahit?!” + Sabari mengangguk. + Markoni mengempaskan tubuhnya ke tempat duduk. +Lama ditatapnya Sabari yang menunduk saja. Dia segera sa- +dar orang seperti apa yang ada di depannya itu. + “Boi, sudah berapa lama kau suka sama Lena?” Nada +suara Markoni turun dua oktaf. + Sabari melirik jam bulat yang tertempel di dinding. + “11 tahun, 5 bulan, 4 hari, 3 jam ... 4 menit, Pak.” + Markoni terpana. + “Apakah Marlena suka sama kau, Boi?” + Sabari tersenyum-senyum simpul. + “Wajar-wajar! Kalau kutinjau-tinjau, wajahmu memang +agak berat, Boi. Muka bulat tak punya dagu, bibir macam +dilemparkan sekehendak hati saja oleh seseorang sambil naik +sepeda, lalu mendarat di bawah hidungmu yang bentuknya + Ayah ~ 165 + +macam tatakan kue kembang itu. Mata sayu menimbulkan +rasa kasihan. Telinga macam telinga wajan, gigi tupai. Maaf, +Boi, semua itu adalah unsur-unsur yang paling dihindari pe- +rempuan dewasa ini.” + + Sabari tersenyum lagi. Hidup ini memang dipenuhi orang- +orang yang kita inginkan, tetapi tak menginginkan kita, dan sebaliknya, +dan Sabari tetap tersenyum. + Konfigurasi + +ADA yang berbeda hari-hari itu, yaitu saban malam Sabari +bermimpi aneh. Dia sedang menyabit rumput di tengah pa- +dang, tahu-tahu dia mendengar suara. + + “Apa kabar, Bang!” + Sabari menoleh ke sekeliling, tak ada siapa-siapa, kecuali +kambing-kambingnya. Ah, dalam hatinya, terlalu banyak me- +lamunkan Lena membuatnya mendengar suara-suara. + “Apakah Abang sehat-sehat saja?!” + Sabari terkejut tak kepalang karena yang menanyakan +kabarnya itu adalah kambing di depannya. Kambing terse- +nyum. Sabari terbangun, bersimbah keringat. + Malam keesokannya dia bermimpi serupa. Namun, kali +ini dia berkawan dengan kambing yang supel itu. Mereka +berkenalan secara baik-baik dan saling bertanya soal keada- +an kawan dan handai tolan. Keesokan malamnya lagi mereka +berdiskusi panjang lebar soal stabilitas politik dalam negeri. + Ayah ~ 167 + + Tak ayal, Sabari berpikir mengapa dia dilanda mimpi- +mimpi yang ganjil itu. Satu firasat yang tak bisa dipastikan- +nya, apakah buruk, ataukah baik, melandanya. + + Adapun keadaan di pabrik biasa saja, di rumah Lena +juga rutin saja, yaitu hampir setiap hari terdengar pertempur- +an sengit Lena versus Markoni. Namun, pertengkaran sore itu +berbeda, yakni disertai bunyi benda-benda pecah. Hal itu tak +pernah terjadi sebelumnya. + + Sabari suka malas berkaca karena sering heran sendi- +ri melihat telinganya yang lebar macam telinga wajan. Hari +ini dia mengerti, untuk keperluan siang inilah mengapa nasib +memberinya bentuk telinga seperti itu. + + Waktu pertengkaran itu meletus, jarak Sabari dengan +TKP kira-kira 75 meter, cukup jauh, tetapi dia tahu Markoni +muntab luar biasa lantaran Lena dengan segala jambalaya as- +maranya akhirnya mengalami semacam peristiwa di luar rencana +dan situasi itu harus segera diatasi sebab nama baik Markoni +dipertaruhkan. Sabari tegang, otaknya berputar cepat, jan- +tungnya berdegup-degup. + + Keributan itu berlangsung berhari-hari karena keputus- +an harus segera diambil. Dan Lena, karena satu dan lain hal +yang kurang sopan dibahas di dalam novel, bingung menetap- +kan keputusan. Ditanyai Markoni, dia disorientasi. Semuanya +begitu gampang diduga, yaitu diperlukan seseorang untuk +menyelamatkan situasi. Selama berhari-hari itu pula Sabari +tak bisa tidur, ketar-ketir dia mengantisipasi apa yang akan + 168 ~ Andrea Hirata + +terjadi. Sekarang dia paham makna mimpi kambing pandai +bicara itu. Tuhan selalu menghitung, dan suatu ketika, Tuhan +akan berhenti menghitung. Inilah saatnya suatu ketika itu. + + Apakah kemudian Sabari ditumbalkan Markoni? Be- +gitukah drama ini berlangsung? Segampang itukah kejadi- +annya? Tidak, sama sekali tidak. Yang terjadi adalah Sabari +menumbalkan dirinya sendiri. Dengan perasaan waswas dia +mendekati seseorang bernama Tabrani. + + “Ni, katakan pada Rosmala, kalau Markoni memerlu- +kan bantuanku, untuk mengawinkan kambing misalnya, aku +siap sedia, seratus persen, jiwa dan raga.” + + Berkerut kening Tabrani. + “Apa maksudmu, Ri? Setahuku, Markoni tak punya +kambing, bantuan apa? Tak paham aku.” + “Aih, janganlah kau panjang tanya. Sampaikan saja, +nanti Rosmala pasti tahu maksudnya.” + Sebelum menemui Tabrani, Sabari sudah bicara dengan +Rosmala. + “Kak, kalau Kakak menerima kabar dari Tabrani, pin- +dah tangankan kabar itu pada Syamsir.” + Sudah barang tentu Rosmala heran. + “Kabar apa, Ri?” + “Aih, janganlah Kakak ni banyak tanya lagi. Sampaikan +saja pada Syamsir. Sebelum dan sesudahnya kuucapkan teri- +ma kasih.” + Ayah ~ 169 + + Sebelum menemui Rosmala, Sabari rupanya juga te- +lah menemui Syamsir dan Safar. Syamsir adalah saudara +tiri Safar. Safar bekerja di kios minyak tanah milik seseorang +bernama Pardi Lihai. Pardi Lihai adalah saudara dua pupu +seseorang bernama Salamah. Salamah tak lain ketua arisan +beras yang berkongsi dengan Mia. Mia berkongsi dengan A +Mung, A Mung berkongsi dengan Jalal, Jalal ada main sama +Narti, Narti berkongsi dengan Arbi, Arbi berkongsi dengan +Mainap. Nah, Mainap ini tak lain saudara sepupu Marko- +ni. Setiap orang itu masing-masing telah diberi amanah oleh +Sabari seperti amanahnya kepada Rosmala. Sasaran tembak +Sabari yang sesungguhnya adalah Markoni. Mengapa Sabari +menggunakan konfigurasi komunikasi yang sangat rumit dan +tidak masuk akal semacam itu? Misteri. Kemungkinan besar +karena dia ingin menyembunyikan taktiknya. + + Ajaib, akhirnya pesan itu sampai ke telinga Markoni. + “Ni,” kata Mainap. + “Apa, Nap,” jawab Markoni. + “Kalau kau mau kawin lagi, Sabari siap menyumbang +kambing untukmu, katanya dia siap seratus persen, siap sedia +jiwa dan raga.” + Karena melalui banyak tangan, boleh jadi pesan itu te- +lah terkorupsi. Dan, bukan main jengkelnya Markoni karena +dia tahu akal bulus Sabari. Dia juga jengkel karena dihadap- +kan pada pilihan yang sulit. Dipalingkan wajahnya ke luar +jendela. Nun di situ, di tengah pekarangan rumah, tanpa sedi- + 170 ~ Andrea Hirata + +kit pun berusaha melindungi diri dari guyuran hujan yang le- +bat, berdirilah lelaki yang telah diabaikan cinta selama sebelas +tahun itu. Dialah pilihan yang sulit itu. + + Siang itu Markoni memanggil Sabari dan menawari- +nya untuk menikahi Lena. Lena ada di situ, duduk membatu +menghadapi meja. Markoni meninggalkan mereka. Sabari +gemetar. Sinar matahari menembus celah tirai keong, terpan- +tul di atas dulang tembaga di tengah meja, tempias menampar +wajah Lena. Tak berkedip Lena menatap lelaki buruk rupa +yang dengan gagah berani telah menumbalkan diri untuknya. + + Si sulung angin mengarak si bungsu awan ke timur. +Awan mengambang dan mengintip ke dapur rumah Marko- +ni melalui terali jendela. Awan takjub melihat seorang lelaki +yang mencintai perempuan di seberang meja itu lebih dari +apa pun di dunia ini, sedangkan perempuan itu membenci +lelaki itu, lebih dari apa pun di dunia ini, dan mereka akan +segera menikah. Cinta sungguh, sungguh ajaib. + Stadium 3 + +WAKTU penghulu membimbing Sabari untuk akad nikah, +baru satu-dua kata penghulu bersabda langsung disambar Sa- +bari. Cepat sekali, macam tukang dadu cangkir menyambar +duit seribu. Sabari mengucap akad sekali saja, cerdas, fasih, +lancar, bahkan lebih lancar daripada penghulu. Ukun terpa- +na dan bertanya bagaimana Sabari bisa begitu hebat. + + “Aku sudah hafal ucapan nikahku pada Lena sejak kelas +tiga SMP,” jawab Sabari dengan tenang. + + Bulu kuduk Ukun merinding. + Sabari bersanding dengan Marlena adalah pemandang- +an paling mustahil yang pernah dilihat Ukun dan Tamat. Se- +mua yang hadir dalam perhelatan yang amat sederhana itu +kiranya sependapat dengan mereka. Acara itu semakin seder- +hana karena hanya sedikit yang datang. Orang-orang yang di- +undang menyangka undangan dari mulut ke mulut itu hanya +kelakar. Hanya bagian dari lelucon yang sudah kerap mereka + 172 ~ Andrea Hirata + +dengar soal cinta sebelah tangan Sabari dan Lena. Maka, me- +reka tak datang. + + Ukun dan Tamat duduk bersanding di bawah hiasan +daun-daun kelapa. Sabari tepat di depan mereka, posisi pukul +12.00. Sulit mereka memahami apa yang terjadi dalam waktu +yang amat singkat. Berkali-kali mereka mengucek mata dan +meyakinkan diri bahwa lelaki berwajah berantakan itu adalah +Sabari, dan perempuan manis bermata indah, berlesung pi- +pit nan dalam macam sumur di kantor polisi lama itu adalah +Marlena. Sebuah anomali, enigma, utopia. + + Sabari gagah dalam baju pengantin Melayu tradisional. +Dia tersenyum terus seolah ada peternakan senyum dalam +mulutnya. Marlena berbaju pengantin sederhana saja. Dia +menunduk, sesekali memandang lurus, kaku, dan dingin, mi- +rip patung Lenin. + + Ukun dan Tamat telah memberondong Sabari dengan +bermacam teori, pandangan, saran, kebijakan, petuah, con- +toh, dan cemooh selama bertahun-tahun, dan semua itu +patah, patah bingkas jadi dua di pelaminan itu. Mereka me- +mandang sekeliling dan tiba-tiba merasa gamang, miris lebih +tepatnya. Hampir tiga puluh tahun usia keduanya, segera ma- +suk bujang lapuk stadium tiga dalam ukuran orang Melayu +udik, seorang pun kenalan perempuan mereka tak punya. + + Kian miris keduanya melihat ke arah pukul 5.00, Ibu +Woeri dan Pak Roeslan Tadjoedin yang duduk berdampingan +di situ adalah guru SMA mereka dulu. Mereka memutuskan + Ayah ~ 173 + +hidup sendiri lantaran prahara cinta masa muda, kini mereka +bujang lapuk stadium empat, lanjut. Tak jauh dari kedua pen- +siunan guru itu ada Wak Doelmasin yang telah membujang +sejak masa Republik Indonesia Serikat. Situasinya sekarang +bujang lapuk stadium terminal. Ulu hati Ukun dan Tamat +ngilu macam disundul-sundul membayangkan nasib mereka +akan berakhir seperti Wak Doelmasin, yang duduk sendiri +saja di bawah untaian janur kuning itu, bersusah payah me- +naklukkan dendeng sapi. + Juru Puisi + +MESTINYA pukul 4.00 sore, Ukun dan Tamat sudah datang. +Jumat puisi, begitu Sabari menyebut pertemuan mereka se- +tiap Jumat sore di warung kopi Solider. Biasanya Sabari me- +nyitir puisi, sekadar menghibur kawan-kawannya, para kuli +tambang, usai seharian membanting tulang. + + Bergabung pula orang-orang kecil lainnya: para peda- +gang kaki lima, tukang reparasi jam, tukang reparasi elek- +tronik, tukang semir sepatu, serta mereka yang menyenangi +puisi. Mereka suka melihat Sabari beraksi. Sesekali mereka +pun membaca puisi. Sabari-lah yang memulai kebiasaan unik +itu. Mereka yang suka obrolan cinta datang ke warung kopi +Usah Kau Kenang Lagi. Yang suka obrolan sepak bola ke wa- +rung kopi Tarmizi dan Anak-Anaknya, sejak 1947. Yang suka +obrolan politik ke warung kopi Respek dan Demokrasi. Yang +suka puisi, ke warung kopi Solider. + Ayah ~ 175 + + Sebenarnya, Tamat ingin segera ke warung kopi, tetapi +dia disemprot majikannya. Belakangan, tepatnya sejak Sabari +kawin, dia sering melamun saat mengipasi satai. Akibatnya, +satai hangus. Dia kena SP 1 (surat peringatan 1). Hal itu da- +patlah disebut skandal sebab Tamat adalah pegawai bermutu +tinggi. Majikan tak habis mengerti apa yang terjadi padanya. +Namun, Tamat mengerti apa yang terjadi padanya, yaitu dia +mau seperti Sabari, dia mau punya istri, itulah penyebab satai +menjadi arang. + + Hal serupa ternyata dialami Ukun. Beberapa pelanggan +mengeluh, kapasitor pompa air mereka meletus gara-gara +voltase dinamo terlalu tinggi. Yang menggulung dinamo itu +Ukun. + + Ukun juga pegawai andalan dengan pengalaman ta- +hunan. Dia tekun, terampil, tak pernah memeleset. Boleh +jadi di seluruh Provinsi Sumatra Selatan dialah yang paling +jago menggulung dinamo. Juragan bertanya dengan lembut +kepada karyawan kesayangannya itu, mengapa pekerjaannya +tidak seperti biasanya. + + “Tegangan dinamo tinggi karena tegangan saya sendiri +tinggi, Pak, sebab saya mau punya bini, Pak,” jawab Ukun. + + Alhasil, Tamat dan Ukun tahu kepada siapa mereka ha- +rus menumpahkan kekesalan atas hidup mereka yang tadinya +tenteram, lalu mendadak kacau balau. + + “Terus terang,” kata Tamat, “dunia ini tak pernah adil!” + 176 ~ Andrea Hirata + + “Setuju!” teriak Ukun. Perlahan-lahan pengunjung wa- +rung kopi merapatkan bangku ke arah mereka. + + “Tengoklah, Kawan-Kawan, nyata-nyata aku dan Ta- +mat lebih tampan daripada Sabari, nyata macam matahari +bulan Juni. Namun, yang dapat istri dia, kami gigit jari, ka- +rena itu aku tersinggung!” seru Tamat disambut gelak tawa. + + “Dari segi pekerjaan, kami tak kalah,” kata Ukun. + “Dari segi upah, apalagi!” + “Apa yang kau bisa dan aku tak bisa, Ri? Apa?!” + Sabari menunduk. + “Semua yang kau bisa, aku bisa, dua kali lebih baik da- +ripada kau!” + “Semua yang aku bisa, belum tentu kau bisa! Coba kude- +ngar, apa yang akan kau katakan sekarang?!” bentak Tamat. + Dipermalukan di muka umum, Sabari menunduk se- +makin dalam. Betapa tega, padahal Ukun dan Tamat ada- +lah sahabat terdekatnya. Namun, kemudian pelan-pelan dia +mengangkat wajahnya. + “Februari sebentar lagi, mungkin sebaiknya kalian ke +pantai barat sana, siapa tahu dapat jodoh!” + Berderai-derailah tawa. + Subuh keesokannya, seperti dilakukan Sabari dulu, +Ukun dan Tamat menenggelamkan diri ke dalam tong berisi +air dingin dengan membawa jeriken kosong. Mereka mela- +kukan sesuatu yang tempo hari bertubi-tubi mereka cemooh, +dan mereka segera timbul dengan bola mata seperti mau me- +loncat. + Ayah ~ 177 + + Sabari mampu menyelam sampai penuh jeriken sepuluh +liter. Nyawa Ukun dan Tamat rupanya lebih pendek. Setelah +berhari-hari berlatih, Ukun hanya bisa mengisi botol kecap. +Tamat hanya bisa mengisi botol kecil minyak wangi sinyong- +nyong. + Ayah +yang Bersembunyi + +RUMAH tangga Sabari dimulai dengan sangat unik. Yaitu +Lena tetap tinggal di rumah orangtuanya dan Sabari di ru- +mah orangtuanya juga. Tak pernah meski hanya sehari, apa- +lagi semalam, Lena tinggal dengan Sabari. + + Tentu Sabari berharap Lena tinggal dengannya, untuk +itu dia membangun rumah sederhana di Jalan Padat Karya, +dekat rumah orangtuanya. Selama bekerja, sejak menjadi kuli +pabrik es di Tanjong Pandan, dia telah menabung. Tabungan +sedikit itulah yang dipakainya untuk membangun rumah. + + Berbulan-bulan Sabari membangun rumah itu dengan +tangannya sendiri. Rumahnya khas Melayu kampung. Sebu- +ah rumah panggung yang rendah, berdinding papan, beratap +rumbia, tetapi istimewa, ada beranda. + + Beranda itu tak sekadar beranda, tetapi sebuah rencana. +Rencana yang manis berlinang madu. Dibayangkannya sete- + Ayah ~ 179 + +lah Lena melahirkan, mereka akan tinggal di rumah itu. Di +beranda rumah itu Sabari akan menggendong si bayi mungil, +mengayunnya dalam pelukan. Jika teringat akan hal itu, mes- +ki tengah malam, dia bergegas ke rumah yang belum jadi itu. +Dikerjakannya apa pun yang bisa dikerjakannya agar rumah +itu cepat selesai. + + Setelah beberapa bulan, rumah kecil itu rampung. Sa- +bari pindah dari rumah orangtuanya ke rumah itu dan tinggal +sendiri. Setiap sore dia duduk di beranda rumahnya sambil +memandangi padang ilalang dan mereka-reka nama anaknya +yang akan segera lahir. + + Jika anaknya lelaki, dia sudah punya pilihan nama: Ta- +bahi, Tekuni, Ta’ati, atau Jujuri. Dicoba-cobanya kepantasan +nama-nama itu. + + “Jujuri, siapakah yang menceburkan sepeda Ayah ke da- +lam sumur?” + + “Aku, Ayah.” + “Oh, tak percuma kau kuberi nama Jujuri, Boi.” + Sabari melihat kiri-kanan, kalau-kalau ada orang meli- +hatnya bicara sendiri. + “Tabahi, apakah kau merasa sedih tidak naik kelas?” + “Tidak, Ayah.” + “Oh, kagum sekali Ayah akan ketabahan hatimu, Boi.” + Kalau anaknya perempuan, Sabari sudah pasti dengan +satu nama saja: Kemasi. Dia ingin anaknya rajin berkemas- +kemas. + 180 ~ Andrea Hirata + +Barangkali, perasaan yang mustahil dilukiskan dengan kata- +kata adalah perasaan orang menunggu kelahiran anak. Sa- +bari disergap perasaan senang yang aneh selama membangun +rumah kecilnya itu sambil menunggu Lena melahirkan. Pera- +saan senang itu kemudian terwujud dalam bentuk lebih tekun +bekerja, lebih menghargai dan lebih sayang pada apa pun. + + Oleh karena itu, dia terpilih lagi sebagai karyawan pab- +rik teladan. Tepuk tangan gemuruh waktu Markoni, untuk +kali kedua, mengalunginya medali. Sabari tersenyum, antara +lain karena tak perlu mengumpulkan tujuh medali untuk me- +narik perhatian Lena, sebab Lena sudah jadi istrinya. Mau +meledak dada Sabari mengenang semua itu. + + Di tengah kegembiraan itulah, sore Minggu itu Sabari +terperanjat melihat ibu mertuanya tergopoh-gopoh menda- +tanginya. Sabari menyongsongnya. Kata ibu mertuanya, di +rumah sedang tak ada siapa-siapa dan Lena harus segera di- +bawa ke klinik karena sakit perut. + + Sabari terpaku macam patung, lalu mendadak dia berla- +ri pontang-panting ke rumah Lena. Sampai di sana disambar- +nya sepeda yang ada. Direngkuhnya Lena, dinaikkannya ke +boncengan seperti menaikkan karung beras enam puluh kilo, +lalu dilarikannya perempuan hamil tua itu dengan cara me- +nuntun sepeda tanpa menyadari bahwa dia akan lebih cepat +jika sepeda itu dinaikinya. Seorang lelaki dengan wajah pa- + Ayah ~ 181 + +nik menuntun sepeda dan seorang perempuan dengan perut +yang besar duduk di boncengannya, terpontal-pontal di atas +jalan berbatu-batu, membuat orang-orang yang melihatnya +terpingkal-pingkal. Apalagi, mereka tahu itu Sabari, yang se- +lalu menjadi bahan tertawaan mereka. + + Sore itu pula, saat angin barat Oktober bertiup kencang +dan matahari menghamburkan cahaya jingga nan bergelo- +ra, pecah di atas langit Belitong, lahirlah bayi lelaki mungil +disertai satu lengkingan hebat bernada F, mirip lengkingan +Soprano Kiri Te Kanawa dalam lagu “I Dreamed a Dream”. +Tak lama kemudian lengkingan itu reda dan makhluk mungil +itu menggerung-gerung macam anak kucing. + + Sabari melirik bayi itu. Napasnya tertahan melihat pipi +dan kening berair-air, hidung mungil dan mulut lembut bak ke- +lopak mawar. Bayi itu bak sebongkah cahaya. Sabari gemetar +karena melihat bayi itu dia menemukan seseorang yang selama +ini bersembunyi di dalam dirinya. Orang itu adalah ayah. + +Akhirnya, semua yang diidamkan Sabari satu per satu men- +jadi kenyataan. Lena dan bayi lucu itu pindah dari rumah +Markoni ke rumah yang baru dibangunnya. Keluarga kecil, +rumah kecil, kebahagiaan besar, begitu perasaan Sabari. + + Sayangnya perasaan Lena berbeda dengan Sabari. Dia +segera kembali ke hobi lamanya. Mulanya dia pergi sebentar, + 182 ~ Andrea Hirata + +lalu pergi lama, lalu menginap, lalu tak pulang-pulang. Untuk +membuat cerita panjang menjadi pendek. Dia tak bahagia. +Jiwanya terlalu rebelious, penuh pemberontakan, untuk terikat +kepada seorang suami dan anak. Apalagi, suami itu tak pernah +diinginkannya. Baginya, tak ada hal yang lebih mengerikan di +dunia ini selain terjebak dalam pernikahan yang tak bahagia. + + Sabari tak pernah ribut-ribut, apalagi semua hal rasanya +beres jika dia melihat bayi yang tumbuh dengan cepat dan +merona-rona itu. Matanya selalu berbinar, mulutnya selalu +tersenyum. Dia selalu rindu kepada Lena, tetapi Zorro telah +menjadi pengganti Lena, dengan kegembiraan yang berlipat- +lipat. + + Sabari membelikan anak itu boneka Zorro. Si kecil +menggenggamnya, tak pernah mau melepaskannya. Jadilah +Sabari menamainya Zorro. Jika mendengar Sabari menyebut +Zorro, anak itu menoleh-noleh mencari sumber suara, lalu +tergelak-gelak. Di telinga Sabari tawanya seperti air hujan +yang berjatuhan di danau. + + Dari wajah anak kecil itu setiap orang dapat menduga +apa yang telah terjadi. Wajah anak itu lonjong macam biji +buah tandong. Wajah Sabari macam bola bekel. Telinganya +macam pucuk daun sirih. Telinga Sabari macam telinga +wajan. Anak itu tampak sangat cerdas. Sabari tampak jauh, +asing, terpencil dari sesuatu yang berbau ilmu dan sekolah. + + Persamaannya dengan Sabari hanya satu, yaitu sama- +sama murah senyum. Kata para tetangga, si kecil yang meng- + Ayah ~ 183 + +gemaskan itu berkarisma. Jika dia menangis, tangisnya keras +bukan kepalang sehingga kayu-kayu yang menopang atap +rumbia menggeletar. Paku-pakunya mau copot. Jika dia men- +jerit mau minum susu, tikus-tikus kabur ketakutan. Namun, +jika dia tertawa, tikus-tikus ngerem mendadak, ingin menyi- +mak tawanya yang lucu. Burung kutilang di sekitar rumah +seakan ikut tertawa. Zorro menatap langit-langit, dengan +matanya yang berkilau macam kelereng, mulutnya berbunyi +ba ... ba ... ba ... sambil menunjuk cicak. Cicak berkerumun +memperhatikannya. + + Betapa Sabari menyayangi Zorro. Ingin dia memeluk- +nya sepanjang waktu. Dia terpesona melihat makhluk kecil +yang sangat indah dan seluruh kebaikan yang terpancar da- +rinya. Diciuminya anak itu dari kepala sampai ke jari jemari +kakinya yang mungil. Kalau malam, Sabari susah tidur lan- +taran membayangkan bermacam rencana yang akan dia la- +lui dengan anaknya jika besar nanti. Dia ingin mengajaknya +melihat pawai 17 Agustus, mengunjungi pasar malam, mem- +belikannya mainan, menggandengnya ke masjid, mengajari- +nya berpuasa dan mengaji, dan memboncengnya naik sepeda +saban sore ke taman balai kota. + + Sabari terjerumus ke dalam dunia baru yang membuat- +nya terpukau setiap hari. Satu dunia yang dulu sering diba- +yangkannya, tetapi dalam kenyataan ternyata jauh berlipat- +lipat pesonanya. Ayah di dalam dirinya melonjak-lonjak, tak +sabar ingin memperlihatkan diri pada dunia. + 184 ~ Andrea Hirata + + Sabari adalah ayah sekaligus ibu bagi Zorro, full time. Dia +menyuapi Zorro dan meminuminya susu. Dia terjaga sepan- +jang malam jika anak itu sakit. Dia telah mengalami saat-saat +panik waktu si kecil demam. Dia membawanya ke puskesmas +seperti layaknya dilakukan seorang ibu. Dia tahu perkara gizi +balita, vaksin, dan obat anak-anak. Bahkan, dia sering mem- +beri tahu ibu-ibu lainnya soal itu. Pesan Sabari, bayi jangan +terlalu sering diminumi air tajin, kalau terlalu sering, nanti +jika besar tak bisa matematika macam Toharun, Ukun, dan +Tamat. + + Selayaknya orang mengurus bayi, dia harus selalu bera- +da dekat anaknya itu, 24 jam. Oleh karena itu, dengan berat +hati, dia menulis sepucuk surat. + + Ke hadapan: + Yth. Bapak Markoni bin Razak + Pimpinan CV Nuansa Harmoni + di tempat + Perihal: Permohonan perkenan pengundurkan diri se- + bagai karyawan atas nama Sabari bin Insyafi + Ayah ~ 185 + + Aku, waktu, dan kawan-kawanku. + + Kulihat kawan-kawanku di laut + Kulihat kawan-kawanku di lubang-lubang tambang + Kulihat kawan-kawanku di sudut-sudut pasar + Kulihat kawan-kawanku di pabrik-pabrik + “Hai, tahukah kau?” Kawanku bertanya + “Kawanmu sudah pergi.” + Kulihat waktu telah memberiku semuanya + Kulihat waktu mengambil semuanya + “Tidakkah kau bersedih, Kawan?” tanya kawanku + Tidak, karena waktu juga kawanku + + Markoni duduk sendiri, dekat jendela warung kopi, +membaca tiga lembar surat pengunduran diri Sabari. Terha- +ru dia membaca puisi perpisahan sebagai pembuka surat dari +lelaki yang lugu itu. + + Sebagai pemimpin pabrik, merasa terhormat dia mem- +baca bahwa Sabari sangat mencintai pekerjaan dan rekan- +rekan kerjanya, dan bahwa dia telah bertekad untuk menjadi +pegawai teladan paling tidak tujuh kali berturut-turut. + + Sebagai mertua Sabari sekaligus kakek dari anak kecil +itu, tersentuh dia membaca bahwa Sabari mengundurkan diri +dari pekerjaan karena harus mengurus anaknya, dan betapa + 186 ~ Andrea Hirata + +dia merasa dirinya diberkahi karena mendapat kesempatan +itu. + + Sebagai seorang ayah, membaca surat Sabari, dia sendi- +ri merasa bangga menjadi seorang ayah. + + Kata Sabari: + + Janganlah bersedih, waktu mengambil seorang sahabat, dan waktu +akan menggantikannya dengan sahabat yang lain. Berdamailah dengan +waktu, karena waktu akan menumbuhkan dan menyembuhkan. + + Demikianlah kiranya surat pengunduran diri ini saya tulis. Atas +perkenan, perhatian, dan pengertian dari Bapak, saya haturkan ribuan +terima kasih. + + Dengan hormat seribu takzim, + Sabari bin Insyafi + + Tembusan; + 1. Yth. Kepala Desa Belantik, untuk perhatian: Yth. Juru Tulis + + Kantor Desa + 2. Yth. Ketua Dewan Kemakmuran Masjid Al-Hikmah + 3. Yth. Kepala Polisi Pamong Praja + 4. Yth. Pengurus Karang Taruna Belantik + 5. Segenap pimpinan dan karyawan radio AM Suara Cinta, + + untuk perhatian: Yth. Penyiar Acara Tembang Buluh Perindu. + 6. Pertinggal + Aya + +FEBRUARI yang ditunggu-tunggu Ukun dan Tamat akhir- +nya tiba. Hari pertama Februari, pulang kerja, keduanya ber- +gegas naik sepeda ke pantai barat. Semangat mereka meletup, +apalagi mereka telah berlatih menahan napas. Di pantai me- +reka berjumpa dengan begitu banyak orang seperti mereka, +yang mau mengubah nasib cinta yang gelap. + + Setiap sore, tak pernah absen, kedua sahabat itu ke pan- +tai barat, tetapi sampai hari terakhir Februari, langit tak kun- +jung menjadi biru. + + Adapun Sabari, setelah mengundurkan diri bekerja di +pabrik Markoni, membuka warung sembako di rumahnya. +Pekerjaan di warung dan memelihara kambing memungkin- +kannya untuk selalu berada dekat Zorro. Semuanya sangat +menyenangkan, apalagi sejak ada Zorro, keajaiban terjadi se- +tiap hari di rumah Sabari. + 188 ~ Andrea Hirata + + Ukun dan Tamat sering ke Belantik karena mereka pun +telah jatuh hati kepada anak itu. + + “Ini Pak Cik Ukun,” Sabari mengenalkan Ukun kepada +Zorro. + + “Om Ukun,” kata Ukun mengoreksi. + Sabari menoleh kepada Tamat. “Om Tamat.” + Dengan bersemangat Sabari bercerita bahwa pada +umur lima bulan anaknya sudah bisa duduk, umur enam bu- +lan sudah bisa merangkak. + “Bagaimana logikanya?” tanya Tamat. + “Anak kecil duduk dulu, baru merangkak.” + “Bisa saja, bagaimana dia mau beristirahat kalau dia le- +lah merangkak, tentu dia akan duduk,” bantah Sabari. Benar +juga. + “Tidak mungkin itu.” Ukun memihak Tamat. + “Kalau anak kecil lelah waktu merangkak, ya dia akan +diam saja, diam di tempat seperti kambing parkir.” Masuk +akal. + Sabari tak terima. “Yang punya anak aku, bukan kalian! +Yang tahu aku. Bagaimana kalian bisa tahu, pacar saja tidak +punya, membaca novel tidak pernah!” + “Cabut kata-katamu, Boi! Apa hubungannya anak bisa +duduk dengan novel?!” Ukun panas. + Sebagaimana biasa, meletuslah debat kusir. Ukun pasti +memihak Tamat. Dua lawan satu. + Ayah ~ 189 + + “Tentu ada hubungannya. Tak ada orang yang suka +membaca novel yang tidak pintar. Cari kalau ada, tak ada! +Kuperkirakan nanti Zorro sudah bisa berjalan umur sembi- +lan bulan, jarang ada anak kecil macam itu, aku yakin umur +sebelas bulan dia sudah bisa bicara.” + + “Mungkin umur dua belas bulan, Zorro sudah bisa bica- +ra bahasa Indonesia dengan ejaan yang disempurnakan, Ri!” +Ukun kesal. + + “Yang pasti kalau SMA nilai Bahasa Indonesia-nya akan +lebih baik daripada nilaimu.” + + Ukun mati kutu. + “Kau sendiri bagaimana, Kun? Waktu kecil kau bisa me- +rangkak dulu atau duduk dulu?” tanya Tamat. + “Oh, oh, aku anak normal, semua urutannya benar. +Pertama tidur-tiduran, bisanya merengek saja, lalu aku bisa +duduk, lalu merangkak, lalu berdiri, lalu berjalan sambil ber- +pegangan, lalu berjalan tanpa berpegangan, lalu berlari, lalu +bercakap, lalu bernyanyi, lalu mengaji, lalu naik sepeda roda +tiga, lalu naik sepeda roda dua, lalu naik motor, sebentar lagi +aku naik mobil.” Padahal, seumur-umur dia naik sepeda bu- +tut. + “Kau, Ri?” + “Oh, seusia Ukun bisa merangkak itu, aku sudah bisa +bernyanyi.” Sabari tak mau kalah. + “Kau sendiri?” Sabari bertanya kepada Tamat. + 190 ~ Andrea Hirata + + “Oh, oh, seusia kau bisa merangkak, aku sudah bisa +membaca!” + + Ukun tak mau kalah. + “Oh, waktu kau baru bisa duduk, aku sudah hafal Pem- +bukaan Undang-Undang!” + Debat kusir yang tadi sudah reda meletus lagi. + Marlena sendiri, ibu dari anak yang sedang diperdebat- +kan itu, tak tahu di mana rimbanya. Sudah berbulan-bulan +dia tak pulang. Markoni angkat tangan tinggi-tinggi meng- +hadapi anaknya yang susah diurus itu. Lagi pula, Lena sudah +punya suami, urusan rumah tangga Lena bukanlah urusan- +nya. + Macam-macam gosip tentang Lena telah didengar Sa- +bari. Bahwa Lena dekat dengan si ini dan si itu, bahwa Lena +lengket lagi dengan cinta pertamanya waktu SMA, Bogel +Leboi, dan mereka diam-diam suka ke Jakarta. Sabari tutup +mata tutup telinga. Perasaannya kepada Lena tak pernah ber- +ubah, pasti dan tetap. Dia selalu merindukannya seperti baru +mengenalnya dulu. Jika Lena pulang, Sabari memperhatikan +semua keperluannya, sayangnya Lena jarang pulang. + “Kau tunggu Lena? Sama dengan menunggu pepesan +kosong, menunggu jerat tak bertali, pungguk merindu bulan. +Kau pandai bahasa, tentu kau mengerti maksudku, Ri,” kata +Ukun. + “Perlukah kujelaskan?” kata Tamat. + Ayah ~ 191 + + “Aih, Kawan, apa yang kualami ini belum apa-apa. Ka- +lian tahu? Florentino Ariza menunggu cinta Fermina Daza +hampir 52 tahun! Aku, Sabari bin Insyafi mencintai Marlena +binti Markoni baru sebentar saja, belumlah seberapa.” + + “Siapa kau bilang?! Florintino Hamzah?” tanya Tamat. + “Florentino Ariza, bacalah buku sastra, Mat, novel, +Marquez!” + “Itulah masalah kau, Ri, teladanmu hal yang konyol, ki- +sah novel adalah fiksi, khayal, sama dengan dongeng!” + “Namun, bukankah fakta lebih aneh daripada fiksi?” Sa- +bari berkilah, pertengkaran meletus. + Beberapa minggu kemudian ada desas-desus Lena mau +menceraikan Sabari. Banyak orang memang sudah mendu- +ga kisah rumah tangga Sabari akan berakhir tak ubahnya +sandiwara radio Putri Limau Manis, tetapi dengan segenap +kenaifa­ nnya. Sabari tak percaya. Walau begitu, tak ayal dia +gelisah. + Sejak kabar itu beredar, Zorro tak pernah lepas dari +pandangannya. Jika Zorro tidur siang, dia menutup jendela +dan pintu rapat-rapat. Hatinya lega jika melihat Zorro masih +ada di situ, tidur melengkung di dipan. Zorro dapat merasa- +kan kecemasan ayahnya. Dia tak mau tidur jika tak dipeluk +ayahnya. Semua itu semakin menghancurkan hati Sabari. + Gosip perceraian itu kian hari kian gencar. Sabari tak ke- +ruan. Dia berharap semua itu hanya kabar burung. Di tengah + 192 ~ Andrea Hirata + +kekalutan itu, saat Sabari mau menidurkan Zorro, Zorro me- +natap ayahnya, lalu dari mulut mungilnya terdengar bunyi. + + “Aya, aya.” + Sabari tertegun. Itulah kata pertama yang diucapkan +anaknya. Perasaan Sabari melambung. Dipeluknya anaknya +rapat-rapat. + Semua +Telah Membeku +di dalam Waktu + +ULAR dan belut nyaris sama. Kambing dan domba serupa. +Bodoh dan dungu setali tiga uang. Tabib dan dukun sering +tertukar. Orkes dan band hanya soal istilah. Namun, tak ada +persamaan sama sekali antara Makmur Manikam dan JonPi- +jareli. + + Drs. Makmur Manikam adalah pegawai pemerintah di +Bengkulu, dengan pangkat III/c, Penata Muda. Adapun Jon- +Pijareli seorang musisi. Asli Pekanbaru, berkiprah di Medan. +Dia pemimpin band Setia Nada, satu band Top 40, artinya band +yang khusus membawakan empat puluh lagu yang sedang +top. + + Manikam pendiam, selalu menyembunyikan perasaan- +nya dan merupakan seorang yang berbakat menjadi pegawai +negeri sipil. Jon flamboyan, ekspresif, dan gitaris kelas satu. +Jarinya cepat. Dia bisa membawakan lagu “Terajana” dengan +bermain gitar sendiri saja, tetapi mencakup bunyi bas, ritem, + 194 ~ Andrea Hirata + +dan melodi. Minta ampun lihainya. Suaranya bagus. Kalau +dibawakannya lagu “Besame Mucho”, sambil meliuk-liukkan +gitarnya dan sesekali menyibakkan rambut gondrong Kenny +G-nya, beberapa perempuan tampak macam diserang de- +mam yang aneh. + + Jon banyak kawan, Manikam tidak. Kawannya hanya +tiga: Drs. Zulkarnain, Drs. Zulkifli, dan Drs. Zulham, dan +mereka menjadi kawan lantaran hubungan kerja. Secara ke- +tampanan, Manikam tak bisa dikatakan tampan, tetapi sikap +kalemnya membuat dia seakan-akan ganteng. Jon bolehlah +disebut—seperti kebanyakan gitaris—cakap. Wajahnya di +atas lumayan. + + Manikam tinggal di kawasan perumahan terpandang di +pinggir Kota Bengkulu. Mobilnya tipikal mobil kelas mene- +ngah untuk pegawai tetap yang selalu naik gaji secara ber- +kala sesuai peraturan gaji pegawai pemerintah. Dengan satu +istilah, Manikam dan keluarganya aman secara ekonomi. Jon +dan keluarganya selalu berpindah-pindah, bergantung ba- +nyaknya job. Ekonominya naik-turun bak gelombang sinus. +Kendaraannya motor antik BSA, meneguhkan kesan artistik- +nya. + + Di antara kawan-kawan kerjanya, Manikam selalu me- +ngatakan bahwa mereka adalah pegawai yang digaji dengan +uang rakyat, penerima amanah yang tak boleh sembarangan +saja bertabiat. Oleh karena itu, banyak yang tak betah bekerja +dengannya. + Ayah ~ 195 + + Adapun Boros Akinmusire, pemain trompet dalam band +Setia Nada berkata, “Repot sekali kalau ada Bang Jon, ngo- +mel saja kerjanya. Tapi, kalau tak ada, kami rindu. Tak man- +tap rasanya kalau tak ada dia.” + + Komentar itu diaminkan Obet Glasper, pada kibod—sa- +lah satu pemain kibod terbaik Sumatra, asli Binjai—Gandrik +Hoj, pada bas, Kris Dep, pada drum, Markus Stiklan, pada +saksofon, dan Palawijaya, pada gitar pengiring. + + “Bang Jon! Bang Jon!” seru siapa saja di pinggir jalan +kalau Jon melewati Jalan M. Yamin dengan sepeda motor- +nya yang gagah. Dia adalah selebritas lokal. Jon melambai +sambil tersenyum lebar. Rambut gondrongnya berkibar-kibar +diterpa angin, keren sekali. Jika Manikam lewat, orang-orang +hanya mengangguk pelan untuk menyapanya, hormat, men- +jaga, dan formal. + + Apa lagi? Semuanya berbeda antara Manikam dan Jon, +yang sama hanya satu, keduanya sedang mengalami krisis ru- +mah tangga tingkat gawat, yaitu digugat cerai istri masing- +masing karena alasan yang sama, istri tak lagi bahagia. + + Tak ada informasi lebih lengkap soal tidak bahagia itu. +Ada gosip Manikam dan Jon diam-diam mata keranjang. +Ada yang bilang bersangkut paut dengan politik kantor un- +tuk Manikam dan politik panggung untuk Jon. Ada pula yang +berspekulasi mungkin istri Manikam bosan pada kemapanan, +sedangkan istri Jon bosan dengan ketidakmapanan. Ironi dan +paradoks, memang selalu menjadi bagian paling memesona +dari cinta. + 196 ~ Andrea Hirata + +Kamis, Manikam menerima surat panggilan dari pengadilan +agama. Dia tak terkejut karena sudah tahu cepat atau lambat +surat itu akan datang. Dia pun tak langsung membukanya. + + Jumat pagi dia menyiapkan diri untuk berangkat ke +kantor sebagaimana biasa. Tak ada yang berbeda, rutin saja. +Apa-apa disiapkannya sendiri karena istri dan kedua anaknya +sudah beberapa waktu tinggal bersama mertua. + + Batik, pakaian dinas setiap Jumat, disetrikanya dengan +rapi. Dia berkaca bersisir. Semua dilakukannya dengan sa- +ngat tenang, bahkan lebih tenang daripada sebelum dia me- +nerima surat panggilan pengadilan. Sedikit pun dia tak ter- +pengaruh. + + Dibukanya koper untuk mengecek isinya. Pulpen Parker, +notes, kalkulator, kacamata baca, kacamata gaya, saputangan, +sisir jarang antirontok rambut, minyak kayu putih, minyak +wangi Quando Quando, minyak rambut El Confido, obat +pening kepala, sikat gigi, pasta gigi—ukuran hotel melati— +permen yang dapat menghindarkan mulut dari bau macam +tempat sampah, kaus kaki cadangan untuk mengganti jika +kaus kaki sudah berbau macam ban sepeda, gunting kuku, +brosur kartu kredit dengan hadiah langsung rice cooker dan li- +buran dua malam ke Nagoya (bukan Nagoya Jepang, melain- +kan Nagoya Batam), obat tetes mata, dipakai jika kebanyakan +melihat layar komputer, buku 15 Cara Gampang Membangun + Ayah ~ 197 + +Hubungan Lestari. Buklet laporan realisasi anggaran dari anak +buahnya yang dibacanya semalam dan harus didisposisinya +hari ini, foto istri dan anak-anaknya, semua sudah pada tem- +patnya. + + Manikam menutup koper, mengacak nomor kombinasi, +berjalan melintasi ruang tengah, dan tersenyum melihat foto +prewed-nya di dinding. + + Fotografer yang kreatif itu mengarahkan mereka berpo- +se di depan gudang peninggalan Belanda di sebuah perkebun- +an kopi. Calon istrinya duduk dengan wajah diarahkan untuk +sedikit cemas. Manikam berdiri di belakangnya, memanggul +sepucuk senapan antik. Makna foto itu tentu Manikam siap +jiwa dan raga melindungi istrinya nanti dari ancaman apa +pun di dunia ini, dan begitulah Manikam selalu berjanji ke- +pada istri dan dirinya sendiri. Tak diragukan, foto prewed itu +sarat akan makna. + + Dipanaskannya mobil, lalu dia meluncur. Karena masih +pagi, jalanan sepi. Anak-anak sekolah baru tampak satu-dua, +berjalan kaki atau bersepeda dengan rambut yang masih ba- +sah habis mandi dan terburu-buru ke sekolah. Yang berangkat +pagi-pagi itu pasti yang kena giliran piket di kelas. Manikam +kembali tersenyum. Dia senang melihat anak-anak berang- +kat ke sekolah masih pagi, membuat dia terkenang masa ke- +cil di Talang Betutu, lalu dia teringat pertemuan pertamanya +dengan istrinya di MTs di sana. Kini semuanya seakan telah +membeku di dalam waktu. + 198 ~ Andrea Hirata + + Mobil terus meluncur, di depan Manikam terbentang +Jalan Seruni yang panjang dan senyap. Kabut tipis mengam- +bang di pucuk trembesi yang berjajar di pinggir jalan. Tiba- +tiba Manikam merasa tak ada siapa-siapa di dunia ini selain +dirinya sendiri. Anak-anak yang berlari di pinggir jalan dan +berteriak memanggil kawan-kawannya seakan bergerak-gerak +dalam kebisuan. Manikam merasa pahit karena luput untuk +mengetahui bahwa selama ini istrinya tak bahagia. Ketidak- +bahagiaan bak musuh tersembunyi yang pandai menyerang +secara bergerilya, tersamar, diam-diam, mematikan. Enam +belas tahun pernikahannya, 44 tahun usianya. Manikam ga- +mang membayangkan apa yang akan terjadi di pengadilan +agama nanti dan miris membayangkan apa yang akan terjadi +setelah itu. + +Jon dan band-nya sedang mencoba-coba lagu ciptaan Jon +sendiri yang berjudul “Aku Berlari”, satu lagu dengan nuan- +sa reggaedut (reggae dangdut), saat seseorang berpakaian orang +kantoran mendatangi Jon dan menyerahkan sepucuk surat. + + Karena pembawaan yang selalu positif, Jon tersenyum +lebar menerima surat itu. Pikirnya, dan itu sudah sering terja- +di, surat itu adalah undangan alias job tampil. Namun, begitu +menyadari maksud surat itu, senyum Jon mendadak terisap +dari mukanya, secepat sedotan WC pesawat Merpati. + Ayah ~ 199 + + Dia panik. Ditinggalkannya latihan itu begitu saja. + “Mau ke mana kau?” tanya Boros Akinmusire. + Jon tak menjawab. Bergegas dia ke tempat parkir. Di- +engkolnya motor, siap meluncur, hampir saja dia lupa menge- +nakan helm. Lalu, memelesatlah dia dengan kecepatan ting- +gi. Berbelok dia ke arah Jalan Putri Hijau. Lampu merah di +muka kantor pos diterjangnya dengan semena-mena, padahal +kereta mau lewat, lalu di-geber-nya motor sejadi-jadinya me- +ngelilingi Lapangan Merdeka. + Yang mengenalnya heran melihat tingkahnya. Mereka +memanggil-manggilnya, tetapi Jon tak membalas sapa mere- +ka seperti biasanya. Bukan baru sekali istrinya minggat. Se- +lama bertahun-tahun sering pula istrinya mengancam akan +mengkhatamkan hubungan mereka, tetapi baru kali ini istri- +nya benar-benar serius. JonPijareli kalut. + +Nun jauh di pojok paling selatan Sumatra, di Pulau Belitong, +Sabari juga menerima surat panggilan dari pengadilan aga- +ma. Seorang lelaki berbaju safari—tersemat lambang Korps +Pegawai Republik Indonesia di atas saku kanan—dan berko- +piah mendatanginya. + + “Saudara Sabari bin Insyafi?” + “Saya, Pak, saya sendiri.” + “Apakah ada kesalahan dengan nama dan alamat ini?” + 200 ~ Andrea Hirata + + Sabari melongok, membaca nama dan alamat penerima +surat di tangan orang itu. + + “Kurasa tidak, Pak.” + “Saudara harus yakin sebab ini bukan surat biasa, ini +bukan surat tagihan iuran televisi, ini bukan surat imbauan +untuk bergotong royong Minggu pagi, ini bukan surat dari +sahabat pena atau surat gita cinta dari SMA, ini adalah surat +panggilan dari pengadilan, pengadilan negara, saya teguhkan +sekali lagi, apakah Saudara mengerti?” + “Mengerti, Pak.” + “Kesalahan penyampaian surat bisa punya akibat hu- +kum, bisa merugikan pihak penggugat atau tergugat. Kesalah- +an sepele bisa menyebabkan hukum sulit untuk ditegakkan. +Kita tidak bicara obrolan sehari-hari di sini, tapi kita bicara +kalimat-kalimat hukum. Oleh karena itu, tak jemu-jemu saya +teguhkan, apakah Saudara mengerti?” + “Mengerti, Pak.” + “Yakin?” + Sabari ragu. + “Apakah Saudara mengerti maksud saya?” + “Mengerti bagian mana maksud Bapak?” + “Semuanya, terutama bagian akibat hukum itu.” + Mirip karakter JonPijareli, Sabari selalu melihat sisi baik +dari segala hal. Panggilan dari pengadilan itu dalam pema- +hamannya mungkin bersangkut paut dengan penegasan sta- +tusnya sebagai ayah Zorro yang sering dipergunjingkan orang, + Ayah ~ 201 + +atau soal akta kelahiran Zorro, yang pernah ditanyakannya ke +kantor desa dan kades bilang bahwa itu urusan pengadilan +agama. Begitulah pemikiran Sabari soal kedatangan lelaki +berbaju safari empat saku itu. Tak ayal tokoh kita bertanya, +“Kalau boleh tahu, apakah isi surat itu, Pak?” + + “Maaf, saya adalah juru antar surat, penyampai amanah +yang diutus panitera pengadilan agama, saya tak berhak dan +tak boleh membicarakan isi surat yang saya sampaikan.” + + “Mengerti, Pak.” + “Baiklah, kalau begitu saya ulangi, apakah benar nama +Saudara adalah Sabari bin Insyafi, dengan alamat ini, bahwa +tak ada orang lain bernama sama di kampung ini? Bahwa +nama ini hanya Saudara, Saudara melulu, dan satu-satunya +Saudara?” + Sabari tercenung. Namanya dan seluruh niat di balik +nama yang diberikan ayahnya itu, agar dia menjadi orang +yang sabar, adalah hal yang sederhana, tetapi di mata hukum +ternyata bisa menjadi runyam. + “Setahu saya memang ada empat nama Sabari di Be- +lantik ini, Pak. Sabari tukang las, dia pegawai PN Timah, lo- +los PHK, dia dipindahkan meskapai ke Kundur, jadi sudah tak +di sini. Yang kedua, Sabari bin Sampani, bukan bin Insyafi. +Yang satu lagi tidak mungkin menerima surat panggilan se- +bab dia sudah dipanggil sendiri oleh Yang Mahatinggi karena +disambar petir tempo hari. Singkat kata, singkat cerita, surat +ini pasti untuk saya, Pak.” + 202 ~ Andrea Hirata + + Sabari tersenyum lebar untuk mencairkan suasana yang +membeku itu. Petugas tak terpengaruh. Baginya semua itu +tidak lucu, tetapi tragis. Sabari menghentikan senyumnya de- +ngan cara pahit. + + “Baiklah.” Juru antar membuka koper kecil model lama +dan mengeluarkan sebuah buku ekspedisi, persis buku utang +di warung Sabari. + + “Sila saudara terima surat ini dan tolong tanda tangan +di sini.” Juru antar menunjuk satu lokasi Sabari harus men- +cantumkan nama lengkap, tanggal, dan tanda tangan. Sabari +melakukannya dengan gesit. Senyumnya bersemi lagi. Petu- +gas heran. + + “Kalau boleh saya bertanya, mengapa Saudara senang +menerima surat panggilan dari pengadilan?” + + Sabari menatap petugas. + “Karena baru kali ini seumur hidup saya menerima +surat, Pak. Memang dulu sering juga saya menerima surat +untuk disampaikan kepada ayah saya, tapi itu surat pembe- +ritahuan agar melunasi tunggakan iuran sekolah. Jadi, baru +kali ini saya benar-benar menerima surat. Apalagi, surat ini +dikirim oleh instansi pemerintah! Untuk saya, Sabari, bangga +sekali saya, Pak.” + Juru antar ternganga sedikit mulutnya. Sabari menerima +surat dengan takzim. Diamati amplopnya, cokelat, tebal dan +kaku, nama dan alamat penerima diketik rapi. Zorro sedang + Ayah ~ 203 + +bermain dengan Abu Meong dan Marleni di bawah pohon +delima. + + “Lihat Zorro, Ayah menerima surat dari pemerintah!” +Sabari mengangkat surat itu tinggi-tinggi. + + Juru antar telah berpengalaman melihat berbagai intrik +rumah tangga, perbuatan culas untuk menguntungkan diri +sendiri, menelikung orang, mengakali aturan, tetapi hari ini +ditemukannya keluguan tak terbatas dari seorang lelaki sete- +ngah baya yang bahkan tak tahu prahara sedang menunggu- +nya di pengadilan nanti. + + Juru antar memandangi Zorro disertai pikiran getir yang +berkecamuk dalam kepalanya, tetapi dia berada di sana tidak +untuk menilai. Dia hanya seorang penyampai pesan, dan sore +ini akan menjadi salah satu sore yang tak terlupakan selama +dia mengabdi pada negara. + + “Itu anak saya, Pak, namanya Zorro.” + “Anak yang lucu.” + “Terima kasih, Pak. Kalau boleh bertanya, apakah Ba- +pak sudah punya anak?” + Juru antar tersenyum. + “Saya ayah untuk tiga anak.” Cara mengatakannya ter- +kesan dia tak sabar ingin menyelesaikan tugasnya, lalu pulang +dan memeluk anak-anaknya. Sabari mengerti perasaan itu. +Juru antar minta diri. + “Tunggu, Pak, tunggu sebentar.” Sabari bergegas masuk +ke rumah dan kembali dengan sesisir pisang. Diserahkannya + 204 ~ Andrea Hirata + +kepada juru antar. “Sekali lagi, terima kasih, Pak, ini oleh- +oleh untuk anak-anak Bapak, teriring salam dari saya dan +anak saya.” + + Sabari terkejut karena juru antar mengangkat kedua ta- +ngannya dan membuka jarinya lebar-lebar, mirip teller Bank of +America kena todong John Dillinger. + + “Maaf, saya tidak bisa menerima pemberian Saudara. +Saya ini aparat pemerintah. Apakah Saudara pernah mende- +ngar istilah gratifikasi?” + + Sabari berpikir sejenak. + “Gaya tarik bumi? Hukum pertama Tuan Newton? Me- +mang nilai Fisika saya selalu merah, tapi waktu SMA saya +pernah mendengar istilah itu.” + Juru antar tersenyum, menyalami Sabari, lalu melang- +kah pergi. + Sabari memandangi juru antar dengan kagum. Dia ka- +gum akan cara orang itu bertugas, dengan caranya melang- +kah, caranya menenteng koper, dan caranya mengatakan +bahwa dia seorang ayah bagi anak-anaknya. Sabari juga ka- +gum pada sepeda motor tua Yamaha bebek V 80-nya, yang +baru hidup setelah lebih kurang enam belas kali diengkol. + +Sepeninggal juru antar, Sabari langsung membaca surat +panggilan itu, tetapi sampai berulang-ulang membacanya tak + Ayah ~ 205 + +benar-benar memahami maksudnya. Surat itu mengandung +istilah yang asing baginya, misalnya juru sita pengganti, pe- +mohon, termohon, dan lain-lain. Seingatnya, dia tak pernah +mengajukan permohonan untuk dinyatakan sebagai rakyat +di bawah miskin pada negara. Dia tahu banyak tetangganya +membuat permohonan seperti itu melalui kantor desa, lalu +diberi stiker untuk ditempel di pintu, selanjutnya menerima +bantuan ini dan itu. Sabari miskin, tetapi merasa masih mam- +pu mandiri. + + Dibacanya lagi surat itu pelan-pelan macam anak kelas +dua SD baru pandai membaca, masih tak paham juga. Na- +mun, meski tak paham, setiap kali habis membaca, dia mera- +sa seakan sebilah belati menusuk dadanya. + + Malamnya Sabari tak bisa tidur. Keesokannya disampai- +kannya pesan kepada orang yang mau ke Tanjong Pandan +agar mampir ke warung satai kambing muda Afrika. Sabari +memerlukan bantuan Tamat dan Ukun. Sore itu pula, surat +itu sudah berada di tangan Ukun. + + “Ini adalah surat panggilan dari pengadilan agama kare- +na kau akan dimejahijaukan oleh Lena.” + + “Maksudnya?” + “Kau diseret Lena ke pengadilan.” + Sudah barang tentu Sabari tak terima. + “Ini dokumen negara! Jangan kau sembarang bicara, +Boi!” + 206 ~ Andrea Hirata + + “Baca ini, surat panggilan pihak-pihak yang beperkara, +dalam kurung, relaas, nomor 4352, garis miring, pdgt setrip +rhsjy setrip hdgu, garis miring BLTG, telah memanggil Mar- +lena binti Markoni dan Sabari bin Insyafi.” + + “Jadi?” + “Kau kena gugat!” Tamat gemas. + “Gugat apa?” + “Gugat cerai!” + Mulut Sabari ternganga. + “Siapa yang menggugatku cerai?” + “Ajudan bupati. Ya, Lena!” Ukun pun tak sabar. + “Tidak mungkin!” + “Mengapa tak mungkin?” + Sabari mengalihkan pandangan ke padang ilalang. + “Itu tak mungkin,” kata Sabari pelan. Matanya berkaca- +kaca. + Ukun dan Tamat tahu Sabari tak sanggup menerima +kenyataan. Oleh karena itu, dia tak mau memahami maksud +surat itu. + Ruang Sidang III + +“MENERIMA, Yang Mulia.” + Drs. Makmur Manikam menjawab waktu hakim ketua + +bertanya. Sebab, siapa pun yang terlibat dalam perkara itu +tahu bahwa masalah ketidakbahagiaan sebagai alasan perce- +raian bukanlah baru terjadi sehari-dua hari, sudah menahun, +berlarut-larut. + + Semua prosedur untuk menyelamatkan bahtera telah +ditempuh. Mereka sudah menghadap penasihat perkawinan. +Kiranya hukum besi rumah tangga, yakni kau tetap berada +di situ, berdiri tegak dan tersenyum, apa pun yang terjadi, +bahagia atau tidak bukanlah soal, sudah tak berlaku lagi bagi +istri Manikam. Baginya ingin bahagia adalah esensi hidup ini +dan hak manusia yang paling asasi. Perempuan itu tak mau +lagi berdiri dan berpura-pura tersenyum. PBB pun sulit men- +damaikan hati istri Manikam itu. + 208 ~ Andrea Hirata + + JonPijareli mengucapkan menerima hampir tak terdengar, +padahal kalau di panggung dialah orangnya. + + Sebenarnya, di mata hukum siapa pun bisa melakukan +pikir-pikir, lalu banding, lalu kasasi, lalu peninjauan kembali. +Istilah yang lazim dipakai tergugat umpama tak menerima +putusan adalah pikir-pikir. Namun, Jon mengikuti saran peng- +acara pro bono yang mendampinginya. Bahwa meski NATO +turun tangan, kisruh antara Jon dan istrinya sulit ditengahi. +Istrinya adalah seorang asisten apoteker, mungkin lama-lama +agak susah untuk seiring dengan pola pikir seorang musisi. + + Dalam keadaan bingung dan gundah, Sabari menerima +saran dari Tamat bahwa satu-satunya hal yang bisa dilaku- +kannya adalah berpakaian serapi mungkin di hadapan ma- +jelis hakim. + + “Lihatlah, penjahat seberengsek apa pun, jika meng- +hadapi Pak Hakim jadi macam anak baru masuk SD. Licin, +pakai kopiah, tanpa dosa. Berpakaian rapi bukan hanya soal +penghormatan pada hukum, pengadilan, dan majelis hakim, +melainkan juga soal simpati.” Ukun menatap Tamat. Tak ha- +bis pikir dia, bagaimana Tamat kian hari kian cerdas saja. + + Ukun dan Tamat mendampingi Sabari. Ketiga sahabat +itu ke pengadilan agama macam orang mau kondangan. + + Sabari memasuki ruang tunggu dan terkejut melihat ba- +nyak orang, tua muda, pria wanita, tampak kaya dan melarat, +duduk di bangku-bangku panjang menanti giliran dipanggil. +Macam-macam ekspresi mereka, ada yang sedih, ada yang + Ayah ~ 209 + +memandang kosong, banyak yang diam menunduk, ada pula +yang tersenyum-senyum. + + Seperti dirinya, setiap orang memang berusaha berpa- +kaian sebagus mungkin. Getir hati Sabari mendapati bahwa +di tempat orang akan mengalami hal yang pahit, orang-orang +justru berpakaian bagus seperti Lebaran. Dan, tak tega dia +melihat anak-anak kecil yang dibawa orangtuanya ke ruang +tunggu itu. Mereka menangis, kepanasan, ingin menyusu, +minta pulang, minta ini dan itu. Jeritan mereka merisaukan. +Anak-anak kecil itu lalu digendong bergantian oleh ayah dan +ibunya yang mau bercerai. + + Sabari teringat akan Zorro, sendi-sendi tubuhnya lum- +puh. Dia duduk terkulai. Di ruang tunggu pengadilan, Sabari +merasa betapa kejam hidup ini. Dia ingin segera pulang, ingin +cepat-cepat memeluk anaknya. + + Ukun dan Tamat lebih tertarik akan dandanan mereka +ketimbang apa yang akan dialami Sabari. Keduanya sibuk +membetulkan jambul dan memandang-mandang sekeliling. +Terutama memandangi wanita-wanita muda. Bagi mereka, +kunjungan ke pengadilan agama bak piknik yang menye- +nangkan. + + Tamat menunjuk satu arah. Di sana, Marlena datang +dengan seorang lelaki yang tampak sangat terpelajar dan +berpakaian seperti seorang direktur. Lengkap dengan koper +kecilnya. Lena segera menarik perhatian sebab dia memang +elok. Berbaju bagus untuk sidang membuatnya semakin me- + 210 ~ Andrea Hirata + +mesona. Harus diakui, amat tak sepadan dengan lelaki norak +dan gugup yang akan diceraikannya, yang duduk terpojok di +ujung sana. + + Semakin siang, suara panggilan untuk pasangan-pasang- +an yang beperkara semakin gencar. Akhirnya, terdengar .... + + “Sabari bin Insyafi, Marlena binti Markoni, Ruang Si- +dang Tiga. Kami ulangi ....” + + Di dalam ruang sidang, Sabari demikian gugup sehingga +tidak sepenuhnya memahami apa yang terjadi. Berbagai kata +asing membuat kepalanya pening. Pikirannya hanya tertuju +kepada Zorro. Yang dia tahu di depannya ada orang-orang +berpakaian aneh dengan jubah panjang, berwajah bijaksana, +berhati-hati jika bicara dan tampak paham benar setiap kata +yang mereka ucapkan. + + Di sebelah sana ada Lena dan pria terpelajar itu. Orang +itu berbicara panjang lebar soal pertikaian antara Sabari +dan Lena yang kian hari kian meruncing, perbedaan yang +fundamental dari berbagai aspek kehidupan pemohon dan +termohon, yang akan berakibat lebih banyak mudarat dari- +pada manfaat jika mereka tetap berumah tangga. Semua itu +membuat Sabari cukup heran sebab selama berumah tang- +ga dengan Marlena, tak habis jumlah jari sebelah tangan dia +pernah berjumpa dengan istrinya itu. Jika berjumpa pun se- +bentar sekali. Sebab, Lena pulang sebentar lalu pergi lagi. + + Fakta demi fakta dibeberkan secara lengkap, sistematis, +dan masuk akal. Berbagai upaya untuk memperbaiki keadaan + Ayah ~ 211 + +sudah ditempuh, tetapi gagal, maka sudah saatnya berlayar +menuju dermaga yang berbeda-beda. + + Sesekali Lena angkat bicara, tangkas, tinggi, dan sengit. +Sabari bahkan tak berani menoleh ke arahnya. Di belakang- +nya, di tempat duduk untuk pengunjung sidang, Tamat dan +Ukun mengangguk-angguk penuh gaya. + + Sabari tenggelam dalam berupa-rupa delik, pasal demi +pasal Undang-Undang Perkawinan, kata menimbang, mengi- +ngat, memutuskan ini dan itu. Dia mengangguk-angguk mes- +ki tak tahu mengangguk untuk apa. Tahu-tahu dia terperan- +jat mendengar Yang Mulia Hakim bertanya kepadanya. + + “Adakah yang ingin Saudara sampaikan?” + Sabari tergagap-gagap. Dia menoleh ke arah Ukun dan +Tamat. Kedua sahabatnya itu malah menoleh ke arah gam- +bar burung Garuda Pancasila. Sabari semakin gugup. Demi- +kian berwibawa ruang sidang itu baginya, demikian hebat +orang-orang yang ada di sekelilingnya sehingga apa pun yang +dituduhkan dia akan mengaku saja. + Sabari menatap Yang Mulia. Sebenarnya, ingin sekali +dia mengatakan bahwa silakan majelis memutuskan apa saja +asal tidak memutuskan hubungannya dengan Zorro. Namun, +dilihatnya Marlena memelotot ke arahnya, matanya besar +macam buah mentega, mulutnya siap menyemburkan api. +Sabari tak dapat berkata-kata. + “Jadi, apakah Saudara menerima putusan?” + 212 ~ Andrea Hirata + + Sabari menoleh lagi ke belakang, Tamat merendahkan +badannya, dengan maksud apa yang akan dikatakannya tidak +dilihat orang, dia berbisik keras sambil melindungi mulutnya +dengan tangan. + + “Pikir-pikir!” + Belum sempat Sabari menyitir kata-kata itu untuk dilon- +tarkan kembali pada majelis, Marlena bangkit. + “Pikir-pikir apa?! Jangan percaya, Yang Mulia, aku kenal +tiga orang itu! Mereka itu satu komplotan, tukang bikin onar! +Lihatlah dandanannya itu!” + Tentu saja tindakan Lena yang tidak normatif itu lang- +sung ditertibkan oleh hakim melalui beberapa ketukan palu, +sekaligus Tamat diperingatkan bahwa dia hanya boleh me- +nyaksikan sidang, bukan untuk memberi satu pandangan hu- +kum. Tamat meminta maaf dan menunduk takzim di muka +Yang Mulia, macam orang mau dipancung lehernya. + Persidangan tak berlangsung lama. Hati Sabari seper- +ti digunting melihat panitera pengadilan menggunting buku +nikahnya dan buku nikah Lena. Yang Mulia mengetuk palu. +Majelis menutup sidang. + Majelis hakim meninggalkan ruangan. Lelaki terpelajar +tadi mengemasi berkas-berkasnya, memasukkannya ke koper, +lalu cepat-cepat pergi bersama Lena. Disusul Ukun dan Ta- +mat. Sabari masih duduk sendiri. + Terdengar panggilan bagi pasangan lain untuk mema- +suki Ruang Sidang III. Seorang petugas meminta Sabari + Ayah ~ 213 + +keluar. Sabari bangkit, berjalan keluar menyusul Ukun dan +Tamat. Dia sempat menoleh ke belakang, melihat tempat +Lena duduk tadi. Begitu cepat semuanya berlangsung, lalu +dia merasa kosong. Di dunia nan fana ini, cinta bersemi dan +terempas tiada jeda. + + Dari tempat parkir sepeda motor, juru antar melihat tiga +orang berdandan aneh berjalan melintasi pekarangan gedung +pengadilan agama. Dia mengenal salah seorang dari mereka. + + Juru antar sedih melihat Sabari, tetapi tak ada waktu +untuk bersedih-sedih sebab banyak surat panggilan beper- +kara yang harus diantar. Masih menumpuk. Untuk ukuran +kabupaten, angka perceraian di Belitong termasuk yang ter- +tinggi. Juru antar sibuk macam madu angin. Puluhan kali dia +mengengkol motornya, tak juga hidup mesinnya. Dia meng- +ambil napas lalu mengengkol lagi, berkali-kali, tetap gagal. +Mungkin karena sebagian hatinya tak ingin mesin motornya +menyala. + Menyukai +Travelling + +JONPIJARELI terpukul lebih keras atas perceraian dengan +istrinya ketimbang Makmur Manikam. Manikam masih bisa +bekerja dengan normal, tak pernah bolos, tak pernah telat +senam kesegaran jasmani. Dia juga berusaha secara positif +untuk menemukan cara rujuk dengan mantan istrinya. Upaya +itu baru berakhir setelah istrinya menikah lagi dengan kekasih +pertamanya waktu mereka masih SMA dulu. Klasik, klasik +sekali. + + Setelah itu, Manikam menutup pintu hatinya untuk pe- +rempuan. Pengalaman dengan istrinya telah membuatnya +kapok dan ingin berkonsentrasi pada pekerjaan saja, serta +mendidik anak-anaknya yang tinggal bergantian antara dia +dan istrinya. + + Jon mendadak jadi pendiam, lalu pemurung. Dia mulai +malas-malasan mengurus band-nya. Padahal, band itu sedang +naik daun dan tengah mengumpulkan materi untuk mencoba + Ayah ~ 215 + +merekam lagu-lagu mereka, termasuk lagu “Aku Berlari” cip- +taan Jon itu. Bagi orang-orang tertentu, nasib sial selalu da- +tang pada saat yang tidak tepat, begitu pula nasib baik. Teori +ini agak membingungkan memang. + + Minggu menjadi bulan, bulan menjadi tahun, satu ta- +hun menjadi dua tahun. Sudah selama itulah sejak Manikam +dan Jon bergabung dengan satu armada besar kaum duda. +Drs. Zulkifli, alias Zul, kawan baik Manikam, berkali-kali me- +nyarankan agar Manikam menikah lagi karena itu baik untuk +anak-anaknya. Manikam masih trauma. + + Zul mengenalkan beberapa perempuan, Manikam tak +acuh. Adakalanya Manikam seperti berminat, bersemangat, +tetapi kemudian dengan cepat membeku kembali, macam +lava yang tumpah dari Gunung Kilauea lalu tercebur ke Laut +Hawaii yang dingin. Jika Zul memperlihatkan foto perempu- +an, foto itu dilungsurkan Manikam kembali kepadanya. + + Alkisah, Zul punya sepupu yang tinggal di Toboali dan +mengenal seorang perempuan pegawai loket wesel di kantor +pos. Pegawai loket itu mengenal seorang pengantar telegram +di kantor Telkom. Pegawai Telkom itu mengenal pegawai +kursus komputer yang bersedia dikenalkan dengan seorang +pria baik-baik, usia matang, sehat badan dan pikiran, suka +membaca buku, tidak merokok, tidak minum minuman keras, +tidak suka mengunyah-ngunyah permen karet secara kam- +pungan, kalau makan tidak berbunyi, dan yang terpenting: +menyukai travelling. + 216 ~ Andrea Hirata + + Zul berhenti membaca surat dari saudaranya di bagian +menyukai travelling itu, lalu melanjutkan membaca syarat-sya- +rat lainnya. + + Yaitu, pria yang diinginkan harus pula suka kepada +anak-anak, tidak suka kebut-kebutan, tidak banyak bicara, +tidak pernah terlibat dalam satu tindakan pidana, pintar me- +nyelesaikan kerusakan-kerusakan kecil di rumah di bidang +listrik, elektronik, atap, atau ledeng. Lebih senang mengena- +kan kemeja daripada kaus, sebaiknya tidak suka mengenakan +celana jins dan akan lebih baik jika selalu mengenakan ikat +pinggang, berpendidikan minimal D-3 di bidang Manajemen +kalau bisa, bidang Peternakan dan Perikanan juga disukai, +perjaka atau duda boleh saja, jumlah anak (kalau duda) ti- +daklah masalah, tetapi harus punya pekerjaan tetap (bergaji +bulanan), berperangai tidak grusa-grusu, menyukai masakan +rumah, senang mendengarkan musik pop masa kini, senang +mendengar radio, dan senang menonton sinetron. + + Zul memperlihatkan foto perempuan yang tak banyak +menuntut itu kepada Manikam disertai satu perasaan pesi- +mis yang menjengkelkan bahwa jangankan 37 syarat, kepada +perempuan yang tak menyebut satu syarat pun Manikam tak +pernah tertarik. + + Manikam melirik foto itu, mulanya sambil lalu saja, te- +tapi kemudian dimintanya Zul memperlihatkannya kembali. +Zul terkejut. Dari belasan, atau mungkin puluhan, foto pe- +rempuan yang diperlihatkannya, baru kali ini Manikam ter- +tarik. + Ayah ~ 217 + + Di rumah, Manikam mengamati foto itu dengan tenang +sambil minum teh sore dan mengumpulkan sebanyak mung- +kin kebijakan dalam dirinya. Dia berbicara dengan dirinya +sendiri bahwa ada sesuatu dalam perempuan di foto itu. De- +retan syarat yang sangat cerewet itu justru baginya sebuah +daya tarik. Orang yang menetapkan banyak syarat merupa- +kan pertanda orang yang bertanggung jawab. Satu kualitas +yang cocok untuknya. Cara berpikir orang pintar memang +berbeda dari kita-kita. Seminggu kemudian Manikam mulai +berkirim-kirim surat dengan perempuan di Toboali itu. + + Adapun JonPijareli kian tenggelam dalam kesedihan. +Dia tak lagi mengajar privat, bahkan sudah jarang main gitar. +Lelaki itu ditinggalkan cinta dan bersama cinta yang pergi, +terangkut pula jati dirinya sebagai musisi. Dia jarang tam- +pil. Hidupnya disokong oleh abangnya. Band-nya mendapat +undangan untuk tampil di festival musik di Bengkulu. Atas +desakan anggota band lainnya, Jon bersedia tampil. Namun, +katanya penampilan di Bengkulu akan menjadi penampilan +terakhirnya. Setelah itu, dia akan mengundurkan diri dari +band. Berakhirlah kiprahnya setelah hampir dua puluh tahun +malang melintang di panggung musik daerah. Jon tak menya- +dari sama sekali, penampilan terakhirnya di Bengkulu nanti +akan membuat hidup jungkir balik, memelesat ke arah yang +tak diduganya. + Rabun + +SABARI tahu bahwa dia sudah bercerai dengan Lena. Dia +melihat dengan mata kepalanya sendiri panitera pengadilan +agama menggunting buku nikahnya dan buku nikah Lena. +Paspor untuk berangkat ke negeri bahagia untuk selama- +lamanya itu telah dianulir oleh negara. Maka, secara resmi +hubungannya dengan Lena, khatam. Namun, kombinasi dari +hatinya yang lapang, keluguan yang tak tanggung-tanggung, +dan kenyataan yang sulit diterima, membuat matanya rabun +melihat konsekuensi hukum dari perceraian itu. Dia tak sadar +bahaya yang besar sedang menunggunya. + + Yang diketahuinya adalah baru tiga hari sejak putusan +pengadilan, sudah beredar kabar Lena dekat dengan seorang +dealer motor vespa. Buncai bersabda, “Mereka mau menikah, +Marlena dan Zorro akan diboyong orang itu ke Pangkal Pi- +nang.” + Ayah ~ 219 + + Sabari menggigil. Tak ada yang paling ditakutkannya +selain Zorro diambil darinya. Namun, Sabari membujuk diri- +nya sendiri dengan mengatakan bahwa Buncai adalah pem- +bual kelas satu. + + Bual Buncai lagi, Lena akan mengambil Zorro kapan +pun atau di mana pun dia mau, kalau dia sudah sempat, kalau +semua urusannya dengan dealer vespa itu sudah beres. Dia tak +perlu memberi tahu Sabari sebab Sabari tak punya hak apa- +apa atas bocah itu. + + “Hati-hati, Boi,” Buncai mengingatkan Sabari. + “Ini masalah hukum. Kata Lena, kalau kau macam- +macam, kau akan dilaporkan kepada pulisi, bisa kena kurung +kau!” + Di depan Ukun dan Tamat, Sabari mempertahankan +posisinya dengan dalih bahwa tak ada orang yang lebih dekat +dan lebih sayang di dunia ini kepada Zorro selain dirinya. + “Setuju,” kata Tamat dengan tenang. + Bahwa Zorro sudah ada dengannya sejak masih merah. + “Setuju.” + “Bilang sama Lena, Kun,” pesan lelaki lugu itu. + “Dia boleh kawin dengan dealer vespa, dengan pengge- +mar vespa, dengan pemilik bengkel vespa, dengan pembalap +vespa, dengan pencuri vespa, dengan orang yang pernah di- +tabrak vespa, bahkan dengan penemu vespa. Dia juga boleh +mengambil tanahku, rumahku, warungku, sepedaku, kam- + 220 ~ Andrea Hirata + +bing-kambingku, radioku, baju-bajuku, sarungku, sepatuku, +semuanya, asal dia tidak mengambil Zorro.” + + Di pelabuhan Tanjong Pandan, seorang tukang ojek ka- +wan Ukun melihat Lena mau naik kapal tak tahu ke mana. +Orang itu memberi tahu Ukun. Pontang-panting Ukun ber- +lari ke pelabuhan. + + “Boi! Aku mau menyampaikan pesan Sabari untukmu.” + “Pesan apa?” + “Begini ....” Panjang lebar Ukun bicara. Malas-malasan +Lena mendengarnya dan tiba-tiba dia muntab. + “Bilang sama Sabari! Aku tak perlu rumah reyotnya! +Sepeda bututnya! Dan, kambing-kambing baunya itu! Ma- +jenun!” + “Baiklah, Boi.” + Ukun menghadap Sabari. + “Aku disuruh Marlena menyampaikan pesan ini kepada- +mu, Ri.” Sabari menyimak. + “Katanya, dia tidak mau rumah reyotmu, warung ba- +nyak utangmu, radio busukmu, baju-baju kampunganmu, se- +peda bututmu, gigi tupaimu, alis jarangmu, telinga wajanmu, +jidat monyetmu, dan bahwa kau lebih bau daripada kambing- +kambingmu! Majenun!” + Sabari tersandar pasrah. + “Maka, dengan ini amanah dari kedua belah pihak telah +kusampaikan.” + “Terima kasih, Boi.” + Ayah ~ 221 + +Sabari berusaha mengalihkan pikirannya dari hal-hal yang +pahit. Setiap sore, usai menutup warung dan mengandang- +kan kambing-kambingnya, dia membonceng Zorro naik se- +peda. Zorro duduk di keranjang rotan yang ditautkan di se- +tang. Sepanjang jalan mulut Zorro tak berhenti berkicau. Dia +melambai kepada siapa saja dan apa saja. Alo, alo sapanya. +Dia menyapa orang-orang yang duduk di beranda meski tak +kenal. Dia menyapa pedagang kaki lima, orang gila, polisi lalu +lintas, orang-orang yang berlalu-lalang. Dia juga menyapa +pohon kelapa, mobil parkir, sepeda motor, kucing, ayam, dan +bunga-bunga. + + Oleh karena itu, Zorro menjadi tenar. Jika dia lewat, +orang-orang senang memanggil anak yang menggemaskan +itu. Setiap kali anaknya disapa, perasaan Sabari melambung. + + Karena hujan, suatu ketika Sabari minggir untuk berte- +duh di emper toko. Di sana ada seekor kucing kecil, kehujan- +an dan lemah. Kucing itu mengeong-ngeong serak, habis sua- +ranya karena kebanyakan menangis. Zorro menghampirinya, +langsung mengambil dan menggendongnya. Kucing itu nanti +menjadi Abu Meong. + + Beberapa hari setelah itu, Sabari terkejut melihat Zorro +menghampirinya sambil menggendong seekor kucing. Mung- + 222 ~ Andrea Hirata + +kin kucing itu dibuang di pinggir jalan lalu dipungut Zorro. +Kucing itu nanti menjadi Marleni. + + Sabari membuat ayunan yang ditambatkan di dahan +pohon delima di samping rumah. Di bawah pohon itu mere- +ka banyak menghabiskan waktu. Sabari, Zorro, Abu Meong, +Marleni, delima, semuanya begitu sempurna. + + Saban malam Sabari tidur sambil memeluk Zorro. Ka- +lau terlintas dalam pikirannya anaknya akan dibawa pergi +jauh ke Pulau Bangka, tubuhnya gemetar. Jika terbangun ce- +pat-cepat dilihatnya Zorro, kalau-kalau sudah tak ada. Zorro +pun semakin tak terpisahkan dari ayahnya. Bocah kecil da- +pat merasakan apa yang terjadi. Dia selalu minta digendong +ayahnya. + +Sabari merasa sangat beruntung telah dibesarkan ayahnya +dengan puisi. Dia bersyukur dikenalkan ayahnya pada salah +satu keindahan tertinggi karya manusia sejak usia dini. Kini +dia ingin membesarkan anaknya sendiri dengan puisi. + + Sebagai pengantar tidur, dia selalu menyitir puisi. Zorro +senang melihat gerak gerik ayahnya, kedua tangan diangkat +ke atas, lalu dibekapkan di dada. Mata meredup lalu terpe- +jam. Suara keras, lalu pelan, lalu berbisik di telinganya. Zorro +tergelak-gelak. + Ayah ~ 223 + + Tentu dia tak memahami sebagian besar puisi ayahnya, +tetapi dia dapat merasakan bahwa ayahnya sedang berusaha +menyampaikan keindahan. Dia terpesona. Matanya berbinar +menunggu kata-kata ajaib diucapkan ayahnya. + + Dua pohon yang menyendiri + Dua pohon di tepi sungai yang mengalir sepi + Berdiri tegak, muda dan tumbuh + Mereka ingin mengatakan sesuatu + Namun, mereka tetap diam + + “Itu puisi dari negeri yang jauh, Boi, Turki,” kata Sabari +sambil membuka-buka lembar buku yang dihadiahkan ayah- +nya: Puisi-Puisi Ahmet Munip Diranas. + + “Kalau kau sudah masuk sekolah nanti akan Ayah ce- +ritakan kisah yang hebat dari negeri yang lebih jauh lagi, +Cartagena, Kolombia, itulah kisah Florentino Ariza.” + + Sabari tergelak mendengar Zorro meniru ucapannya, +yoyenyio yayiya! yoyenyio yayiya! + + Kisah tetap Sabari untuk mengantar Zorro tidur adalah +kisah istimewa karya ayahnya, yakni Kisah Keluarga Langit dan +Nyanyi Puisi Merayu Awan. Dengan sukacita Sabari menurun- +kan kisah itu kepada anaknya. + + “Tahukah kau, Zorro? Awan dapat dirayu agar tak me- +nurunkan hujan, nyanyikanlah puisi untuk awan.” + 224 ~ Andrea Hirata + + Sabari bersenandung pelan, seperti senandung ayahnya +dulu. + + Wahai awan + Kalau bersedih + Jangan menangis + Janganlah turunkan hujan + Karena aku mau pulang + Untukmu awan + Kan kuterbangkan layang-layang .... + + Zorro terpana. Setiap malam dia selalu meminta ayah- +nya untuk menyanyikan puisi rayuan awan itu. Setelah bebe- +rapa waktu, dia sendiri mulai pandai menyanyikannya, meski +terbata-bata. + + Zorro senang mendengar cerita dan Sabari senang +bercerita. Sabari menceritakan kisah favoritnya, yaitu Cinta +pada Masa Wabah Kolera dengan menganggap dirinya sebagai +Florentino Ariza. Zorro terbuai kisah dari negeri yang jauh, +Amerika Selatan. + + Dalam salah satu kisah-kisah ninabobo itu, secara tak +sengaja Sabari menyinggung soal makanan. Zorro senang. +Mungkin nama makanan terdengar lucu baginya. Keesokan- +nya Sabari berkongkalikong dengan tukang parkir di depan +Restoran Bundo Kanduang. Malamnya dia berkisah tentang +petualangan pendekar ayam pop sambil mengepak-ngepak- + Ayah ~ 225 + +kan tangan dan berkokok-kokok. Zorro tertawa sampai berair +matanya. Sayangnya restoran padang itu hanya restoran ke- +cil, menunya terbatas sehingga dengan cepat Sabari kehabis- +an kisah. + + Beruntung, ada restoran yang baru buka di Tanjong +Pandan. Restoran Modern, begitu namanya. Sabari menitip- +kan Zorro kepada tetangga dan langsung ngebut mengayuh +sepeda, seratus kilometer ke Tanjong Pandan. + + Di muka restoran itu Sabari berteduh di bawah naungan +pohon kersen. Sekujur tubuhnya berkeringat karena perjalan- +an yang jauh. Dia berpura-pura membetulkan rantai sepeda. +Di dalam restoran orang-orang berpakaian bagus sedang ma- +kan. Mobil-mobil berdatangan. + + Lama menunggu, akhirnya kesempatan itu tiba, seorang +pegawai, perempuan setengah baya, ke luar, mungkin giliran- +nya beristirahat. + + “Kakak, Kakak!” + Perempuan itu menoleh. Sabari menghampirinya. + “Ada apa, Pak Cik?” + “Maaf, tentu Kakak bekerja di restoran ini.” + “Aok.” + “Restoran apakah ini?” + “Restoran masakan modern, Pak Cik.” + “Maksudnya?” + “Semua masakannya model negara Barat.” + “Model negara Barat?” + 226 ~ Andrea Hirata + + “Aok.” + Melambunglah semangat Sabari karena membayang- +kan hebatnya kisah yang akan diceritakannya kepada Zorro. + “Maaf, Kak, bolehkah aku meminta daftar menunya?” + “Maksudnya?” + “Aku memerlukan daftar menunya.” + “Untuk apa?” + Sabari berkisah apa adanya. Bahwa dia memerlukan +daftar menu itu untuk meninabobokan anaknya. Ternganga +lebar mulut kakak itu. Lama diamatinya Sabari. + “Berapa umur anak Pak Cik?” + “Oktober nanti, pas tiga tahun, Kak.” + Kakak itu tersenyum. + “Anakku juga mau tiga tahun.” + “Laki-laki, perempuan?” + “Laki-laki, Pak Cik.” + “Anakku juga laki-laki.” + Kakak itu masuk kembali ke restoran lalu keluar mem- +bawa daftar menu. + Malam itu Zorro tergelak-gelak mendengar nama ma- +sakan nasi goreng luar negeri dan ikan bakar luar negeri. Sa- +bari senang meski dia sedih karena begitu miskin sehingga tak +dapat membelikan Zorro makanan di dalam daftar menu itu. +Dalam hati dia berjanji suatu hari nanti akan membelikan +anaknya makanan-makanan itu. Sementara ini, biar cerita +menu saja dulu. + Ayah ~ 227 + + Sabari terpikir untuk mencoba restoran lain. Melalui +kawannya, anak buah kapal feri Bangka–Belitong, dia men- +dapat menu Restoran Copa Cabana, Pangkal Pinang. Sabari +menitipkan ongkos kepada kawannya, anak buah kapal ba- +rang Manggar–Sunda Kelapa. + + Tak lama kemudian segepok menu restoran Tiongkok +dan Jepang sudah ada di tangan Sabari. Tak tahu bagaimana +cara anak buah kapal itu menggelapkannya. Mata Zorro tak +berkedip, wajahnya tegang melihat ayahnya bersilat-silat me- +niru jurus pendekar Yakiniku membasmi penjahat di Negeri +Teriyaki. Akhirnya, pendekar jagoannya menang, Zorro ber- +sorak-sorak girang, Sabari meraihnya lalu mengangkat anak- +nya tinggi-tinggi. + + Konon, hari paling penting dalam hidup manusia ada- +lah hari saat manusia itu tahu untuk apa dia dilahirkan. +Sekarang Sabari tahu bahwa dia dilahirkan untuk menjadi +seorang ayah. Seorang ayah bagi Zorro. Anaknya telah meng- +urai semua misteri tentangnya. Bahwa wajahnya tidak tam- +pan agar dia tidak menjadi orang seperti Bogel Leboi. Karena +dia seorang Sabari maka Tuhan memberinya Zorro. Bahwa +tangannya yang kasar dan kuat seperti besi adalah agar dia +tak gampang lelah menggendong Zorro. Bahwa dia gemar +berpuisi dan berkisah adalah agar dapat membesarkan anak- +nya dengan puisi. Sabari memeluk anaknya yang telah jatuh +tertidur, serasa memeluk awan. + 228 ~ Andrea Hirata + +Seperti biasa, setiap sore, Sabari mengajak Zorro ke taman +balai kota. Masuk September, hujan hampir setiap hari. Se- +belum berangkat, disiapkannya tas punggung kecil kesayang- +an anaknya, yang kemudian dipakai Zorro dengan gagah. Di +dalam tas itu ada topi, jas hujan, sarung tangan, baju ganti. +Sabari pun memasukkan kemeja ganti untuknya sendiri ka- +lau-kalau nanti kehujanan. + + Seperti kebiasaannya, Zorro menyapa apa pun dan si- +apa pun sepanjang jalan. Di dalam boncengan rotan yang +disematkan di setang sepeda dia tak berhenti berkicau-kicau. +Orang-orang pun selalu memanggilnya. + + Sampai di taman balai kota, kedua anak-beranak itu du- +duk di bangku taman. Zorro sibuk mengunyah kembang gula +berwarna pink, makanan aneh yang kribo itu. Sabari bangkit +dan berjalan untuk membeli balon gas yang jaraknya hanya +beberapa langkah dari tempat duduk mereka. Usai membe- +li balon gas, begitu berbalik dilihatnya beberapa orang telah +mengelilingi Zorro. Orang-orang itu adalah Lena, lelaki ter- +pelajar yang dilihatnya di pengadilan agama itu, dan dua le- +laki lainnya. + + Lena meraih Zorro, langsung menggendongnya dan +bergegas pergi. Zorro meronta. Sabari mendekat, dua pria +tadi menghalanginya. Lena bergegas pergi. Zorro memberon- +tak dan memanggil-manggil, Aya! Aya! Tangannya mengga- + Ayah ~ 229 + +pai-gapai. Semuanya terjadi dengan sangat cepat. Tahu-tahu +Lena dan Zorro telah berada di seberang jalan, lalu masuk ke +mobil dan langsung meluncur. + + Sabari tahu apa yang paling ditakutkannya telah terjadi. +Dia berdiri gemetar di pinggir taman balai kota sambil me- +megang balon gas. Zorro, Zorro, panggilnya dalam hati. + + Lama dia berdiri memandangi persimpangan jalan di +ujung sana, tempat dia terakhir melihat Zorro. Sendi-sendi +tubuhnya lumpuh. Dia bahkan tak mampu memegang tali +balon gas. Balon-balon itu terlepas, terbang menyedihkan ke +angkasa. + + Ramai orang di taman balai kota, hiruk pikuk anak- +anak. Orang-orang berbicara dan memanggil-manggil, peda- +gang kaki lima bersaing keras suara menawarkan dagangan, +mainan balon yang dipencet anak-anak melengking-lengking. +Klakson sahut-menyahut dari kendaraan yang ingin cepat- +cepat sebab langit sudah gelap, hujan segera tumpah. Peluit +yang disemprit polisi membuat susana makin bising, tetapi +Sabari tak mendengar suara-suara itu. Dia merasa berdiri +sendiri di tengah padang pasir. Tak ada siapa-siapa kecuali +dirinya sendiri. Tak pernah dialaminya rasa sepi sehebat itu. + + Di muka toko kain Pakistan itu juru antar bersusah pa- +yah mengengkol sepeda motornya, yang tadi baik-baik saja, +meluncur dengan syahdu melewati taman balai kota, lalu +tiba-tiba mogok. Dia melongok ke langit, titik-titik air mulai +berjatuhan. + 230 ~ Andrea Hirata + + Orang-orang berlarian untuk berteduh di emper-emper +toko. Tinggallah Sabari berdiri sendiri. Hujan rintik-rintik +mulai menimpanya. Dia berjalan pelan menuju tempat parkir +sepeda. Dipandanginya keranjang rotan tempat duduk Zorro +tadi, kosong. Hatinya pedih. Dia selalu mengajak Zorro ke ta- +man balai kota dan sore ini dia akan pulang sendiri, anaknya +tak ada lagi. + + Sabari mencoba menaiki sepeda, tetapi tak mampu ka- +rena tenaganya telah sirna. Maka, dituntunnya saja sepeda +itu. Dia lewat dekat juru antar. Mereka tak saling menyapa +karena juru antar tak melihat Sabari. Dia terlalu sibuk meng­ +engkol motornya. Dan, Sabari tak melihatnya sebab dia me- +nuntun sepeda di tengah padang pasir, tak ada siapa-siapa di +sana. + + Hujan pun turun dengan lebat. Sabari tak berteduh. Dia +terus menuntun sepedanya sambil menangis tersedu-sedu. + 37 Syarat + +GEGABAH, bukanlah tipikal Manikam. Dia itu teliti, meto- +dikal, dan sistematis. Dia memiliki kepribadian seorang pe- +nerjun payung. + + Oleh karena itu, perlu waktu hampir setahun dan pu- +luhan surat dari dan untuk perempuan di Toboali itu sampai +akhirnya dia memutuskan untuk meningkatkan hubungan +mereka ke tahap lebih lanjut. + + Manikam telah melakukan semacam analisis versinya +sendiri, sampai mencakup telaah tulisan tangan. Satu kenya- +taan yang tak dapat dimungkiri, tersirat beberapa soal krusial +dalam tulisan tangan perempuan itu. Yakni, menurut buku +Memahami Tulisan Tangan yang dipedomaninya, ada bagian +yang gelap dari perempuan itu. + + Bahwa mereka yang menulis huruf tertentu dengan ben- +tuk seperti anggota badan, umpama bentuk huruf K macam + 232 ~ Andrea Hirata + +tangan manusia—bagaimanakah bentuk huruf K macam tangan ma- +nusia? Kawan, janganlah kau ributkan soal itu, baca saja—mengin- +dikasikan satu problem psikologis, yaitu orang itu tak banyak +pikir-pikir, pembosan, informal, antikemapanan. + + Maka, tak dapat dimungkiri pula, Manikam sedikit ce- +mas karena merasa ada bagian misterius dari perempuan +Toboali itu, dan dia bingung sebab hasil analisis tulisan ta- +ngannya kontradiktif dengan sebagian dari 37 syarat yang +ditetapkannya. Di sisi lain, Manikam yang berjiwa amtenaar +bukanlah seorang player. Dia tak pernah berspekulasi, apalagi +soal perempuan. Semua risiko haruslah calculated risk, satu risi- +ko yang telah diperhitungkan. + + Begitu di atas kertas, tetapi jika melihat lagi foto perem- +puan itu, segala teorinya lindap, segala kebijaksanaan lenyap. +Begitu kuat tenaga gambar, wajar orang berbondong-bon- +dong menonton sinetron. Perempuan di foto itu membuat +Manikam merasa menemukan semacam sense of purpose, istilah +kerennya, menemukan alasan dan tujuan hidupnya, dan foto +itu mengabarkan bahwa kedamaian telah tercipta di muka +bumi ini. Kupu-kupu beterbangan, burung-burung berkicau. + + Foto itu jelas tidak diutak-utik dengan komputer, yang +bisa membuat orang berwajah macam helm habis dibentur- +kan ke tembok menjadi licin cantik sekali. Foto itu menunjuk- +kan perempuan dengan kecantikan natural. Segala hal ten- +tangnya original, genuine, asli, tidak dibuat-buat. Dia pun tidak +bergaya, tidak berdandan, tidak pula mengenakan baju yang + Ayah ~ 233 + +bagus. Dia memandang sesuatu yang menyenangkan di sebe- +lah sana, tersenyum, lalu seseorang memotretnya, candid. + + Akhirnya, Manikam menyerah pada pesona perempuan +misterius itu, fotonya lebih tepatnya. Untuk menunjukkan ik- +tikadnya dia mengirim sejumlah uang kepada perempuan itu +untuk membiayai perjalanannya dari Toboali ke Bengkulu, +meski perempuan itu tak pernah memintanya. + + Sabtu pagi itu menjadi amat istimewa bagi Manikam. +Bersama kedua anaknya yang masih duduk di sekolah dasar, +dia ke Terminal Bus Arga Makmur. Tegak dia berdiri di plat- +form kedatangan, teliti menatap para penumpang yang ke- +luar dari bus malam. Perempuan itu telah mengatakan akan +bepergian dari Bangka, lalu ke Lampung, lalu ke Bengkulu +naik bus dari Tanjung Karang. Berulang-ulang dilihatnya foto +di tangannya untuk dicocokkan dengan wajah perempuan- +perempuan muda yang keluar dari bus. Kedua anaknya du- +duk dengan wajah cemberut. + + Pukul 10.00 lewat sedikit, sebuah bus besar dari Tan- +jung Karang menikung masuk melalui gerbang kedatangan +disertai klakson yang membuat dada Manikam berdentum- +dentum. + + Pintu bus terbuka, penumpang keluar satu per satu, dan +muncullah perempuan dan seorang bocah. Jika tidak meng- +ingat dirinya PNS golongan III/c, Manikam mau melompat +karena apa yang dibayangkannya selama ini tak memeleset, +bahkan jauh lebih baik. Perempuan itu manis minta ampun. + 234 ~ Andrea Hirata + +Durian runtuh. Dia berlari kecil menyongsong perempuan +itu. Mereka berhadapan. + + “Manikam?” tanya perempuan itu. + “Saya, saya Manikam,” Mantap, perempuan itu menju- +lurkan tangannya. + “Marlena.” + “Ini pasti Zorro,” kata Manikam sambil menunjuk bo- +cah tadi. Dengan pedang plastiknya, Zorro melukis huruf Z. + +Sudah barang tentu sidang pembaca bertanya, apa yang ter- +jadi dengan dealer motor vespa itu? Alkisah, hanya beberapa +bulan berumah tangga dengan pria itu, Lena minta cerai. Se- +bab musababnya adalah semua yang dibayangkannya, tepat- +nya dijanjikan oleh lelaki itu, berbeda dalam praktik. + + Hal sepele, Lena suka musik, lelaki itu tak bisa membe- +dakan musik dangdut dan musik reggae. Lena senang bepergi- +an, dia ingin melihat dunia, lelaki itu senang melihat burung +perkututnya. Lena tak mau menghabiskan sisa hidupnya de- +ngan lelaki yang maunya tinggal di rumah saja. + + Kepribadian Lena yang tak suka ambil pusing membu- +atnya mudah saja memutuskan bercerai dan oleh karena itu +Markoni muntab luar biasa. Dia bilang dalam suratnya kepada +Lena bahwa Lena tak berpikir panjang soal anaknya, menyia- +nyiakan seorang lelaki, yang punya keterampilan di bidang +motor dan menyia-nyiakan Sabari. + Ayah ~ 235 + + Sabari memang buruk rupa, aku pun suka kasihan melihat muka- +nya itu, tapi hatinya baik! Hatinya mulia!!! + + Begitu tepatnya Markoni menulis suratnya. Paling tidak +ada enam belas tanda seru dalam surat yang menyalak-nyalak +itu. + + Lantas, Markoni bilang bahwa kesabarannya sudah ha- +bis karena Lena suka meraupkan abu ke mukanya, satu ung- +kapan betapa malunya orang Melayu. Bahwa dia tak mau +lagi menerima Lena kecuali anaknya itu sudah tobat. + + Merasa kena usir, Lena yang tak kalah keras kepala +dengan ayahnya tersinggung berat. Api dilawan api. Patah +arang dia dengan ayahnya. Diremasnya surat ayahnya sekuat +genggamannya, lalu dibantingnya tanpa ampun. Dia berjanji +kepada dirinya sendiri untuk takkan pernah kembali ke Beli- +tong. Wassalam. + +Zorro sendiri macam bola bekel dibuat nasib. Anak kecil itu +terombang-ambing dalam berbagai kepentingan orang dewa- +sa. Dia yang tak tahu apa-apa itu bak ekor badai, terbanting- +banting akibat kemelut rumah tangga. + + Selama hidup bersama dealer vespa itu dia selalu rewel. +Saban malam dia susah tidur lantaran tak ada orang yang +bercerita kepadanya kisah makanan dan tak ada yang mem- +bacakannya puisi. Dia merengek-rengek sambil bernyanyi tak + 236 ~ Andrea Hirata + +jelas. Sebenarnya, dia menyanyikan puisi merayu awan dan +dia menginginkan ayahnya, tetapi Lena tak mengerti. Diberi +mobil-mobilan dia menolak, diberi gula-gula dia minta balon, +dikasih balon dia minta balon gas, dikasih balon gas dia min- +ta gula-gula. Tak dikasih apa-apa, dia minta mobil-mobilan. +Diberi mobil-mobilan dan balon, dia minta balon gas. Diberi +mobil-mobilan, gula-gula, balon, dan balon gas, dia tak minta +apa-apa. + + “Apa sebenarnya maumu, Boi?!” Lena jengkel. + Zorro menangis. + Dalam kejengkelan yang memuncak lantaran tak tahu +cara menenangkan Zorro, Lena melihat tas punggung kecil +yang selalu dipakainya. Dibukanya tas itu dan ditemukannya +kemeja Sabari. Diberikannya kemeja itu kepada Zorro. Zorro +terpana lalu menjulurkan tangannya menerima kemeja itu. +Diciumi dan dipeluknya kemeja itu. Perlahan-lahan tangisnya +reda menjadi isakan sehingga tubuhnya tersentak-sentak. Aya, +aya, katanya. Tak lama kemudian dia tertidur. + Satire +Akhir Tahun + +SABARI takkan pernah lupa, hujan lebat, September, saat +itulah Lena mengambil Zorro darinya. Dua minggu setelah +itu ibunya meninggal. Hanya berselang tiga minggu setelah +itu, ayahnya meninggal. November, Marleni hilang. Tetangga +melihat kucing itu kabur bersama seekor kucing garong. + + Sabari mengalami situasi sudah jatuh tertimpa tangga, +lalu menginjak paku dan pakunya karatan, mengandung ba- +haya tetanus. Semua orang telah pergi naik kapal Nabi Nuh, +dia ditinggal sendiri, tak diajak. Yang tertinggal hanya dua +orang, dia dan sepi. + + Tengoklah apa yang tersisa sekarang, tak ada, selain ma- +lam yang senyap dan kafilah-kafilah angin yang datang dari +selatan, menampar-nampar atap rumbia, menyelisik daun- +daun kenanga, menjatuhkan buah kenari, menyapu pucuk- +pucuk ilalang, menepis permukaan Danau Merantik, lalu ter- +lontar jauh, jauh ke utara. Sesekali burung pipit yang tidur di + 238 ~ Andrea Hirata + +gulma-gulma terbangun, bercuit-cuit sebentar, berebut tem- +pat tidur lagi, lalu senyap lagi. + + Sabari duduk sendiri di beranda, mengamati garis-garis +nasib di telapak tangan kirinya, yang tampak nyata di bawah +sinar purnama kedua belas. Dia rindu kepada Zorro, Marle- +na, ayahnya, ibunya, dan Marleni. Sabari yang sentimental, +lembut, dan perasa. Air mata berjatuhan di telapak tangan +kirinya itu. Tangan kanannya teguh menggenggam pensil. + + Abu Meong kembali dari dapur dengan gaya berjalan +seperti orang habis melemparkan bola boling, lalu meloncat +lagi ke pangkuan Sabari. Mereka duduk memandangi purna- +ma kedua belas hingga rembulan tersembunyi di balik awan- +awan sisik Januari. + + Sabari sadar bahwa segala hal yang dia lakukan selama +ini, semangat yang tumbuh di sendi-sendi tubuhnya, setiap +tarikan napasnya, adalah demi anaknya, si kecil yang mu- +rah senyum itu. Tak bisa dialihkannya pikirannya dari Zor- +ro. Hampir tiga tahun, tak pernah walau hanya sehari dia +terpisah dari anaknya itu, tiba-tiba anaknya tak ada. Sering +dia melakukan rutinitasnya, bangun subuh, cepat-cepat men- +jerang air untuk membuat susu. Tergesa-gesa karena bangun +agak terlambat. Aduk ini, aduk itu, masukkan ke botol susu. +Bergegas ke kamar lagi, tetapi terkejut karena Zorro tak ada. +Sabari tersandar di dinding, tubuhnya lunglai. Dia bersimpuh +di lantai, tersedu-sedu tangisnya. + + Setiap hari Sabari dicekik kerinduan sekaligus kecemas- +an akan keadaan anaknya. Oleh karena itu, dalam waktu sing- + Ayah ~ 239 + +kat hidupnya merosot. Warungnya tak terurus, mismanagement. +Nama Buncai menghiasi buku utang hampir setiap halaman. +Nama Budimat dan Abdut muncul di buku itu sesering kata +barang siapa muncul di dalam Kitab Undang-Undang Hukum +Pidana. Nama Salamah tak pernah absen. Sesudah Salamah +selalu ada Jamot dan Mainap. Seisi kampung tahu ketiga pe- +rempuan itu saling bersaing dalam hal apa pun, ternyata juga +dalam hal berutang. Sabari membolak-balik buku utangnya +dan terkejut mendapati hampir setengah umat yang berada di +Jalan Padat Karya telah berutang di warungnya. Warungnya +kolaps. Karena patah semangat, Sabari juga tak mengurusi +kambing-kambingnya. Dengan harga murah kambing-kam- +bing itu dilegonya. Partikelir, itulah situasi Sabari sekarang. + Surat-Surat +Lena + +DAN, menikahlah Marlena dengan Manikam dan hiduplah +Zorro dengan dua saudara tiri yang terus-menerus memusuhi­ +nya. + + Untuk kali pertama dalam hidupnya, Lena mendapat +ketenangan di haribaan seorang pria berpendidikan tinggi, +berperangai baik, berkarier bagus, dan bergaji besar. Sejak +dapat bini baru, Manikam pun makin tegap langkahnya. Di +kantor dia makin berprestasi sehingga segera naik pangkat. + + Di rumah, kerap dia berkisah tentang foto yang dulu di- +kirim Lena dan betapa matanya yang indah serta lesung pipit- +nya membuat perasaannya tak keruan. + + Kata Lena foto itu diambil oleh kawan kerjanya, Laila, +di kursus komputer di Toboali. Yang mengirim foto itu juga +Laila. Kata Lena, mengutip ucapan Laila, jika mengirim foto +jangan yang lebih cantik daripada keadaan sebenarnya kare- + Ayah ~ 241 + +na masalah runyam bisa timbul belakang hari. Agaknya Laila +sudah tahu seni mengirim foto. + + Manikam mengatakan bahwa dia tertarik untuk me- +ngenal Lena lebih jauh karena 37 syarat yang ditetapkannya. +Lena tertawa. Katanya bukan dia yang menetapkan syarat- +syarat itu, melainkan semuanya karangan Laila, yang sudah +empat kali kawin cerai dan menganggap semua lelaki di dunia +tak lain selain buaya darat. + + Betapa Manikam pegawai negeri sipil terperanjat. Ber- +bulan-bulan dia terpesona dengan syarat-syarat itu. + + “Jadi, bukan kau yang membuat 37 syarat itu?” + “Bukan,” jawab Lena santai sambil membetulkan ikat +rambutnya. Tiba-tiba Manikam menjadi gugup. + Bulan demi bulan berlalu, genap empat tahun usia +Zorro dan hampir setahun Lena bersama Manikam. Setiap +malam Zorro hanya bisa tidur jika mencium kemeja itu. Dia +terkucil di rumah besar, yang semuanya berkilap, dingin, dan +asing. Sahabatnya hanya sebuah pedang plastik dan selembar +kemeja. Jika diperlakukan dengan kasar oleh saudara-saudara +tirinya, dia bersembunyi di pojok ruangan, dan dengan me- +nutupkan kemeja itu ke tubuhnya, dia merasa terlindungi. + Kerap Zorro memandangi kemeja itu, kemeja siapakah +itu? Ketika dipisahkan dari ayahnya, usianya belum tiga ta- +hun, saraf-saraf ingatannya belum terjalin dengan baik. Yang +menempel samar di benaknya hanya bau kemeja itu berhu- +bungan dengan seseorang yang dipanggilnya aya, selalu terse- + 242 ~ Andrea Hirata + +nyum kepadanya, selalu bercerita menjelang dia tidur, selalu +memeluknya, tetapi kian hari bayangan itu kian pudar. + + Zorro bertanya kepada ibunya tentang kemeja itu. Lena +bilang bahwa kemeja itu dibelinya di kaki lima pasar dalam +Tanjong Pandan, sepuluh ribu tiga! Jangan tanya-tanya lagi +soal kemeja kampungan itu! + +Sejak masih SD, Lena punya hobi bersahabat pena, dan sesa- +ma sahabat pena mereka telah berjanji untuk tetap berkirim- +kirim surat sampai tua nanti. Tiap bulan dia ke kantor pos +untuk mengirim surat. Lama-lama sekali dia juga mengirim +surat ke Belitong, kepada sahabatnya sejak SMA, Zuraida. +Maksudnya jika terjadi sesuatu, ada yang tahu di mana dia +dan Zorro berada. Namun, sehubungan dengan pecah kongsi +antara Lena dan ayahnya, semuanya harus dirahasiakan. Se- +cara diam-diam Zuraida akan memberi tahu ibu Lena bahwa +Lena dan Zorro baik-baik saja. + + Lama tak menerima surat dari Lena, akhir Maret itu, +Zuraida tercenung membaca kalimat terakhir dalam surat +Lena. + + Semuanya ada di sini. Zorro senang, aku senang, dan aku merasa +sangat bosan. + + Jika seseorang punya sifat pembosan di satu sisi dan di +sisi lain tidak punya respek terhadap lembaga-lembaga yang + Ayah ~ 243 + +telah bersusah payah diciptakan oleh pemerintah agar warga +negara Republik Indonesia bisa hidup lebih tenteram—lem- +baga itu misalnya KUA—kombinasi sifat semacam itu akan +membuat orang tersebut tak pernah berhenti mencari dirinya +sendiri. Zuraida kenal benar dengan Lena, dia tak terkejut +waktu bulan berikutnya menerima surat dari Lena bahwa dia +mau bercerai dari Manikam. + + Tentu saja Lena sudah cukup dewasa untuk memahami +bahwa bahtera rumah tangga tidak boleh pecah hanya lantar- +an salah satu pihak merasa bosan. Lambat laun Lena merasa +ada perbedaan karakter yang besar antara dia dan Manikam, +yang menyebabkan dia akan bersikap semakin tak adil kepa- +da Manikam jika terus melanjutkan rumah tangga. Inilah ri- +siko membangun rumah tangga melalui foto. + + Manikam berusaha membujuk Lena untuk tidak per- +gi, tetapi Lena bukanlah orang yang gampang ditaklukkan. +Bersusah payah Manikam minta izin dari kantor untuk per- +ceraian keduanya. Akhirnya, Manikam-Marlena tutup buku. +Mereka berpisah tanpa ribut-ribut. + + Lena memutuskan untuk hidup mandiri bersama Zorro +dan tetap tinggal di Bengkulu. Dia telah punya kawan-kawan +dan senang berada di kota yang memesona itu. Dia mau men- +cari kerja. Dia memang berjiwa pemberontak dan berwatak +keras seperti ayahnya, tetapi dia bukanlah orang yang tidak +pintar. + + Di Pangkal Pinang dulu, waktu masih menjadi istri dealer +motor vespa itu, dia ikut kursus komputer. Masa kini, siapa + 244 ~ Andrea Hirata + +yang berdaya menolak seorang sekretaris pintar berwajah +manis, yang lesung pipitnya pernah membuyarkan konsentra- +si pengatur lalu lintas sehingga simpang lima Kota Tanjong +Pandan macet total? + + Lena percaya diri dan cepat belajar, bisa komputer pula, +bahasa Inggris-nya lumayan. Ke mana pun dia melamar ker- +ja, asal ada wawancara dan orang sempat melihat penam- +pilannya, pasti dia diterima. Maka, Lena diterima bekerja di +sebuah perusahaan jasa ekspedisi yang mengirim furnitur an- +tarpulau. Distibutor susu kuda liar sampai memohon-mohon +agar perempuan manis itu mau bekerja dengannya. + + Tak mudah berjuang, tinggal di rumah petak yang kecil, +begitu Lena mengaku kepada Zuraida soal hidup mandirinya +bersama Zorro. Amat berbeda dengan hidupnya yang berke- +cukupan dengan Manikam. Namun, dia lebih senang keada- +an morat-marit ketimbang hidup dengan orang mapan yang +semua yang akan terjadi dengan mudah dapat diramalkan. + + Dapat mengambil keputusan sendiri adalah kemerdekaan yang in- +dah. Ada perasaan lega yang tak dapat kulukiskan dengan kata-kata. Ke- +jutan yang menyenangkan terjadi setiap hari. Aku tak tahu apa lagi yang +akan terjadi dalam hidupku, Zurai, cinta adalah sahabat yang licik, tapi +aku siap menerima tantangan baru. + + Jiwa manusia memang lebih rumit daripada konstelasi +bintang gemintang di angkasa. Lena pun bercerita bahwa dia + Ayah ~ 245 + +sering bepergian dengan Zorro. Mereka pergi ke mana pun +mereka suka, dan katanya, Zorro menuruni sifatnya, senang +berkelana. Zuraida membalas. + + Berkirim suratlah terus, Boi, aku suka membaca kisah-kisahmu. +Dari segenap perjalananmu itu, apakah kau terpikir untuk pergi ke Ban- +da Aceh? Kalau iya, aduh, beruntungnya kau dapat melihat kota yang +hebat itu. Kota tua bersejarah, dan Masjid Baiturach­man. Aku hanya +bisa melihat masjid megah itu dari almanak 78, tak pernah kuganti +bagian itu. Lena. Kalau kau sempat ke sana, berfotolah di muka masjid +itu, kirimkan kepadaku fotonya. + +Lena tak pernah tahu betapa surat-suratnya telah memenga- +ruhi Zuraida, perempuan penyendiri pembuat kue satu itu. +Seperti Izmi yang diam-diam terinspirasi oleh Sabari, diam- +diam Zurai merasa dikuatkan oleh surat-surat Lena. Dia ka- +gum akan pendirian Lena, betapa sahabatnya itu telah ber- +kelana dan tak pernah ragu untuk menjadi dirinya sendiri, +seseorang yang berani berdiri tegak untuk mengatakan apa +yang diinginkan dan tak diinginkannya, seseorang yang da- +pat memerdekakan diri dari kebergantungan atas apa pun, +termasuk atas rasa malu yang tak beralasan. Seseorang selalu +tersenyum meski kesulitan mengimpit dan melangkah lagi un- +tuk melihat kemungkinan baru. + 246 ~ Andrea Hirata + + Tak pernah sebelumnya Zuraida berani mengunjungi +pasar malam sendiri. Di depan kaca, dikuatkannya hatinya +bahwa tak perlu menunggu punya pasangan hanya sekadar +untuk naik komidi putar yang disukainya, menyaksikan aksi +tipu daya tukang dadu cangkir, melihat para pembalap tong +setan dari Mojokerto, sambil menikmati kembang gula. + + Tak sedikit yang berbisik-bisik dan memandangnya de- +ngan aneh. Zuraida melangkah dengan tenang, sendiri di +tengah hiruk pikuk pasar malam. Dia menyaksikan apa pun +yang disukainya, membeli apa pun yang diinginkannya, dia +tersenyum, tertawa, dan bertepuk tangan, sesuatu yang tak +pernah berani dilakukan sebelumnya. Surat-surat Lena telah +membuatnya menemukan seseorang yang baru dalam diri- +nya, seseorang yang lebih gembira dan bernyali. Di sebelah +sana, Izmi sibuk mengokang senapan mainan, lalu membidik +bebek yang lewat dengan cepat. Dia menembak dan memele- +set, berderailah tawanya, sendirian. Telah lama Zuraida dan +Izmi tak merasa gembira seperti malam itu. + “Besame Mucho” + +HAMPIR setahun Marlena hidup berdua saja dengan Zorro +sebagai—istilah populer masa kini—single mother. Lena gem- +bira karena semakin dekat dengan Zorro, yang telah berusia +lima tahun, semakin cerdas, dan semakin tampan. + + Zorro masih selalu bertanya, siapakah pemilik keme- +ja yang dia tak bisa tidur jika tak menciumnya? Lena selalu +mengalihkan pembicaraan. Setiap malam, Zorro dininabo- +bokan bau dan kenangan berkabut yang menguar dari ke- +meja itu. Setiap malam pula Lena membaringkan satu sosok +pemberontak yang bersembunyi dalam dirinya. + + Pada Sabtu sore itu, Marlena mengajak Zorro ke alun- +alun Rajo Malim Paduko untuk menonton festival musik. +Festival yang meriah. Ada beberapa panggung pertunjukan. +Di salah satu panggung, sepasang MC mengumumkan—se- +telah melakukan gerakan tangan secara seragam dan secara +bersama mengucapkan hal yang sama—melalui festival seni kita + 248 ~ Andrea Hirata + +tingkatkan bla ... bla ... bla—bahwa di panggung itu akan segera +tampil sebuah band legendaris dari Medan. Lena dan Zorro +melangkah ke arah panggung itu, satu langkah nasib. + + Akhirnya, muncullah band dari Medan itu. Rata-rata +pemain musiknya berambut panjang. Intro berkumandang, +seorang lelaki mendekati mik dan mulai bernyanyi. + + Setelah itu, tak ada, tak ada yang bisa disalahkan sela- +in lagu “Besame Mucho”. Mulanya Lena merasa biasa saja. +Seperti anak Melayu yang umumnya tumbuh dalam budaya +radio, dia tahu banyak tentang lagu dan tahu penyanyi yang +masuk akal bertingkah laku di depan mik. Dia dapat membe- +dakan antara bernyanyi dan ngomel-ngomel, khotbah, atau +melolong sekehendak hati diiringi bunyi-bunyian. Singkat ce- +rita, tak mudah membuatnya terkesan melalui musik, tetapi +lelaki di atas panggung itu dalam waktu singkat langsung me- +nyita perhatiannya. + + Alunan suaranya, denting gitarnya, sinar matahari sore +yang menyinarinya dari samping, dan angin lembut dari arah +Sungai Bantai yang mengibarkan rambutnya, membuat hati +Lena tak keruan. + + “Besame Mucho” berakhir, langsung disambut entakan +drum yang khas, Marlena langsung tahu intro itu. + + “Ruby! Ruby!” pekiknya dalam hati. + Penyanyi itu tersenyum dan bernyanyi lagi. + Lena hafal lagu country lama yang lincah itu. Dia ikut +bernyanyi. Penyanyi pun senang melihat salah seorang pe- + Ayah ~ 249 + +nonton mengikuti lagunya. Petikan gitarnya membuat Mar- +lena mengajak Zorro menari. Zorro berputar-putar riang +mengikuti tangannya yang diputar-putarkan ibunya. Marlena +terus bernyanyi oh, Ruby, don’t take your love to town .... Zorro +tertawa riang. + + Dari atas panggung, penyanyi melihat para penonton +bergerak lambat, lalu membentuk lingkaran dan menari me- +ngelilingi seorang perempuan cantik dan anak lelakinya yang +menari canggung sambil tersipu malu. + + “Ruby” selesai bersama riuh tepuk tangan penonton. +Penyanyi melambaikan tangan kepada Marlena dan Zorro. +Marlena tak membalas karena tertegun menatap lelaki yang +indah itu. Dia dilanda pikiran tentang betapa besar kebaha- +giaan dapat diberikan sebuah lagu dan betapa besar seorang +penyanyi dapat membuatnya terpukau. Zorro heran melihat +tingkah ibunya. + + “Ada apa, Ibunda?” + Lena menatapnya dan tersenyum lebar. + “Siap-siap, Boi, kita akan berangkat ke Medan!” + +Pedih hati Ukun mengetahui Mbak Yu sudah digaet pega- +wai PDAM. Yuyun pun sudah digondol anak buah kapal feri +Samudera Jaya. Bahkan, perempuan yang tak banyak bicara +tetapi banyak tersenyum, yang suka duduk di bangku taman +balai kota itu, sudah serius dengan seseorang. + 250 ~ Andrea Hirata + + Mereka bosan terjebak dalam hal yang itu-itu saja, ba- +ngun tidur, bekerja, nongkrong di warung kopi, pulang, tidur +lagi, bangun lagi, bekerja lagi, nongkrong lagi, pulang lagi, +tidur lagi. SSDD, same sh$#different day. Kebosanan itu kejam, +tetapi kesepian lebih biadab daripada kebosanan. Kesepian +adalah salah satu penderitaan manusia yang paling pedih. + + Tidak hanya konyol, tetapi juga riskan mengharapkan +nasib berubah dari melihat saat-saat mistik ketika langit menjadi +biru di pantai barat sana. Kejadian itu belum tentu setahun +sekali. Tindakan yang lebih kongkret harus diambil, yakni ko- +lom jodoh di koran lokal, halaman tujuh. + + Pagi-pagi pada hari Minggu, Ukun dan Tamat sudah +berada di warung kopi Solider dan langsung menyambar ko- +ran lokal. Tak keruan hati mereka melihat propaganda ten- +tang mereka sendiri di kolom jodoh. + + UK, Pria (32), perjaka, suku Melayu, ramah, bertanggung ja- + wab, ijazah SMA, punya pekerjaan tetap di bidang mekanika dan + elektronika, sehat badan & pikiran, tak berminat pacaran, serius, + langsung menikah. Mencari wanita, belum pernah menikah, pega- + wai negeri, sehat, berpenampilan menarik, usia selaras. Peminat + silakan hubungi redaktur dengan kode UK32/per658/90. + + Sebenarnya, dalam kolom pekerjaan Ukun mau me- +nambahkan, khususnya untuk produk berteknologi digital dari Jepang. + Ayah ~ 251 + + Redaktur bertanya, “Pekerjaan Abang sebenarnya apa, +sih?” + + “Tukang gulung dinamo, Pak.” + Redaktur segera menyuruh Ukun tutup mulut. + Propaganda Tamat lebih kurang sama. Pada bagian +pekerjaan dia agak sungkan menyebut profesinya sebagai tu- +kang kipas satai di restoran kambing muda Afrika. Digantinya +secara diplomatis: aktif di bisnis kuliner, dan selain meminati +pegawai negeri, dia menambah sedikit, kalau bisa guru. + Perempuan para pegawai warung kopi yang merubung +koran Minggu mencibir iklan Ukun dan Tamat, banyak tingkah! +kata mereka. + Redaktur sependapat. + “Tentu saja tak ada respons, Boi, karena syarat kalian +berat sekali. Mana ada pegawai negeri mencari jodoh lewat +kolom jodoh.” + Ukun dan Tamat sepakat mengurangi syarat, menjadi +cukup belum pernah menikah, berpenampilan menarik, dan usia sela- +ras. Respons tetap nihil. Syarat dikurangi lagi menjadi: siapa +saja, asalkan perempuan yang serius mau menikah. Tetap tak ada res- +pons, mungkin karena para pegawai warung kopi itu saling +mengingatkan agar jangan pernah berhubungan dengan pria +yang putus asa. + Sebaliknya, Ukun dan Tamat kerap menanggapi wanita +yang memasang profilnya di kolom jodoh itu. Namun, usai + 252 ~ Andrea Hirata + +sekali bertemu, mereka tak pernah dihubungi lagi oleh wanita +itu. Tak ada follow up istilahnya. + + Lantaran jengkel, sudah enam bulan Ukun bersurat- +surat dengan seorang perempuan yang juga dikenalnya lewat +kolom jodoh. Berkali-kali perempuan dari Sekunyit itu meng- +ajaknya kopi darat, Ukun selalu menghindar. Karena, dia tahu +semuanya akan gagal setelah wanita itu melihatnya. + Kisah +Keluarga Langit + +ADA bentuk-bentuk gembira kecil, misalnya waktu tukang +cat menemukan duit dua ribu perak dibungkus plastik dalam +kaleng cat tembok, atau jika Jumat tanggal merah. Atau, saat +mendengar pramugari berkata bahwa sebentar lagi pesawat +akan segera mendarat, atau secara tak sengaja sandal kita +tertukar dengan sandal orang lain, yang lebih bagus. Atau, +saat pelukis menempelkan label sold pada lukisannya, tetapi +nilai gembira yang dirasakan JonPijareli setara dengan semua +gembira kecil tadi diakarkan, lalu dipangkatkan enam, hasil- +nya dipangkatkan enam lagi (mengapa harus repot-repot diakarkan +dulu? Misteri.). + + Dari orang yang suntuk, mumet, dan sumpek, setelah +berkenalan dengan Lena, sekonyong-konyong Jon jadi ceria. + + “Biarlah kita jatuh cinta dan biarlah waktu mengujinya.” +Bukan main kata-katanya itu. Lain waktu dia berkata betapa +dia bersyukur telah berjumpa dengan Lena. + 254 ~ Andrea Hirata + + “Waktu kau datang, aku sedang sakit. Tahukah kau, +Lena?” + + Demam? + “Orang yang datang membawa cinta kepada orang yang +sedang sakit, dia membawa kesembuhan.” + Bicara apa orang ini? + “Ah, indah sekali!” Jon memuji kata-katanya sendiri. +“Bolehkah kupakai untuk lirik lagu ciptaanku?” + Kata-katamu sendiri, suka-sukamulah, aih, satu lelaki, seribu ce- +rita. + Menggelikan, sebelum berangkat ke festival di Bengku- +lu, lantaran merana, Jon berkata kepada siapa saja bahwa dia +akan pensiun. Bahwa band-nya akan dilungsurkannya kepada +Boros Akinmusire, pemain trompet nan jempolan itu. Lena +telah mengubah segalanya. + Perkawinan Jon dengan Lena adalah perkawinan ketiga +dan dengan segera sang musisi menganggap angka tiga se- +bagai angka keramat. Dari perkawinan sebelumnya, Jon tak +pernah punya anak karena itu dia senang sekali kepada Zor- +ro. Lagi pula, siapa yang tak jatuh hati kepada bocah tampan +yang pintar itu? Zorro membuat Jon menjadi seseorang yang +diam-diam, jauh dan getir di dalam hati, selalu diinginkan- +nya: ayah. + “Siapa namamu, Anak Muda?” tanya Ibu Basaria, siap +mengisi formulir pendaftaran kelas satu SD. Dengan tangan- +nya, Zorro melukis huruf Z di udara. + Ayah ~ 255 + + “Zorro!” pekiknya. + Bu Basaria tergelak. “Oh, Zorro macam di pelem itu?” + Zorro mengangguk. + “Maaf, Bu, itu nama panggilannya.” Lena kemudian +menyebut nama asli anaknya. + “Nama yang bagus, berawalan huruf A. Tapi, nama +berawal A suka dipanggil kali pertama oleh guru-guru, untuk +menjawab pertanyaan, untuk bernyanyi. Apakah kau siap, +Anak Muda?” + Zorro berdiri dan dengan sengit melukis lagi huruf Z. + Saban hari Jon mengantar Zorro ke sekolah dan men- +jemputnya. Jon senang melakukannya, Zorro pun senang +dibonceng naik motor BSA. Dipeluknya kuat-kuat pinggang +ayahnya dari belakang. Dadanya berdentam-dentam seirama +dentum knalpot motor besar itu. Kata guru-guru Zorro ada- +lah murid yang istimewa. + “Cerdas dan banyak kali tahu kata-kata, jauh di atas +rata-rata anak-anak seusianya. Apakah dia diajari kata-kata +di rumah?” + Jon dan Lena menggeleng sambil tersenyum geli. + Zorro naik ke kelas dua menduduki peringkat pertama. +Nilai-nilainya jauh meninggalkan Imelda di peringkat kedua. + Lena tercenung melihat rapor anaknya. Zorro telah ter- +tidur sambil mencium kemeja itu. Dari kaca jendela Lena me- +lihat jalan raya M. Yamin yang panjang, dipagari tiang-tiang +lampu jalan. Kantor pos, kantor Telkom, rel kereta tampak di + 256 ~ Andrea Hirata + +ujung sana. Cahaya kuning yang terang sambut-menyambut +menerangi jalan. Sesekali melintas orang-orang mendorong +gerobak sambil memukuli kuali. Dari jauh terdengar bunyi +kereta terakhir melintas, sesudah itu senyap. Makin senyap +Jon memainkan lagu yang pelan dengan gitarnya. Lena rindu +pada Belitong, keluarga, dan kawan-kawannya. Diambilnya +kertas dan pulpen, ditulisnya surat. + +Ke hadapan kawanku, Zuraida, di Belantik, + +Halo Boi, apa kabarmu? + Semoga kau dalam keadaan baik dan sehat. Maafkan sudah lama + +aku tidak memberimu kabar. Bukannya aku telah melupakanmu, melain- +kan di Medan banyak hal yang terjadi sehingga aku menunggu saat yang +tepat untuk menulis surat. + + Aku menulis surat ini dalam keadaan sedih sekaligus gembira. Se- +dih kalau teringat masa lalu, gembira karena keadaanku sekarang. Hidup +selalu menghadapkan kita pada pertukaran, pertukaran antara apa yang +kita dapatkan dan apa yang kita korbankan, pertukaran antara prinsip +yang kita pegang dan nama baik yang kita pertaruhkan. Adakalanya +pertukaran itu sulit, yaitu antara apa yang kita anggap benar dan orang +lain menganggap apa yang kita anggap benar itu salah (kurasa itulah +yang telah terjadi antara aku dan ayahku). Dalam pertukaran itu setiap +hari kita membuat pilihan dan keputusan, dan masing-masing punya +risikonya sendiri-sendiri. + Ayah ~ 257 + + Kubayangkan hidupku jika dari dulu selalu patuh akan nasihat +ayahku. Namun, mungkin jalan pahit yang berliku-liku inilah yang harus +kutempuh. + + Aku tak menyangkal bahwa banyak peristiwa masa lalu yang ku- +sesali sekarang. Karena waktu itu aku muda, bodoh, dan marah. Namun, +bukankah kita tidak benar-benar hidup jika kita hidup tanpa penyesalan? + + Aku telah mengambil pilihan yang sulit sampai akhirnya bertemu +dengan pemusik ini. (Kuharap kau tertawa, Boi, karena di sini aku terse- +nyum, lihatlah dia sedang memainkan gitarnya di situ. Kuharap dia tak +membawakan lagu “Hotel California”!) + + Dan kuharap kau pun segera menemukan cinta sejatimu. Karena +cinta sejati akan melemparkanmu pada sebuah tempat yang dari situ kau +dapat melihat segala sesuatu dalam hidupmu dengan jernih. Aku selalu +merasa Bogel Leboi adalah cinta pertamaku, rupanya aku keliru. Cinta +pertamaku, setelah malang melintang berkenalan dengan banyak orang +dan tiga kali kawin cerai, adalah JonPijareli, gitaris Medan, percayakah +kau? + + Salam rindu. Zurai, ciumlah tangan ibuku untukku. + Sahabatmu selalu, + Lena + +Anak yang sehat, baik budi, dan pintar, suami musisi berbakat +yang dicintai setengah mati, tak ada lagi yang diminta Lena +dari hidup ini. Namun, rapor Zorro pada semester 1 kelas + 258 ~ Andrea Hirata + +dua jatuh. Dia hanya menempati urutan kedua. Saingan be- +ratnya, Imelda, berjaya di posisi teratas. Lena dan Jon mena- +nyakan kepadanya apa yang terjadi. Jawaban Zorro membu- +at mereka tercengang. Kata Zorro dia sengaja menurunkan +nilainya, sengaja tak menjawab beberapa soal dalam ujian, +sengaja membuat dirinya kehabisan waktu dalam ujian ka- +rena kasihan kepada Imelda yang sangat ingin menjadi juara +pertama. Bagaimana anak kelas dua SD bisa berpikir seperti +itu? Bayangan Sabari berkelebat dalam kepala Lena. + + Lena dan Jon membiarkan apa yang terjadi. Mental +lebih penting daripada akal, barangkali itu prinsip mereka. +Zorro pun biasa saja. Menempati urutan kedua malah mem- +buatnya semakin ceria dan semakin mudah berkawan dengan +Imelda. Suatu hari, menjelang kenaikan kelas, karena teram- +pil berbahasa, Zorro diikutkan lomba bercerita tingkat anak- +anak. Cerita haruslah karangan anak-anak sendiri. + + Banyak sekali penonton lomba itu. Guru-guru, para sis- +wa, orangtua murid, dan penonton lainnya. Jon dan Lena du- +duk di deretan bangku paling depan. Zorro naik panggung, +meraih mik, dan mulai bercerita: + +Tahukah dirimu, Kawan? Langit adalah sebuah keluarga. Anaknya ada +dua, Angin dan Awan. Ayahnya adalah Matahari. Ibunya Bulan. + + Angin senang berkeliaran sesukanya, memelesat ke selatan, meng- +goda ilalang, berputar di atas ombak, terlambung tinggi ke angkasa, lalu +berpencar ke delapan penjuru. Jika sore, ayahnya, Matahari, memang- + Ayah ~ 259 + +gilnya dan kita mendapat senja yang indah. Jika malam, Angin tak ber- +embus karena Bulan memeluk anak bungsunya. + + Awan adalah anak perempuan yang suka bersedih. Oleh karena +itu, manusia bisa mengajak Awan bercakap-cakap. Jika awan gelap dan +manusia tidak menginginkan hujan, Awan bisa dibujuk. Berhentilah se- +jenak di mana pun kau berada, tataplah Awan dan berbicaralah dengan- +nya agar dia menunggu sebentar saja sampai engkau sampai di rumah. + + Akan tetapi, kau hanya bisa membujuk Awan dengan puisi dan +puisi itu harus kau nyanyikan. Seperti ini nyanyiannya .... + + Wahai Awan + Aku ingin sekolah, janganlah dulu kau turunkan hujan + Ajaklah Angin, untuk menerbangkanmu ke selatan + Wahai Awan + Janganlah dulu kau turunkan hujan + Wahai Awan, kuterbangkan layang-layang untukmu + + Penonton terpana mendengar anak kelas dua SD dapat +bercerita seperti itu. Jon ternganga, Lena menggenggam ta- +ngannya kuat-kuat. Tadinya mereka pikir akan mendengar +cerita Zorro, seperti cerita anak-anak lainnya, tentang kucing, +kancil, petualangan ke rumah bibi selama libur sekolah mere- +ka. Namun, cerita Zorro sangat berbeda. + + Mata Lena berkaca-kaca. Dari seluruh prahara yang te- +rus-menerus menderanya, selama bertahun-tahun, untuk kali +pertama, di muka panggung lomba cerita itu, dia menangis. +Benar kata orang, sekuat apa pun halangan, setinggi apa pun + 260 ~ Andrea Hirata + +tembok menjulang, tak ada yang tak dapat diluruhkan seo- +rang anak. + + Bu Basaria berdiri dan bertepuk tangan, diikuti tepuk +tangan riuh penonton lainnya. Dia menoleh sekeliling seakan +memberi tahu setiap orang bahwa Zorro adalah muridnya. + + Zorro menjadi juara lomba. Di rumah Lena bertanya, +bagaimana dia bisa mengarang kisah keluarga langit itu? Zor- +ro menatap ibunya. Dia tak bisa menjawab karena dia sendiri +heran bagaimana dia bisa bercerita seperti itu. + Sketsa + +FEBRUARI menjelang. Meski tahun demi tahun tak pernah +melihat langit menjadi biru, Ukun dan Tamat tetap datang ke +pantai barat. Lebih mudah mendapat kenalan ketika semua +pendamba cinta berkumpul pada satu tempat, seperti pasar +jodoh. Itukah sesungguhnya maksud mitos saat langit menjadi +biru? Yakni kebijakan budaya saja agar orang-orang gampang +menemukan pasangan. Barangkali tak ada hubungannya de- +ngan fenomena alam. + + Usailah musim barat dan usailah masa pancaroba. +Anak-anak punai yang selamat dari ganasnya musim hujan +mulai belajar terbang labuh, terbang sebentar, lalu berlabuh +di dahan-dahan rendah. Kepompong telah bersayap menjadi +kupu-kupu. Abu Meong memanggil-manggil Marleni yang +telah pergi. Sabari kian merana. + + Sejak ditinggalkan Marleni, Abu Meong mengeong- +ngeong parau sepanjang malam, sampai habis suaranya. Iba + 262 ~ Andrea Hirata + +Sabari melihatnya. Marleni tiba-tiba hilang. Kata tetangga, +betina itu kabur bersama seekor kucing garong yang diduga +berasal dari pasar. + + Maka, saban sore Sabari menggendong Abu Meong dan +membawanya ke pasar. Di gang-gang pasar yang sempit, Sa- +bari memanggil-manggil. + + “Leni, Leni, miau ... miau ....” Sahut-menyahut dengan +panggilan pilu Abu Meong. Suara mereka menyelusuri re- +lung-relung pasar yang sepi. + + Leni tak juga muncul. Seperti Zorro, Leni telah hilang +tak tahu rimbanya. Dalam banyak hal Sabari melihat nasib- +nya serupa dengan nasib Abu Meong. Mereka sama-sama di- +tinggalkan istri. Sabari bertekad menemukan Leni. + + Di dalam film yang pernah ditontonnya, Sabari pernah +melihat orang mencari kucing hilang dengan menempelkan +foto kucing itu di tiang-tiang listrik dan di tempat-tempat +umum disertai tulisan ke mana harus menghubungi jika me- +lihat kucing itu. Sabari ingin melakukannya, tetapi tak punya +foto Marleni. Dia berpikir, jika tak ada fotonya mungkin bisa +pakai sketsanya saja. Untuk itu dia tahu siapa yang harus di- +hubungi, yaitu guru Seni Rupa SMA dulu. + + Bu Woeri sudah pensiun dan hidup sendiri. Dia terke- +jut sekaligus senang menerima kedatangan Sabari, muridnya +dulu. Setelah berbasa-basi, Ibu berkata, “Kudengar bini kau +sudah diambil orang ya, Boi?” + + “Iya, Bu.” + Ayah ~ 263 + + “Siapa yang mengambil binimu?” + “Dealer motor vespa, Bu.” + “Jadi, kau diceraikan binimu.” + “Iya, Bu.” + “Anak kecil yang suka sama kau itu juga diambil bini- +mu?” + Sabari menunduk. + “Orang-orang bilang kau kehilangan sekali akan anak- +mu itu ya, Ri?” + Sabari menunduk semakin dalam. + “Kalau kita punya, yang kita punya bisa diambil orang, +kalau kita tak punya, tak ada yang bisa diambil orang.” + Bu Woeri yang memutuskan hidup sendiri, membekap- +kan tangan di dada sambil melihat sekeliling rumahnya yang +sederhana. Seseorang pernah mengambil sesuatu darinya, +sekarang dia tenang karena tak punya apa-apa lagi untuk di- +ambil. + “Maka, lebih baik jika kita tak punya.” + “Iya, Bu.” + “Anakmu itu bernama Zorro, bukan?” Bu Woeri kenal +dengan Zorro. Dulu di taman balai kota Sabari pernah me- +ngenalkan anaknya kepadanya. + “Anak yang tampan. Begitu tampan, sampai aku masih +ingat wajahnya.” + Sabari menyampaikan maksud kedatangannya bahwa +kucingnya hilang dan sketsa Marleni yang dibuat Bu Woeri + 264 ~ Andrea Hirata + +nanti akan diperbanyaknya, lalu ditempelkannya di mana- +mana. + + “Oh, cerdas sekali, Boi.” Ibu bersemangat dan cepat- +cepat mengambil kertas gambar dan pensil-pensil berwarna. +Dipasangnya kertas di dudukan lukisan, pensil di tangan. Sa- +bari duduk di sampingnya. + + “Ojeh, Boi, sila ceritakan dengan teliti bagaimana ben- +tuk muka kucing itu, warnanya, pola belangnya, bentuk muka- +nya, matanya, telinganya, hidungnya, mulutnya, semuanya.” +Sabari menatap Bu Woeri lalu melemparkan pandangannya +ke luar jendela. + + “Mukanya ...,” katanya pelan. + “Mukanya agak lonjong.” + Bu Woeri segera menggoreskan pensil dan menggambar +satu bentuk muka kucing. + “Maaf, pipi dan dagunya tidak seperti itu, Bu, agak se- +perti ini.” Sabari menggambarkan bentuk dengan kedua ta- +ngannya. Bu Woeri membuat penyesuaian dan tak suka kare- +na bentuk muka itu mirip muka manusia, bukan muka kucing. +Namun, didiamkannya, biarlah diperbaiki kemudian. + “Telinganya, Boi?” + “Telinganya kecil.” + Ibu menggambar dua telinga. + “Hidungnya?” + “Hidungnya juga kecil, tapi panjang.” + Lincah tangan Ibu menggaris gambar hidung. + Ayah ~ 265 + + “Mulutnya?” + “Bibir atasnya seperti dua bukit yang bertemu, bibir +bawahnya seperti lengkung perahu, mulutnya selalu terse- +nyum.” Ibu berusaha menggambar sebaik mungkin sesuai +keterangan Sabari. + “Matanya, Boi?” + “Bulu matanya lentik, Bu, matanya indah sekali, seperti +mata ibunya. Bola matanya cokelat dan bening. Bentuk mata- +nya seperti buah kenari muda.” + Ibu melukis semuanya dan takjub melihat yang dilukis- +nya bukan wajah seekor kucing, melainkan wajah seorang +bocah, bocah yang tampan, yang mengingatkannya kepada +anak kecil yang pernah dikenalnya, Zorro. + Kota yang Pandai +Berpuisi + +SEMUANYA tampak sempurna, sayangnya tak berlangsung +lama. + + Lena mengetahui Jon tak setia, yang menurut banyak +orang juga menjadi penyebab dua perceraiannya sebelumnya. + + Lena bukanlah tipe lampu hijau, lampu kuning, lampu +merah. Dia hanya akan memperingatkan sekali, setelah itu +tiada maaf, khatam, tamat, the end, finito, game over. Pesannya +untuk kawan-kawannya dan dirinya sendiri terutama, jika +menghadapi pasangan yang selingkuh: get out, don’t look back. +Berkali-kali Jon membujuk Lena dan minta ampun macam +orang Lebaran, tetapi Lena adalah perempuan besi dengan +pendirian yang lebih tegak dari pada tiang bendera di La- +pangan Merdeka. + + Bagi Lena, hidup ini terlalu singkat untuk dilewatkan +dengan orang yang tak setia. Penyelewengan adalah penyakit +kambuhan yang harus dibasmi dengan sekali bidik. Selingkuh + Ayah ~ 267 + +ibarat ular yang menggigit ekornya sendiri, takkan berkesu- +dahan. Dulu dia memang punya banyak pacar, tetapi dia tak +pernah menjalin hubungan dengan lebih dari satu orang da- +lam waktu yang sama. Dalam suratnya kepada Zuraida, Lena +berkata, manusia bisa berada di tempat yang sama dalam +waktu yang berbeda, tetapi tak bisa berada di tempat yang +berbeda dalam waktu yang sama, semua itu karena pencipta +manusia mau agar manusia setia. Kata-kata Lena itu macam +teori lorong waktu, aneh, ganjil, tetapi hebat. + + Dalam surat itu Lena juga menulis bahwa sesungguhnya +ada dua orang yang amat dicintainya di dunia ini—sekaligus +dibencinya—yaitu JonPijareli dan ayahnya. + + Lena dan Zorro mengemasi tas dan meninggalkan Me- +dan yang mereka cintai. Lena merasa pahit. Tak pernah dia +begitu sedih putus hubungan dengan seseorang seperti dia +putus hubungan dengan Jon. Terseok-seok dia membawa tas +yang besar. Zorro kecil juga menyandang tas dan tas pung- +gungnya, berlari-lari limbung mengikuti ibunya. Lena me- +nguatkan dirinya. Aku Marlena, anak ayahku, Markoni, berpantang +menangis. Ibu dan anak itu duduk rapat-rapat di Terminal Pi- +nang Baris, tak tahu mau ke mana. + +Lena merasa telah mengambil putusan terbaik ketika meni- +kah dengan Jon, tetapi kini baginya bagaikan putusan terbu- + 268 ~ Andrea Hirata + +ruk dalam hidupnya. Terpukul hebat akibat perpisahan itu +di satu sisi dan berjiwa pemberontak di sisi lain, Lena beling- +satan. Satu tempat tak pernah dapat memadamkan kecewa, +sedih, sesal, dan marah kepada Jon, terutama kepada dirinya +sendiri. Mulailah Lena dan Zorro hidup berpindah-pindah +seperti kaum nomaden. Zorro tergopoh-gopoh mengejar ibu- +nya. + + Zorro besar di jalan, terbiasa menempuh perjalanan +jauh, naik bus antarkota, naik kereta, dan kapal feri. Dia men- +jalani hidup yang tak sepatutnya dijalani anak kecil. Dalam +perjalanan yang tak henti-henti itu sering dia dan Lena tidur +di stasiun kereta, pelabuhan, atau bangku-bangku terminal. +Tak jarang mereka berhadapan dengan orang-orang yang +kasar. + + Pernah suatu malam tempat tinggal Zorro didatangi po- +lisi. Sirene bertalu-talu. Lena dibawa polisi. Ketar-ketir hati +Zorro menunggu di pekarangan kantor polisi. Tak tahu apa +yang terjadi dengan ibunya di dalam sana. Dadanya sesak +menahan tangis. Waktu ibunya keluar, dia berlari tergopoh- +gopoh menyongsongnya. + + “Apa yang terjadi, Ibunda?” + Ibunya tak menjawab. + Berkali-kali, tanpa alasan jelas, ibunya membangunkan- +nya tengah malam, mereka berlari pontang-panting hanya +membawa barang-barang yang bisa disambar dengan cepat, +lalu terdengar suara orang berteriak-teriak. Zorro tak tahu + Ayah ~ 269 + +dengan siapa dan untuk urusan apa ibunya terlibat. Adakala- +nya Lena meninggalkannya selama berhari-hari. + + Zorro berusaha memahami ibunya, dan baginya adalah +kewajiban seorang anak untuk memahami orangtua. Maka, +meski hidup mereka kocar-kacir, Zorro dan ibunya kompak +saja. Mereka adalah ibu dan anak, tetapi sering bak kawan +dekat. Zorro tahu ibunya tengah mengalami saat-saat yang +sulit. Dia ada di sana untuk ibunya. Dia selalu berusaha mem- +besarkan hati ibunya, melindunginya, sekuat kemampuannya. + + Cobaan yang bertubi-tubi membuat Zorro menjadi bo- +cah yang tangguh. Pikirannya jauh lebih dewasa daripada usia-­ +nya. Apa yang tak mampu membunuhmu akan membuatmu +semakin kuat. Ungkapan itu berlaku untuk Zorro. Jika kea- +daan memburuk, dia mengucilkan diri dan mencium kemeja +itu dan mengenang satu masa yang indah, saat seorang lelaki +menyayanginya, memeluknya menjelang tidur, selalu melin- +dunginya. + + Dalam masa yang gelap itu, kerap Sabari terbangun ka- +rena mimpi yang buruk. Dalam mimpinya dia melihat seekor +anak kucing terpincang-pincang karena dilempari orang de- +ngan batu. Sampai pagi dia tak bisa tidur. Dia tahu sesuatu +yang buruk sedang menimpa Zorro. + + Sesekali Lena dan Zorro tinggal di panti asuhan atau +tempat-tempat milik yayasan. Jika berada di sebuah kota, +Lena bekerja apa saja, menjadi pegawai pabrik, menjadi pe- +gawai tukang jahit, pelayan restoran, penjaga toko, sales girl, + 270 ~ Andrea Hirata + +pengasuh anak, pengasuh orang tua, atau pembantu rumah +tangga. Namun, tak pernah berlangsung lama. Sekolah Zorro +tak keruan karena dalam satu semester bisa pindah sampai +tiga kali. + + Setiap kali pindah, Zorro selalu mengenang kota yang +telah mereka singgahi dengan menulis puisi kecil. + + Yang kan kukenang hingga akhir nanti + Takkan habis jumlah jari jemari + Salah satunya engkau, Batanghari + + Berdiri aku di tepi sungaimu + Terpana aku melihat sejarah mengalir di situ + Siak, Siak + Kenanglah aku + Seperti aku kan selalu mengenangmu + + Bulan lebih rendah + Bintang-bintang dapat dijangkau + Matahari lebih hangat + Karena ingin melihat Rengat dari dekat + + Kulihat rumah berbaris-baris + Di pekarangan bersenda gadis-gadis + Tiada pantun yang lebih manis + Selain pantun dari Bengkalis + Ayah ~ 271 + + Bagai sampan terikat pada bengawan + Bagai ikan terikat pada lautan + Bagai angin terikat pada awan + Begitulah hatiku terikat pada Pariaman + + Kawanku Indragiri Hulu + Apalah dayaku melawan waktu + Kalau tiba saatnya nanti kutinggalkanmu + Bujuklah aku, agar tak menangisimu + + Setelah beberapa waktu tinggal di Indragiri Hulu, Zorro +yang telanjur jatuh hati pada kota nan elok itu harus pindah +lagi ke Bagansiapiapi. + + “Kata orang bandar pelabuhan sedang ramai, saatnya +mencari kerja di sana,” ujar Lena. + + Bus ekonomi Sigula-Gula meluncur pelan meninggalkan +kota. Zorro membaca lagi puisi itu. Tak sanggup dia mena- +han air mata, meski Indragiri Hulu berkali-kali membujuknya +agar tak menangis. + + Anakku, hapuslah air matamu + Suatu hari nanti + Waktu akan membawamu kembali + Indragiri Hulu akan memelukmu lagi + 272 ~ Andrea Hirata + +Zorro lega karena akhirnya menyelesaikan kelas empat SD +di Bagansiapiapi. Nilai-nilai rapornya ciamik. Baginya itu +istimewa mengingat hidupnya yang kacau balau. Dia selalu +belajar meski keadaan tak mendukung. Dia membaca buku +di terminal, di stasiun, dalam bus, kereta, dan kapal feri. Dia +belajar saat menunggu ibunya pulang dari bekerja menjaga +toko. Dia membuat PR sambil menunggui dagangan kue ber- +sama ibunya. + + Ke mana pun dia pergi, di mana pun dia berada, Zorro +gampang menyesuaikan diri dan selalu disukai kawan-kawan +dan guru-gurunya. Karena semakin besar semakin nyata dia +mewarisi kecerdasan dan keelokan paras ibunya dan di sisi +lain dia mewarisi kelembutan dan kesabaran Sabari. Tak ter- +bayangkan malangnya nasib bocah itu jika kombinasi itu ter- +tukar. + + Guru-guru di Bagansiapiapi tak henti-henti membicara- +kan pandainya murid baru itu. Nilai Bahasa Indonesia Zorro, +hmmm, 9,5. Hampir sempurna. Mungkin karena manusia +tak mungkin mendapat nilai bahasa yang sempurna seperti +kata Bu Norma, gurunya menahan diri untuk tidak membe- +rinya angka 10. + + Suatu ketika guru Kesenian memintanya bernyanyi di +depan kelas. Zorro menawar, bolehkah nyanyian digantinya +dengan puisi? Guru tak berkeberatan. + Ayah ~ 273 + + Kalau kau dapat melihat ke dalam jiwaku + Kau akan melihat sungai mengalir + Anak-anak sungai itu berhilir di mataku + Dan bermuara di hatimu + + Terpana seisi kelas. + “Puisi siapakah itu?” tanya gurunya. + “Puisiku sendiri, Ibu Guru.” + “Benarkah?” + “Iya, Ibu Guru.” + “Apakah itu puisi cinta?” + Zorro tersenyum. + “Apakah kau sedang jatuh cinta?” + Kelas tertawa. + Hari-hari di Bagansiapiapi berlangsung dengan menye- +nangkan. Lena bekerja di pabrik pengepakan ikan asin dekat +pelabuhan. Namun, baru dua minggu di kelas lima, waktu itu +Zorro sedang membaca, ibunya duduk menghadapi meja, di +pojok rumah petak kontrakan mereka, melamun, sedih. Ta- +ngan ibunya mengetuk-ngetuk pinggir cangkir kopi. Sudah +berhari-hari ibunya melamun. Iba Zorro jadinya. + Zorro menutup buku, lalu membereskan semua buku, +alat-alat sekolah, pakaian, dan memasukkannya ke tas. Dia +menoleh kepada ibunya dan tersenyum. Ibunya pun terse- +nyum. Malam itu Zorro menulis puisi. + 274 ~ Andrea Hirata + + Wahai Bagansiapiapi + Kau tahu, dengan satu puisi, aku dapat menaklukkanmu + Namun, kerling senjamu malah membuatku cemburu + Bagan, dan cinta pada laut yang kau ajarkan kepadaku + Bagan, rindu akan debur ombak yang kau nyanyikan untukku + Siapiapi, di bawah pesonamu, aku minta diri + Siapiapi, tibalah saatnya aku pergi + Namun, kalau aku tak lagi di sini + Kuingin kau pun tahu, Siapiapi + Bahwa hatiku, telah kau curi + + Keesokannya Lena dan Zorro sudah ada di Tanjung Pi- +nang. + +Setiap kota yang pernah dia tinggali telah memberinya ke- +san tersendiri. Ingin Zorro menulis seribu puisi tentang Ba- +tanghari, Siak, Rengat, Bengkalis, Pariaman, Indragiri Hulu, +dan Bagansiapiapi. Puisi tentang penganan khasnya, sungai- +sungainya, gunung-gunungnya, senyum perempuan tua pen- +jaja sirih di pasar tradisionalnya, keriut bunyi roda pedatinya, +hikayat dari para pemangku adatnya, kelakar para pemang- +kas rambut di bawah pohon asam, acara-acara radio lokal- +nya, anak-anak perempuan dengan jilbab indahnya, lantunan +merdu azan muazinnya dan pilar-pilar masjidnya, kemudian +dia terdampar di Tanjung Pinang, satu kota paling bersemi + Ayah ~ 275 + +yang pernah ditemuinya, tempat, bahkan guru Matematika, +lihai berbalas pantun. + + Anak-anak liar puisi Zorro menemukan lapangan untuk +berlari-lari di sekolah di Tanjung Pinang. Berangkat sekolah +dia tersenyum, pulang sekolah, tertawa, mengerjakan PR, +bersiul-siul. + + “Kelas berapa kau sekarang, Boi?” tanya ibunya. + Zorro tersenyum karena dia tahu sebenarnya ibunya +tahu dia kelas berapa. + “Berapa sih, umurmu, Boi?” + Zorro tersenyum lagi, ibunya pun tahu persis berapa +umurnya. Namun, minggu itu saja sudah tiga kali ibunya ber- +tanya begitu. Zorro sendiri senang ditanya hal yang sama. + Sesungguhnya Lena tak mengharapkan jawaban. Dia +bertanya karena kagum akan Zorro yang dapat dengan te- +nang, tak pernah mengeluh, menghadapi situasi yang sulit. +Dia merasa bersalah. + “Maafkan Ibu, Zorro, keadaan kita tak menentu begi- +ni.” Mata Lena berkaca-kaca. + “Ih, tak apa-apa, Ibunda, tak apa-apa, janganlah berse- +dih.” + Ibunya berusaha menahan air mata. + “Jadi, apakah kita akan pindah lagi?” kata Zorro sambil +berpura-pura gesit membereskan buku-bukunya. Dia meng- +goda ibunya, untuk menghiburnya. Ibunya tertawa sambil +menangis. + 276 ~ Andrea Hirata + + Lena mendapat pekerjaan di travel agent. Menerima gaji +pertama dia langsung ke kota, ingin membeli hadiah untuk +Zorro karena nilai rapornya sangat bagus. + + Di tengah kota, dilihatnya kios penyewaan buku. Lena +senang membaca. Dia mampir untuk melihat-lihat kalau- +kalau ada novel yang ingin dibacanya. Waktu melihat-lihat +matanya terpaku melihat sebuah novel. Dia teringat dulu Zu- +raida pernah menyinggung soal novel itu. + + Pemilik kios tak menjual novel itu, tetapi menyerah pas- +rah waktu melihat Lena mengipas-ngipaskan duit disertai se- +nyum berlesung pipit dalam macam sumur di kantor polisi +lama itu. Belum menghitung mata indahnya macam purna- +ma kedua belas. Pemilik kios sewa buku yang berkacamata +tebal itu terkapar. + + Lena juga membeli kamus tebal bahasa Inggris-Indone- +sia. Dibungkus dengan kertas kado yang menawan bersama +novel itu, Zorro bersukacita menerimanya. Langsung dibu- +kanya kertas kado dan terbelalak melihat sebuah novel dalam +bahasa Inggris dan kamus yang tebal. Belum-belum dia sudah +terpana membaca judul novel itu: Love in the Time of Cholera. + + “Oh, terima kasih, Ibunda.” + “Sama-sama, Boi.” + Sepanjang sore tak ada hal lain yang dikerjakan Zorro +selain mencari setiap kata dalam novel itu di dalam kamus +Inggris-Indonesia. Waktu membalik-balik lembar novel kar- +ya agung Marquez itu dia terkejut melihat tulisan Florentino + Ayah ~ 277 + +Ariza. Dia tercenung, nama itu tak asing baginya. Di manakah +pernah kudengar nama itu? Ah, tak mungkin aku pernah mendengarnya. + + Akhirnya, dengan pengucapan bahasa Inggris seadanya, +terbata-bata Zorro berkisah kepada ibunya. + + “It was inevitable: the scent of bitter almonds always reminded him +of the fate of unrequited love.” + + Lena menahan tawa. + “Tak terhindarkan, bau buah-buah almond yang pahit se- +lalu mengingatkannya pada cinta yang tak terbalas.” + Lena tertawa. + “Begitukah kira-kira, Ibunda?” + “Cerdas sekali, Boi!” + Lena meminta Zorro terus membaca novel itu meski +Zorro mengucapkan kata-kata Inggris dengan pengucapan +huruf-huruf seperti dalam bahasa Indonesia. Zorro pun se- +nang melakukannya. + Sejak membeli novel di kios itu, Lena terbayang terus +akan Zuraidia. Sudah lama dia tak menulis surat kepadanya, +pun untuk sahabat-sahabat penanya. Prahara rumah tangga, +hidup terbirit-birit ke sana kemari, dan sifatnya yang tak suka +mengeluh membuatnya merasa belum menemukan saat yang +tepat untuk menulis surat. Saat itu akhirnya tiba. Diambilnya +pulpen dan kertas. + +Ke hadapan kawanku, Zuraida. +Tentu kau terkejut menerima surat dariku. + 278 ~ Andrea Hirata + + Tulisan Lena terhenti karena dia teringat akan sesuatu, +dipandanginya Zorro. Dulu di Medan sering dia menulis su- +rat diiringi denting gitar Jon, kini diiringi anaknya membaca +novel dalam bahasa Inggris, terbata-bata. + + Kalau kau berjumpa dengan anakku, kau akan terkejut, Zurai. +Zorro sudah besar, sudah kelas empat dan sangat pintar. + + Zorro membaca dengan penuh semangat, dia berdiri +dan mengucapkan kata-kata Inggris satu demi satu seper- +ti orang membaca puisi, meski tak satu pun dimengertinya +kata-kata itu. + + Zorro memberiku alasan untuk terus berjuang. Dia dapat membuat +beban berat jadi ringan, marah jadi senang, tangis jadi senyuman. Ah, +beruntungnya aku punya Zorro. + + Tanjung Pinang adalah kota tua yang indah. Tak tahu aku apa +yang akan terjadi selanjutnya, tetapi aku selalu merasa perjalanan ini +belum selesai. Rasanya aku masih akan pindah lagi .... + + Lena termenung. Dicobanya menulis lagi, tetapi pikiran- +nya buntu. Minggu lalu seorang lelaki membeli tiket kapal di +kantor travel agent tempat dia bekerja. Lelaki itu bilang bahwa +akan ke kantornya lagi untuk membeli tiket lagi esok. Lena +berdebar-debar. + Ayah ~ 279 + +Nun jauh di Medan, tanpa diketahui Lena, Jon pun terpukul +hebat akibat perpisahannya dengan Lena dan Zorro. Rasa se- +salnya jauh lebih besar daripada perceraiannya dengan istri- +istri sebelumnya. Kesedihan karena perpisahan dengan istri- +istrinya dulu adalah hujan rintik-rintik. Dengan Lena, puting +beliung. Perpisahan dengan istri-istrinya dulu, futsal. Dengan +Lena, sepak bola. Dengan istri-istrinya dulu, FTV. Dengan +Lena, film kolosal layar lebar. + + Persis seperti dialami Sabari, dalam waktu singkat hidup +Jon merosot. Dia tak hanya mengundurkan diri dari band Se- +tia Nada, tetapi juga membubarkan band itu. Dia marah kepa- +da diri sendiri karena perbuatan isengnya main mata dengan +perempuan lain, sesuatu yang disesalinya hingga membentur- +kan kepala ke tiang. Boros Akinmusire dan kawan-kawan ke- +hilangan band, Jon kehilangan cinta, dunia musik kehilangan +seorang gitaris berbakat. + + Jon menjadi mudah tersinggung karena frustrasi berke- +lanjutan. Akibatnya, dia ditinggalkan kawan-kawan dan sau- +dara-saudaranya. Dia tinggal sendiri di dalam rumah yang +pintu dan jendelanya selalu tertutup. Kata orang, JonPijareli +stres. + Delapan Tahun +Kegilaan + +KATA orang pula, Sabari linglung. + Tahun pertama setelah ditinggal Lena dan Zorro, dia + +masih tinggal di rumah. Tak punya lagi warung dan kambing, +dia menghidupi diri dengan bekerja menggembala ternak te- +tangga. Ukun dan Tamat suka mengantarinya beras. + + Kalau malam dia menonton televisi umum, di peka- +rangan balai desa. Dia duduk sendiri di pojok sana, di bagian +yang agak gelap. Orang-orang lain tertawa menonton acara +“Srimulat” di TVRI, Sabari tersenyum sedikit. Orang-orang +bersedih menonton acara drama dari TVRI Palembang, Sa- +bari juga bersedih. Orang-orang kecewa menonton bola bun- +dar berwarna-warni disertai bunyi berdenging karena siaran +mengalami gangguan teknis, Sabari juga kecewa. Orang- +orang ngomel-ngomel melihat layar televisi berbintik-bintik +disertai bunyi seperti hujan lebat, Sabari juga ngomel-ngo- +mel. + Ayah ~ 281 + + Selebihnya, Sabari hanya melamun sendiri di beranda, +lama memandang ke satu arah. Kalau ada layangan putus +yang mendarat di pekarangan rumahnya, dipungutnya. Di- +kumpulkannya tali layangan-layangan putus itu, disambung- +sambungnya sampai panjang, ditulisnya di secarik kertas: +Zorro, pulanglah, Ayah menunggumu. Disematkannya kertas itu di +teraju layangan. Layangan dinaikkan tinggi-tinggi dengan tali +yang panjang itu, lalu setelah tali habis diulur, dengan sengaja +layangan itu diputuskannya. Dibayangkannya layangan putus +itu akan hinggap di Sumatra, lalu ditemukan Zorro. + + Pernah pula seorang nelayan mendapat seekor penyu +yang besar. Sabari memintanya. Dia tahu penyu dapat ber- +umur lebih tua daripada manusia dan suka menjelajah lintas +samudra. Dengan ujung paku yang tajam, ditulisnya pesan +dalam bahasa Inggris semampunya di sekeping aluminium +seukuran telapak tangan. Dilubanginya lempeng aluminium +itu, lalu diikatkannya ke kaki penyu dengan akar bahar yang +tahan air laut. Penyu itu dilepaskannya kembali ke laut. Da- +lam pikirannya yang sudah tak beres, seseorang tak tahu di +negeri mana akan menemukan penyu itu, menerima pesan- +nya, lalu menyampaikannya kepada Lena dan Zorro. + + Tahun kedua, Sabari masih tinggal di rumah. Dia meng- +gembala kambing dan sapi, lalu pulang. Setiap malam Jumat +dia menonton televisi di balai desa, tetap duduk sendiri di ba- +gian yang agak gelap, nun di pojok sana. Orang-orang terta- +wa menonton “Srimulat”, Sabari tidak. Orang-orang berse- + 282 ~ Andrea Hirata + +dih menonton drama dari TVRI Palembang, Sabari tidak. +Orang-orang kecewa menonton bola bundar berwarna-warni +disertai bunyi berdenging, Sabari tidak. Orang-orang ngo- +mel-ngomel melihat layar televisi berbintik-bintik dan berbu- +nyi seperti hujan lebat, Sabari tidak. + + Tahun ketiga, orang-orang tertawa menonton “Srimu- +lat”, Sabari menangis. Orang-orang bersedih menonton dra- +ma dari TVRI Palembang, Sabari tertawa. Orang-orang ke- +cewa menonton bola bundar berwarna-warni disertai bunyi +berdenging, Sabari tersenyum. Orang-orang ngomel-ngomel +melihat layar televisi berbintik-bintik dan berbunyi seperti hu- +jan lebat, Sabari tertawa. + + Tahun keempat, Sabari tak bisa tidur memikirkan bagai- +mana orang bisa berada di dalam televisi. + + Tahun kelima, Sabari melihat-lihat bagian belakang TV +Sanyo hitam putih empat belas inci itu, jangan-jangan ada +para pemain “Srimulat” kecil-kecil di dalam televisi itu. + + Tahun keenam, Sabari tak lagi menonton televisi di ba- +lai desa karena takut pada manusia-manusia kecil di dalam +televisi. + + Tahun ketujuh, terjadi keributan besar di pasar karena +pasar diserbu kambing, sapi, dan kerbau, ratusan jumlahnya. +Hewan yang biasanya berada di padang yang luas dan sepi +menjadi panik melihat orang banyak, kendaraan lalu-lalang, +dan mendengar hiruk pikuk pasar. Mereka semburat tak ke- +ruan, berteriak-teriak, menerjang para pedagang kaki lima, + Ayah ~ 283 + +menyeruduk gerobak, menguasai jalan. Pasar kacau balau. +Sabari berdiri di tengah kekacauan itu. Berdiri mematung +tanpa dosa, bingung. Usut punya usut, menurut keterangan +para saksi, gembala ternak yang bernama Sabari bin Insya- +fi itu, di pertigaan di ujung kampung, harusnya menggiring +ternaknya ke kiri, tetapi mungkin dia melamun, ternak malah +digiringnya ke kanan, langsung menuju pasar. + + Sabari berurusan dengan polisi. Namun, demi melihat +gembala yang duduk dengan lesu, pasrah, dan hanya melihat +kosong ke satu arah, Ajun Inspektur Agung Novrianto sege- +ra tahu bahwa tak banyak yang bisa dilakukan dengan lelaki +yang telah bertahun-tahun dilanda penderitaan yang tak ter- +perikan. Sabari dilepas kembali dalam waktu kurang dari satu +kali 24 jam. + + Tahun kedelapan, tak ada lagi yang melihat Sabari di +rumahnya. Atap rumbia yang jatuh akibat sapuan angin sela­ +tan dan tetap tergeletak di beranda, menandakan tak ada lagi +umat manusia di rumah itu. Rupanya Sabari sudah meming- +gatkan diri sendiri dari rumah. Dia hidup menggelandang di +platform pasar ikan bersama Abu Meong dan puluhan kucing +pasar dan anjing kurap di sana. Pasar selalu menjadi tempat +orang membuang anak-anak kucing dan anjing yang tak di- +inginkan. Sabari pun merasa terbuang, tak diinginkan oleh +cinta. Dia pun merasa nasibnya tak ubahnya nasib Florentino +Ariza. + + Sabari makan dari belas kasihan para pemilik warung +nasi di seputar pasar. Kalau tak sedang ingin melamun, sese- + 284 ~ Andrea Hirata + +kali dia membantu mencuci piring. Pegawai warung membe- +rinya kopi. + + “Terima’ kase, Kak,” langsung diminumnya. + “Aduh, enaknya teh ini.” + Dikasih teh, dia berkata, “Terima’ kase, Kak, tak pernah +aku merasa air putih seenak ini.” + Dikasih air putih dia bertanya, “Kakak, mengapa teh ini +tak ada rasanya?” + Dari sore sampai malam, Sabari adalah satu-satunya +manusia di platform pasar ikan. Dia berjalan melalui relung- +relung gang pasar yang sepi sambil menggendong Abu Me- +ong dan memanggil-manggil Marleni. Kerap pula memanggil +Marlena dan Zorro. Langkahnya diikuti belasan kucing pasar. +Jika ada penertiban gelandangan dan orang gila, kerap Sa- +bari dinaikkan ke bak mobil pikap polisi pamong praja, tetapi +tak lama kemudian dia akan kembali lagi ke pasar ikan. + Suatu ketika Zuraida melihat Sabari berkelebat di pasar +ikan, langsung jalannya dipotong Zurai. + “Boi! Apa-apaan kau ini?! Kalau mau sinting bilang- +bilang! Jangan raib begitu saja!” + Sabari menunduk dalam. + “Lihatlah kau kurus sekali!” + Sabari mengangkat wajahnya. + “Biarkan aku kurus, Rai, biar aku bisa bersembunyi di +balik ilalang.” + “Puisi gila itu lagi! Majenun! Puisi sudah tak musim!” + Ayah ~ 285 + + Zuraida melihat map terapit di ketiak Sabari. + “Map apa itu?” + Sabari tak menjawab. + “Apa, Boi?” + Zuraida merampas map itu dan membukanya. Terkejut +dia melihat berlembar-lembar daftar menu restoran. + “Untuk apa ini?!” + Sabari diam saja sambil menjulurkan tangan agar Zurai- +da mengembalikan map itu. + “Pulanglah, mandi sana, cukur rambut, nonton layar +tancap, lihat pasar malam, goda-goda perempuan di Pantai +Tanjong Pendam, macam orang laki lainnya, kembalikan hi- +dupmu! Jangan sinting begini.” + Sabari tak acuh. + “Ada lagi lomba maraton piala kemerdekaan. Ikut saja, +Ri, seperti dulu. Kau pelari hebat. Berlarilah, kau pasti jadi +juara lagi.” + Sabari memalingkan wajahnya. + “Jangankan berlari, Rai, berjalan pun aku tak sanggup.” + Sabari berlalu, Zuraida mengerti maksudnya. Sedih dia +melihat Sabari berjalan dengan langkah berat, seakan-akan +kakinya ditambati batu. + Nun di tepi jalan sana, juru antar surat dari pengadilan +agama bersusah payah mengengkol motornya. + Genap + +TENTU saja Ukun dan Tamat tahu keadaan Sabari. Mereka +mencari-carinya, tetapi dia sudah hilang. Sabari sendiri tahu +dia dicari kawan-kawannya. Dia merasa malu, dia tak mau +bertemu dengan siapa pun. + + “Banyak orang suka angka delapan. Karena kalau un- +tung, tak berkesudahan, tapi begitu juga kalau senewen, se- +newennya takkan selesai-selesai. Sudah saatnya kita berbuat +sesuatu yang spektakuler untuk Sabari,” kata Tamat kepada +Ukun. + + “Ojeh, Boi.” + Maka, mereka mengadakan rapat mendadak di warung +kopi Solider. Tiga jam mereka saling bertukar pikiran. Tandas +masing-masing lima gelas kopi, dan tumpas masing-masing +mi rebus 34 (tiga mi empat telur). Setelah mempertimbang- +kan berbagai aspek, mereka memutuskan untuk mencari +Lena dan Zorro ke Sumatra dan membawa keduanya pulang + Ayah ~ 287 + +ke Belitong. Masalahnya, tak ada yang tahu di mana Lena +berada. Namun, Tamat sudah punya akal. Sore itu pula me- +reka mendatangi Zuraida. + + “Apa kabarmu, Zurai?” Ukun bertanya. + “Tambah manis saja,” goda Tamat. + Zuraida jengkel. + Sejak SMA, dulu mereka sering bertengkar hingga men- +jelang tua sekarang mereka tak pernah cocok. + “Jangan sampai kuganti kopi kalian dengan air aki, kata- +kan cepat apa mau kalian?!” + “Mengapa, Boi, kau tak punya waktu?” Ukun bertanya. + “Aku pengangguran, punya banyak waktu untuk apa +pun. Tapi, tak punya waktu untuk raskal macam kalian!” + “Aih, makin marah, makin manis,” Tamat tak tahu adat. + “Kuhitung sampai tiga,” ancam Zurai. + “Tunggu, tunggu, janganlah menghitung dulu, macam +granat mau meletus saja.” + “Katakan!” + “Ojeh.” Tamat menegakkan tubuhnya. + “Di mana Lena dan Zorro?” + Terperanjat bukan main Zurai. Dia langsung mau meng- +elak, tetapi Tamat menyalak, menyaru suara Zurai sendiri. + “Jangan kau katakan, mengapa kalian bertanya kepada- +ku soal Lena? Jangan kau bilang, apa hubungannya dengan- +ku? Aku tak tahu-menahu soal Lena, memang aku ini ibunya? +Jangan, Boi, sama sekali jangan, itu adalah jawaban yang tak +bermutu!” + 288 ~ Andrea Hirata + + Zurai terpana karena dia memang mau mengatakan se- +mua itu. Tamat menembak lagi. + + “Begini-begini, aku ini pernah jadi relawan penyuluh +KB, Boi, jadi aku tahu cara menjawab, dan tahu cara berta- +nya.” Apa hubungan semua itu? + + Bagaimana Tamat bisa menduga dia tahu soal Lena? +Dia dan Lena telah membuat janji besi untuk merahasiakan +keberadaan Lena. Yang tahu hanya Zurai, Lena sendiri, Tu- +han Yang Maha Esa, dan seseorang berkopiah, tetapi dia ber- +ada di dalam prangko surat-surat Lena. + + Dengan seringai menyebalkan, Tamat menyalak lagi. + “Tentu kau mau bertanya dari mana aku tahu bahwa +kau tahu soal Lena, bukan?” + “Iya, Boi.” Zurai tak berkutik karena semua hal yang +ada dalam kepalanya terbaca oleh Tamat. + “Baiklah, kujelaskan kepadamu.” Tamat menghirup +kopi, lalu berkisah. + “Begini, aku punya pak cik, dia nelayan di Selat Nasik, +tukang cari ketam tuli tepatnya. Dia punya istri orang Gual, +namanya Dinot. Akibat hubungan dengan pak cik-ku itu, ten- +tu istrinya itu bisa kupanggil Mak Cik Dinot. Mak Cik Di- +not itu adik bungsu dari Ngamot. Mereka hanya dua sauda- +ra. Karena Mak Cik Dinot kawin dengan pak cik-ku, maka +bolehlah kupanggil Ngamot dengan panggilan Mak Long +Ngamot. Sebab Ngamot adalah anak tertua. Tentu karena +Dinot dan Ngamot hanya dua saudara, bukan? Maka, yang + Ayah ~ 289 + +ada hanya si sulung dan si bungsu. Mak Long Ngamot punya +suami orang Batu Belida, tukang bikin taoco, namanya Ma­ +hanip. Maka, boleh juga dia kupanggil Pak Long Mahanip. +Di Kampong Burong Kedidi aku juga punya pak nga, karena +dia anak tengah, namanya Pak Nga Syaram. Pak Cik dan Pak +Nga itu adalah adik-adik ibuku. Pak Nga Syaram orangnya +memang seram. Pekerjaannya bikin rusip. Dia kawin dengan +orang Kampung Lutung Tenteram bernama Hanum. Maka, +bolehlah istrinya kupanggil Mak Nga Hanum. Mereka punya +delapan anak, Zainap, Sinap, Mainap, Tatap, Rangkap, Inap, +Mantap, dan Genap. Nah, si Genap itu punya anak yang ber- +nama Harap. Harap sekolah di SMK jurusan Tata Boga alias +masak-memasak. Setiap libur Lebaran, kantor pos menerima +siswa magang. Tugas mereka menyortir surat dan kartu Le- +baran. Tahun lalu, Harap bin Genap ikut magang di kantor +pos dan bercerita kepada ayahnya bahwa dia pernah melihat +surat untukmu. Katanya, di sampul surat itu ada tulisan, ke +hadapan Siti Zamia Zuraida binti Alim Makruf Kabarudin, +Kampung Belantik, Belitong, kode pos 33462. Nama si pengi- +rim: Marlena binti Markoni, di satu tempat di Kota Medan. +Tak ada nama seelok namamu di Belitong ini, Rai, dari hulu +Sungai Lenggang sampai ke Padang Buang Anak. Ayah Ha- +rap, yaitu si Genap itu, bercerita kepadaku soal surat itu. Mau +apa kau sekarang, Boi? Kena kau!” + Bahasa Indonesia + +ZURAIDA serbasalah. Dia harus memegang janji besinya +dengan Lena, tetapi dia cemas karena sejak menerima surat +dari Medan, Lena tak lagi memberi kabar. Ibu Lena sendi- +ri sudah tua, sakit-sakitan, dan semakin sering menanyakan +Lena. Maka, jika ada yang mau mencari Lena, dia setuju. +Akhirnya, diserahkannya surat-surat Lena kepada Ukun dan +Tamat. Melalui surat-surat itulah mereka akan menyelusuri +jejak Lena. + + “Kupastikan surat-surat ini memang dari Lena. Caranya +menulis Masjid Baiturachman di beberapa surat ini tetap, tak +berubah. Artinya surat-surat ini memang ditulis orang yang +sama dan orang itu adalah Marlena bin Markoni, tak lain tak +bukan.” + + Memangnya siapa lagi? Nyata-nyata surat-surat itu dikirim Mar- +lena untuk Zuraida! Namun, Ukun hanya berani mengatakan + Ayah ~ 291 + +itu dalam hati. Sebab, dia takut dipermalukan Tamat soal +rengking-nya dulu di depan Zurai. + + “Dari surat-surat ini aku tahu sepak terjang Lena. Dia +tinggal di Pangkal Pinang sampai cintanya dengan pemilik +deal­ er motor Vespa itu khatam, lalu dia telah menjelajah ham- +pir seluruh Sumatra!” + + Tamat tak dapat menyembunyikan rasa kagumnya. + “Kurasa Lena pernah pula ke Singapura, atau boleh jadi +Penang. Sangat mungkin Lena menemukan suami orang In- +dia dan sekarang bermukim di Mumbai. Ingat, setelah Kuala +Lumpur, naik ke Thailand, belok ke kanan Hongkong, belok +ke kiri India, lurus terus ke Jeddah, jazirah Arab, semuanya +bisa lewat jalan darat!” + Mengernyit dahi Zuraida sebab tak ada sedikit pun ka- +bar dari Lena mengindikasikan hal itu. + +Kata Tamat, untuk bepergian jauh mereka harus mengurus +dokumen-dokumen perjalanan. Lantaran rengking Tamat di +SMA adalah 43 dari 47 siswa, dan rengking Ukun di bawahnya, +Ukun melihat Tamat sebagai junjungan. + + Mereka menghadap Pak RT untuk mendapat surat ke- +terangan tingkah laku, surat itu disahkan dengan senang oleh +kepala desa. Tamat dan Ukun memang suka nongkrong sam- +pai malam di warung kopi Solider, suka nonton organ tung- + 292 ~ Andrea Hirata + +gal, sesekali menyerobot naik panggung, berduet menyanyi- +kan lagu “Terajana”, kerap pula menggoda-goda biduanita, +tetapi tak ada pasal-pasal yang mereka langgar. Mereka ada- +lah warga republik yang produktif. + + Dengan senang hati pula Pak Camat memberi catatan +yang baik tentang mereka. Surat keterangan dari Pak RT, Ke- +pala Desa, dan Pak Camat diperlukan sebagai lampiran untuk +membuat SKKB (surat keterangan kelakuan baik) dari pihak +yang berwenang mengawasi kelakuan warga. Ajun Inspektur +Agung Novrianto meneken SKKB mereka tanpa ragu. + + Usai membuat SKKB, Tamat terpikir untuk sekalian +membuat KK (kartu keluarga). Sehingga, jika terjadi apa-apa +di jalan nanti, identitas mereka jelas bahwa mereka anak dari +ayah dan ibu siapa, adik dan abang dari siapa saja. Lalu, dia +terpikir lagi untuk membuat surat wasiat. Sebuah usul yang +sempat dipertanyakan Ukun. + + “Nasib manusia siapa tahu! Kalau ada apa-apa di jalan, +kau dan aku tewas, atau hilang, tenggelam, menjadi korban +kejahatan, diculik, mati kelaparan. Bagaimana nasib harta- +benda kita?! Boleh jadi peninggalan kita menimbulkan keri- +butan yang berlarut-larut dalam keluarga karena mereka be- +rebut! Risiko besar keluarga pecah kongsi bisa terjadi hanya +lantaran kau malas membuat selembar surat wasiat!” + + Untuk kali kesekian, Ukun mati kutu disekak Tamat. Dia +tak berkutik sebab rengking Tamat memang lebih tinggi dari- +pada rengking-nya. + Ayah ~ 293 + + Akan tetapi, terjadi sedikit masalah soal surat wasiat itu. +Yaitu, ketika Kades menanyakan harta benda apa saja yang +mereka miliki dan kepada siapa saja akan diwariskan, ternya- +ta benda paling berharga punya Tamat hanya sebuah sepeda +Simking butut made in China, yang mungkin diproduksi zaman +Dinasti Tang. + + Sepeda itu pernah menabrak truk timah yang tengah +parkir sehingga garpu depannya melesot. Jika dinaiki sepeda +itu selalu mengajak pengendaranya belok ke kiri. Mirip ke- +cenderungan kiri pemiliknya. + + Adapun setelah ditelaah secara mendalam, harta paling +berharga Ukun hanya jam tangan Rado. Merek yang pres- +tisius memang, satu jam tangan yang sering dikenakan para +petinggi eselon 3 paling tidak, tetapi arloji Rado punya Ukun +agak aneh, jika diamati lebih dekat, tulisan Rado di dalam +jam itu mirip tulisan Ridho. + + Alhasil, proses pembuatan surat wasiat itu ditunda. + Rencana perjalanan mereka semakin matang. Di wa- +rung kopi Solider, Tamat berkata, “Delemot menjadi saksi, +kau kutunjuk sebagai juru bicara dalam perjalanan kita nanti. +Aku sendiri adalah pemimpin ekspedisi.” + Tamat menunjuk Ukun dan menunjuk dirinya sendiri. +Delemot, pegawai warung kopi, mengangguk. + “Ojeh, Mat.” + “Masalahnya, bagaimana mau jadi juru bicara, bahasa +Indonesia pun kau tak becus!” + 294 ~ Andrea Hirata + + Ukun tersinggung. + “Ah, kau pun tak lancar bahasa Indonesia.” + Tamat tak terima. + “Tak ada hormat, mari kita coba!” + “Apa bahasa Indonesia-nya gelaning?” Ukun menjajal Ta- +mat. Gelaning satu kata kuno dalam bahasa Belitong. + “Aih, gampang, artinya ‘bersih, rapi’.” + Delemot bertepuk tangan, Ukun tersenyum pahit. + “Ayo, apa lagi.” + “Hademat.” Kata Belitong yang lebih kuno lagi. Bahkan, +orang Belitong sendiri belum tentu tahu. + “Oh, gampaaaaaang .... Artinya ‘bunyi yang sangat be- +sar, menggelegar, misalnya gunung meletus’.” Jawaban itu +benar. + Delemot bertepuk tangan lagi. + “Giliranku!” bentak Tamat. + Ukun gugup. + “Apa bahasa Indonesia-nya ngayau?” + “Jalan-jalan!” jawab Ukun tangkas. + Delemot bertepuk tangan untuk Ukun. + Tamat jengkel. “Apa bahasa Indonesia-nya ketumbi?” + Ketumbi adalah satu kata yang cantik, sayangnya sudah +jarang dipakai orang Belitong. Artinya ‘tertinggal paling bela- +kang’, dalam perjalanan atau perlombaan. + Ukun tergagap-gagap. Dia tak mampu mengungkap arti +kata ketumbi dalam bahasa Indonesia. Keringat bertimbulan di + Ayah ~ 295 + +dahinya. Dia menoleh kepada Delemot, Delemot mengang- +kat bahu gemuknya. Tamat mencibirnya. + + Ukun jengkel. Dia berpikir keras, tetapi tiba-tiba terse- +nyum lebar karena dia tahu jawabannya. Kalau ngayau bahasa +Indonesia-nya jalan-jalan, boleh jadi ketumbi bahasa Indonesia- +nya .... “Tumbi-tumbi!” jawabnya lantang. + +Komunikasi dianggap penting oleh Tamat sebab nanti mere- +ka akan bertemu dengan orang-orang dari berbagai daerah. +Oleh karena itu, kemampuan berbahasa Indonesia Ukun ha- +rus ditingkatkan. Mereka menghadap Bu Norma, guru Baha- +sa Indonesia sekaligus wali kelas mereka di SMA dulu, yang +galak tetapi disayangi. + + “Jadi, kalian mau mencari Lena dan Zorro, agar Sabari +tidak jadi orang sinting? Itu baru namanya kawan, sungguh +mulia!” + + Bu Norma senang bukan kepalang karena Ukun mau +belajar bahasa Indonesia. Bersemangat dia. + + “Terdapat puluhan ribu bahasa daerah. Puluhan ribu, +dapatkah kau bayangkan itu! Barangkali bahasa terbanyak +di dunia ini ada di Indonesia. Konon, di beberapa daerah di +Sumatra, di kampung yang bersebelahan saja, orang bisa tak +mengerti bahasa masing-masing. Lihat betapa kayanya baha- +sa di negeri kita ini. Jelajahi Sumatra, Boi, simak orang berbi- +cara, kau akan bergelimang kesenangan kata-kata.” + 296 ~ Andrea Hirata + + “Jadi, apa yang harus kami lakukan, Bu?” + “Cukup dengan berbahasa Indonesia secara baik dan +baku, kau akan terbebas dari sikap tidak sopan, akan lancar +berbicara dengan orang dari daerah mana pun!” + “Maksud Ibu?” + “Misalnya, kau mau duduk di depan orang-orang lain, +dalam bahasa Belitong, ringkas saja, kuang ke aku dudok de sinek? +Dalam bahasa Indonesia, dapatlah kau katakan, ‘Bapak atau +Ibu, berkenankah seandainya saya duduk di sini?’ Hmmm, +elok, bukan?” + “Elok nian, Bu.” + “Jangan sungkan berpantun, berpepatah. Pantun adalah +madu bahasa, pepatah adalah harta bahasa. Pakailah kata- +kata seperti wahai, kiranya, seandainya, bilamana, manakala, sudi- +kah, berkenankah, sediakala, gerangan, semua itu perbendaharaan +bahasa Indonesia yang megah dan bermutu tinggi. Kata-kata +itu mencerminkan kualitas watak orang yang mengucapkan- +nya!” + Bu Norma masuk ke kamar lalu kembali membawa +buku yang sangat tebal. Begitu tebal sehingga kalau menimpa +anak kecil, mungkin anak itu bisa pingsan. + “Pakailah ini, kalian akan selamat,” kata Bu Norma +sambil menyerahkan buku itu kepada Ukun. + Ukun membaca judulnya. Kamus Umum Bahasa Indonesia. +Milik Departemen Pendidikan dan Kebudayaan. Tidak diperdagangkan. +Berdasarkan Instruksi Presiden No.7 Tahun 1983. + Ayah ~ 297 + + “Terima kasih, Ibunda Guru.” Ukun mencium tangan +Bu Norma dengan takzim. + + “Sama-sama, Raskal 2.” + Sejak itu, kamus tebal itu selalu berada di dalam tas +kecampang Ukun, dibawanya ke mana pun dia pergi. Di sela +pekerjaannya menggulung dinamo, dibukanya kamus dan di- +temukannya kata-kata baru bagaikan jendela yang terbuka, +lalu di dalam jendela itu ada jendela lagi. Rajin dia membuat +catatan sembari berbicara sendiri mempraktikkan apa yang +telah dipelajarinya, lalu dia tersenyum. Ukun tenggelam da- +lam labirin bahasa dan berusaha menemukan jalan keluar de- +ngan mengikuti jejak kata-kata. Sekonyong-konyong dia jatuh +hati pada bahasa Indonesia. + Pada sore nan syahdu itu, Ukun duduk berhadap-hadap- +an dengan Tamat di warung kopi Solider. Setelah beberapa +waktu berbincang, melihat kopi di dalam gelasnya hampir +habis, Ukun memberi kode agar pegawai warung mendekat. +Ditatapnya pegawai itu dengan penuh hormat. + “Wahai Kakanda Delemot yang berbudi mulia, sudikah +kiranya Kakanda Delemot mengisi gelas kopi saya ini dengan +air kopi manakala kopi di dalamnya sudah tiada lagi?” + Tertegunlah Tamat. Dipandanginya Ukun, dadanya di- +landa keharuan yang mendalam sebab dia tahu, Ukun telah +belajar bahasa Indoensia dengan sepenuh hati dan sekarang +siap menempuh perjalanan yang tak terperikan untuk men- +jelajah Sumatra. + Kapal Ternak + +SORE itu, sehari sebelum berangkat, Ukun, Tamat, dan +Zuraida mencari Sabari di platform pasar ikan. Mereka me- +nyusuri lorong pasar yang sempit dan berliku-liku. Sepi, ku- +cing-kucing pasar mengeong panjang dan anjing-anjing pa- +sar menyalak. Mereka ngeri membayangkan setiap malam +Sabari tidur di sana. + + “Sabari, Sabari!” Berkali-kali mereka memanggil, Sa- +bari tak muncul-muncul. + + Sebenarnya, sejak mereka masuk gerbang pasar ikan +tadi Sabari telah melihat mereka dari kejauhan. Cepat-cepat +dia bersembunyi di balik peti es. + + “Boi, kemarilah. Aku dan Tamat mau pamit.” + Pamit? Mau ke mana? Sabari keluar dari persembunyian +dan berjalan ke arah Ukun, Tamat, dan Zuraida. + Alangkah terkejut mereka melihat Sabari. Sepintas me- +reka tak lagi mengenalinya. Badannya kurus melengkung + Ayah ~ 299 + +karena kurang makan. Rambutnya panjang awut-awutan +macam rambut Lenny Kravitz sebelum di-rebonding tempo +hari. Jenggotnya panjang macam jenggot pertapa Kapuchin. +Kumisnya simpang siur. Mukanya kumal jarang dibasuh. Se- +pasang mata yang liar melirik-lirik dengan cepat. Tipikal pan- +dangan mata orang sakit ingatan. + + “Astaga, apa yang terjadi kepadamu, Boi?” tanya Tamat. + “Lihatlah, rupamu macam iblis.” Zuraida terperangah. + Sabari tersenyum pahit, lalu menunduk. + Tamat mengatakan bahwa esok sore mereka akan ke +Sumatra untuk mencari Lena dan Zorro. Jika berjumpa, me- +reka akan membujuknya agar pulang ke Belitong. Sabari tak +berkata-kata. + “Karena itu, Boi,” kata Ukun, “tolong jangan gila dulu. +Biarlah kami mencari Lena dan Zorro dulu. Kalau kami ga- +gal, silakan nanti kalau kau mau menjadi gila, tak ada ke- +beratan dariku dan Tamat sebagai kawan-kawanmu. Untuk +sementara ini, tahan dulu.” + Sabari diam saja. Diam macam kuburan. + +Keesokannya, Jumat sore, berbondong-bondong orang ke +dermaga untuk mengantar Tamat dan Ukun. Banyak seka- +li, mereka datang karena bersimpati pada dua sahabat yang +ingin mencari Lena dan Zorro, demi sahabat lainnya. + 300 ~ Andrea Hirata + + Bu Norma bangga melihat Ukun menyandang tas besar +dan menenteng plastik kresek berisi Kamus Umum Bahasa Indo- +nesia yang tebal. Dia terharu membayangkan mereka akan +menjelajah Sumatra, tempat asing yang sama sekali tak per- +nah mereka tempuh, tak tentu arah tujuan, demi memperte- +mukan seorang ayah dengan anaknya. + + Ukun dan Tamat akan menumpang kapal ternak Mona- +lisa, yang nakhodanya telah mereka kenal dengan baik. Kapal +itu akan berlayar dari Pelabuhan Tanjong Pandan ke Pela- +buhan Kayu Arang, Bangka. + + Bersama serombongan besar kambing, Ukun dan Ta- +mat naik ke kapal. Tak lama kemudian sirene kapal berku- +mandang. + + Sabari bersandar di balik peti es. Dia tahu apa yang ter- +jadi di dermaga yang tak jauh dari pasar ikan. Dia terharu +membayangkan Ukun dan Tamat telah naik ke kapal untuk +menjemput Lena dan Zorro. + Juliet-mu + +TABIAT-TABIAT buruk yang dulu tak pernah tampak dalam +diri JonPijareli, kini muncul. Karena dia telah naik jabatan +satu setrip, dari orang stres menjadi orang depresi. + + Dia tak cocok dengan siapa saja, gampang emosi. Se- +mua orang tak becus, yang pintar dia saja. Sanak saudaranya +dipelototinya, tetangga didiamkannya, tamu tak dibukainya +pintu, presiden dan menteri-menteri, satu kabinet, habis di- +kata-katainya. + + Layaknya orang depresi, yang tak bisa menalar dengan +sehat, Jon tak bisa berhenti memikirkan kemungkinan yang +terjadi jika dia tak berjumpa dengan wanita lain di toko obat +itu, yang akhirnya menyebabkan dia pecah kongsi dengan +Lena. Berkali-kali dia membayangkan jika sore itu dia tidak +sakit kepala dan meluncur ke toko obat untuk membeli aspi- +rin, lalu bertemu dengan wanita semlohai yang membuatnya +lupa daratan itu. + 302 ~ Andrea Hirata + + Sering dia berpikir motor BSA-nya rusak, bensinnya ha- +bis, bannya kempes sehingga dia tak pergi ke toko obat itu, +dan sekarang masih berleha-leha bersama Lena dan Zorro. +Oh, Zorro, betapa Jon rindu kepada anak tirinya yang tam- +pan, pintar, dan amat baik itu. + + Atau, boleh pula motor BSA yang sangat hebat itu dicuri +orang sekalian sehingga sore itu dia tak pergi ke toko obat, +atau perusahaan yang membuat aspirin gulung tikar sehingga +di dunia ini tidak ada lagi aspirin. Atau, sakit pening kepala +telah punah, macam sakit cacar. Manusia tidak lagi menga- +lami pening. Dengan begitu Jon tak pernah berjumpa dengan +wanita bohai itu. Namun, yang terjadi adalah dia ke toko obat +dan tahu-tahu sekarang tak punya bini. + + Berupa-rupa skenario tentang toko obat, aspirin, dan +motor BSA berputar-putar dalam kepala Jon, menyiksanya +pagi, siang, sore, dan malam. Tidak realistis tentu saja. Jon +mendekam dalam rumah kotor dengan lampu yang remang, +pintu dan jendela tak pernah dibuka. Tak tahu apa yang dila- +kukannya di dalam rumah. Tragis, seseorang yang amat po- +puler, flamboyan, selebritas lokal yang bangga akan kawan +yang banyak, menjadi seseorang yang hidup sendiri hanya +berkawan sepi. Jika mendengar suara anak-anak tetangga ri- +but sedikit saja, Jon berteriak: + + “Jangan ribuuuuuut!!! Pergi sana!” + “Hantuuuuuu ...,” jerit anak-anak itu semburat kabur +ketakutan. + Ayah ~ 303 + + Kalau ada tamu berkunjung, mengetuk pintu, Jon +muntab. + + “Tak terima tamu!!!” Karena, Jon malas berjumpa de- +ngan manusia. + +Setelah merapat di Pelabuhan Kayu Arang, Bangka, nakhoda +kapal ternak yang ditumpangi Tamat dan Ukun bertanya tu- +juan mereka berikutnya. + + “Aceh, Pak,” jawab Tamat. + Ukun terkejut. “Baiklah, Kawan, selamat jalan.” Mere- +ka bersalaman. “Setahuku tujuan kita adalah Medan, sesuai +surat terakhir Lena.” + “Ikut saja.” + “Ikut apanya?! Aceh tak ada dalam rencana kita! Tak +pernah ada surat Lena dari Aceh!” Ukun jengkel. + “Aku ketua perjalanan ini, aku tahu apa yang kulakukan. +Lena bisa saja ada di Tanjung Karang, Palembang, Bengkulu, +Medan. Lebih baik kita ke utara dulu baru turun ke selatan +karena turun lebih gampang daripada naik. Ingat, aku navi- +gator, kau juru bicara, tapi sekarang tutup mulutmu, tumbi- +tumbi!” + Maka, dari Pelabuhan Kayu Arang mereka naik kapal +kayu menuju Pelabuhan Tangga Buntung di Palembang, dari + 304 ~ Andrea Hirata + +sana mereka naik kapal kayu lagi, langsung ke Pelabuhan +Ulee Lheu, Aceh. + + Perjalanan itu begitu menakjubkan bagi mereka. Di ka- +pal, Ukun rajin mempraktikkan bahasa Indonesia dan senang +mendapat banyak kenalan baru. Tiga hari kemudian orang- +orang kampung itu sudah berdiri tertegun dengan napas ter- +tahan di haribaan Masjid Baiturachman. + + “Inilah tujuan kita ke Aceh, Boi,” kata Tamat sambil +memeluk pundak Ukun. + + “Alangkah megahnya, Boi, jauh lebih megah daripada +yang kulihat di almanak. Alangkah beruntungnya kita pernah +melihat langsung masjid yang hebat ini.” Mata Ukun basah. +Dia memang lebih sentimental daripada Tamat. + + “Aku seperti merasa berada dalam kisah seribu satu ma- +lam.” + + Tamat mengeluarkan sepucuk surat dari dalam tasnya +dan memperlihatkan surat Lena yang membicarakan keingin- +an Zuraida mendapat foto Lena di depan masjid itu. Mereka +difoto oleh tukang foto langsung jadi di sana. + + Seminggu kemudian Zuraida menerima sepucuk surat. +Tak percaya Zurai akan pandangan matanya sendiri melihat +Tamat dan Ukun bergaya di depan Masjid Baiturachman. +Tak keruan perasaannya membaca surat itu. + + Besarnya mungkin dua puluh kali lebih besar daripada Masjid Al- +Hikmah di kampung kita, Rai. Lantainya dingin, pilar-pilarnya gagah, + Ayah ~ 305 + +seakan dapat memanggul gunung. Kalau kau memandang langit-langit- +nya, rasanya angkasa terbelah dan kau berubah menjadi sebutir pasir. + + Begitulah kata Ukun. Tamat menyambung, + + Suasana shalat Jumat di masjid ini tak dapat dilukiskan dengan +kata-kata. Saat engkau shalat rasanya ribuan malaikat menungguimu. +Suara muazin merdu sekali. + + Begitu megah, begitu agung masjid ini sehingga kuakui semua do- +saku, yang terkecil sekalipun. + + Zuraida terharu. + Sabari juga mendapat kiriman surat dari Ukun dan Ta- +mat, disertai foto dan sebuah pengakuan bahwa surat-surat +dari Juliet-mu untuk Sabari di majalah dinding SMA dulu se- +benarnya bukan buatan Lena, melainkan buatan Ukun dan +Tamat sendiri, pakai mesin tik Olympic yang mereka pinjam +dari juru tulis kantor desa. Begitu pula lagu “Truly” yang di- +nyanyikan Sabari di radio seperti kucing kena cekik itu. Se- +sungguhnya lagu itu bukan lagu kesayangan Lena, semuanya +rekayasa Ukun dan Tamat. + Ilmu Bumi + +JONPIJARELI jengkel sekali karena sejak pagi dia telah +mengalami hal yang paling dibencinya, yaitu mendengar +orang mengetuk pintu. Dia tak mau berjumpa dengan manu- +sia karena baginya manusia adalah makhluk jahat yang hanya +memikirkan diri sendiri. + + Dia makin jengkel karena orang yang mengetuk pintu +itu ternyata orang pintar yang dikirim abangnya untuk meng- +obatinya. + + “Apa kau sangka aku ini sudah gila?!” + “Maaf, Bang, aku datang ke sini untuk membekam +Abang ....” + “Apa katamu?! Membekam aku?! Mulutmu yang kube- +kam nanti!” + “Maaf, Bang, aku hanya disuruh Bang ....” + “Hanya apa?! Enyah sana!” Jon mengayun-ayunkan +sapu di tangannya. + Ayah ~ 307 + + Orang itu cepat-cepat mengemasi alat-alat bekamnya, +lalu kabur terbirit-birit. + + Sial, masih naik-turun dada Jon karena marah akibat +kedatangan tabib itu, tahu-tahu pintu rumahnya diketuk lagi. + + “Siapa?!” + “Selamat siang, kami petugas sensus, Pak.” + Melalui kaca pintu, Jon melihat dua orang berseragam +pemerintah. + “Bolehkah kami masuk, untuk bertanya dan mengisi for- +mulir ini?” + “Tidak boleh!” + “Tapi, Pak ....” + “Tidak ada tapi-tapi! Tolong tulis saja di formulirmu itu, +JonPijareli, sampah masyarakat!” + “Tapi, Pak ....” + “Angkat kaki!” + Kedua petugas itu kabur. + Sungguh hari yang benar-benar sial. Setelah petugas +sensus itu, ada lagi yang mengetuk pintu. Darah mengalir de- +ras ke kepala Jon. Diambilnya senapan angin, diisinya peluru, +dipompanya tujuh kali. + “Siapa itu?!” + Terdengar bisik-bisik di luar. + “Siapa?!” + Tak ada jawaban. + 308 ~ Andrea Hirata + + “Jawab! Kalau tidak, peluru senapan angin akan berde- +sing-desing.” + + Bisik-bisik lagi di luar, lalu diam lagi. + “Kuhitung sampai tiga!” + Di luar terdengar orang bertengkar. + “Satu!” + Tak ada respons. + “Dua!” + Jon siap keluar dari balik lemari, lalu menembak ber- +tubi-tubi. Situasi kritis, tetapi tiba-tiba terdengar suara yang +lembut. + “Wahai Saudara JonPijareli, pertama-tama, atas perke- +nan Saudara, sudilah kiranya menerima perkenalan dari saya. +Nama saya Ukun, saya bertandang ke sini bersama mitra +saya. Manakala Saudara berkenan, saya bermaksud menge- +nalkan nama mitra saya ini.” + Jon terpana. Tak pernah dia mendengar orang bicara +seajaib itu. Siapakah orang-orang itu? Namun, suara itu bersaha- +bat sehingga Jon menurunkan moncong senapan. + “Apakah kalian dari asuransi?!” + Terdengar pertengkaran kecil lagi di luar. Jon mengintip. +Dari kaca yang buram dia melihat bayangan dua orang, salah +seorangnya membuka-buka buku yang tebal. + “Maaf, dengan perkenan Saudara, bukan, kami bukan- +lah dari daerah sini.” + Jon bingung. + Ayah ~ 309 + + “Apakah kalian dari partai politik?!” + “Kiranya bukan.” + “Apakah petugas?!” + “Kiranya bukan.” + “Apakah kalian penjual minyak wangi?” + “Maafkan telah mengecewakan Saudara, kami datang +bukan untuk berdagang berniaga.” + “Tukang tagih?!” + “Oh, maafkan kami mengecewakan hati Saudara lagi.” + “Apakah kalian orang jahat?!” + Tamat membuka tas, mengeluarkan map, mengambil +dua lembar kertas, menyerahkan selembar untuk Ukun. Se- +rentak mereka menempelkan kertas itu di kaca pintu. + “Bilamana Saudara merasa sangsi, kiranya Saudara +berkenan melihat ini, kami punya surat keterangan kelakuan +baik yang dikeluarkan pihak Kepolisian Republik Indonesia.” + Jon takjub atas peristiwa ganjil itu. Dia semakin penasar- +an, siapakah manusia-manusia ajaib itu? Jon mendekati pintu +dan mengamati SKKB itu. Di celah-celah surat itu, Jon meli- +hat dua orang berpakaian mencolok seperti biduan orkes Me- +layu mau naik panggung. Kedua orang itu tersenyum lebar. + Tanpa benar-benar menyadarinya, Jon memutar kunci, +memegang hendel, lalu membuka pintu. Itu tindakan berse- +jarah sebab itulah untuk kali pertama sejak dia ditinggalkan +Lena dan Zorro setahun yang lalu dia membuka pintu untuk +tamu. + 310 ~ Andrea Hirata + + Jon menatap Ukun dan Tamat dari bawah ke atas bo- +lak-balik. Bau harum menguar. Jon teringat terakhir menci- +um bau minyak wangi sinyong-nyong waktu minyak itu dipakai +kakeknya, yang telah meninggal 25 tahun yang lalu. + + Jon adalah orang panggung jadi sudah sering melihat +orang berpenampilan norak, tetapi tak pernah dia melihat +orang berpenampilan senorak dua pria di depannya. + + Rambut Ukun bergaya belah samping, jambulnya dite- +guhkan dengan minyak rambut Tancho hijau sehingga gempa +bumi 6,5 skala Richter takkan mampu menggoyangnya. Dia +berkacamata netral yang dibelinya di kaki lima dekat Masjid +Baiturachman, Banda Aceh. Senyumnya kalem. Dari leher +ke atas dia tampak seperti Spiderman saat sedang menjadi +orang biasa. + + Kemejanya ketat lengan panjang berwarna metalik. Ikat +pinggangnya besar, sebesar selempang putri kecantikan, ber- +manik-manik pula. Celananya cutbrai, yang jika empat orang +mengenakannya dan berjalan beriringan di Pasar Manggar, +para pegawai Dinas Kebersihan Kota Kabupaten Belitong +Timur bisa dirumahkan. Sepatunya jenggel hitam berkilat, ber- +hak agak tinggi dan mancung, dari plastik. Cincin batu akik +bertebaran di jarinya. + + Dandanan Tamat mirip Ukun. Mereka seperti anak +kembar yang diberi pakaian sama oleh orangtuanya. + + Jon menampar-nampar pipinya sendiri, untuk memasti- +kan bahwa dia tidak sedang bermimpi. + Ayah ~ 311 + + “Kudengar ilmuwan tak menemukan makhluk selain +di Bumi, rupanya mereka keliru, dari planet manakah kalian +ini? Halo? Ini planet Bumi.” + + Jon mempersilakan mereka masuk dan duduk. Dia kem- +bali terpana melihat Kamus Umum Bahasa Indonesia yang diba- +wa Ukun serta koper besar aluminium yang ditenteng Tamat. +Ukun dan Tamat menyampaikan maksud kedatangan mere- +ka. Jon terperangah. + + “Jadi, kalian dari Pulau Belitong?” + “Ya.” + “Jauh-jauh ke Medan, mau mencari Lena dan Zorro?” + “Begitu kiranya.” + “Tunggu-tunggu.” Susah bagi Jon mencerna semua itu. + “Terangkan kepadaku seolah-olah aku ini hanya tamat +SMP.” Padahal, SD pun Jon tak tamat. + Ukun dan Tamat bergantian menjelaskan. + “Bagaimana kelean bisa sampai ke sini?” + “Oh, itu karena keahlian seseorang bernama Tamat.” + “Siapakah Tamat itu?” + “Kiranya saya sendiri, Bang.” + Jon menggeleng-geleng. + “Jadi kau tukang gulung dinamo?” + Ukun mengangguk. + “Dan, kau tukang kipas satai?” + “Di restoran satai kambing muda Afrika, Tanjong Pan- +dan.” Tamat memperjelas jabatannya. + 312 ~ Andrea Hirata + + “Dan, kalian memecahkan tabungan dari susah payah +bekerja bertahun-tahun, untuk perjalanan mencari Lena dan +Zorro, demi kawan kalian yang bernama Sabar Menanti itu?” + + “Ya, Bang,” jawab Tamat ringan, seakan semua itu bu- +kanlah masalah. Jon tercenung. Dia takjub di satu sisi dan ter- +haru di sisi lain. + + “Maaf, kiranya berkenan saya bertanya, pernahkah +Saudara JonPijareli ke Belitong? Manakala pernah, bilama- +nakah?” Ukun bertanya. + + “Oh, tentu, aku pernah main musik di Pangkal Pinang.” + Tamat dan Ukun saling pandang, Ukun bicara. + “Maaf Saudara Jon, kiranya Pangkal Pinang berada di +Pulau Bangka. Kalau kita telaah peta secara saksama, akan +tampaklah bahwa Pulau Bangka bertetangga dengan Pulau +Belitong. Namun, usahlah risau, tak terbilang banyaknya +orang yang menyangka telah ke Pulau Belitong, tapi sesung- +guhnya mereka ke Pulau Bangka. Karena, kedua pulau itu +sama-sama memiliki pantai-pantai nan elok. Mereka ke Pan- +tai Parai, mereka sebut ke Belitong, padahal pantai itu di +Bangka. Pantai Tanjong Tinggi nan indah tak terperi, itu ada +di Pulau Belitong. Maaf beribu ampun, boleh jadi waktu SD +dulu, nilai rapor Saudara Jon untuk Ilmu Bumi dapat 4. Aih, +janganlah berkecil hati, nilai Ilmu Bumi saya pun sering 4, +paling pol 5. Sama merahnya dengan Saudara Jon. Daripada +saya pun, sampai sekarang masih sering terkacaukan antara + Ayah ~ 313 + +Pulau Kalimantan dan Pulau Irian, tapi janganlah karena hal +semacam itu membuat kita berkecil hati.” + + “Terima kasih, Bung.” + “Sama-sama, Saudara Jon.” + Indonesia +Lonely Man + +PERSIS Izmi yang diam-diam terinspirasi oleh Sabari, Jon- +Pijareli pun diam-diam tergugah oleh Ukun dan Tamat. Dia +kagum akan ketulusan dua lelaki Belitong itu dan merasa +malu akan sikapnya yang selalu mengasihani diri sendiri. + + Jon melamun memikirkan masa depannya. Tiba-tiba dia +dapat melihat semuanya dengan jernih. Semuanya gara-gara +kehadiran Ukun dan Tamat. Maka, baginya kedua orang itu +adalah kiriman dari langit. Jon merasa terlahir kembali. + + Mereka segera menjadi sahabat baik. Sifat-sifat buruk +Jon lenyap, sifat-sifat baiknya kembali. Dia mulai bertegur +sapa dengan tetangga dan kawan-kawannya. + + “Ngomong-ngomong, bolehkah aku ke pasar sebentar? +Aku mau membeli air raksa, akan kukeraskan kalian berdua +ini, lalu kutempel di dinding. Karena, orang macam kalian +ini sudah tak ada lagi di dunia ini.” Jon berkelakar, terurailah +tawa gembira di ruang tamu yang tadinya kelam itu. + Ayah ~ 315 + + Hari itu juga Jon menurunkan gitar kosongnya yang +hampir setahun tergantung di dinding. Dengan lembut di- +lapnya debu, lalu dipeluknya gitar itu dengan syahdu. Tamat +duduk di sana, di bangku, menghadap ke jendela, memperha- +tikan merpati yang hinggap di kawat telepon, silih berganti. +Ukun tak lepas memandang Jon. + + Lalu, terdengar petikan gitar. Ukun terpana. Benar kata +orang bahwa Jon berbakat. Ukun tak tahu banyak soal musik, +dia pun lupa-lupa ingat lagu yang dibawakan Jon itu, teta- +pi caranya bernyanyi dan bermain gitar membuatnya mera- +sa indah. Tamat memandang jauh ke luar jendela. Kakinya +menge­ ntak-entak lantai dengan halus mengikuti lagu. + + Dilanda semangat baru, Jon kembali mengumpulkan +anggota band-nya dan mereka mulai tampil. Dia pun berse- +mangat untuk menyelesaikan lagu ciptaannya yang berkali- +kali tertunda. Lagu berjudul “Aku Berlari” itu semula ingin +dibuatnya dengan irama reggaedut alias reggae dangdut. + + “Kupikir harus lebih bersemangat, Bung! Rock lebih co- +cok. Kalian tahu lagu Bon Jovi, ‘You Give Love a Bad Name’? +Kurasa harus macam lagu itu. Intronya drum mengentak- +entak, kemudian masuk vokal, vokal dan drum saja. Setuju?” + + Sulit bagi Ukun dan Tamat untuk mengangguk sebab +mereka tak tahu. + 316 ~ Andrea Hirata + +Sementara itu, nun jauh di belahan dunia yang lain, terpi- +sahkan oleh samudra, tepatnya di Darwin, Australia Utara, +Brothe­r Niel Wuruninga, seorang nelayan Aborigin, heran +melihat seekor penyu tersangkut di pukatnya. Penyu itu sa- +ngat besar, itu hal biasa, dia tak heran. Yang membuatnya +heran adalah sepotong aluminium yang terikat di kaki penyu +itu. + + Dia tahu para ahli biologi maritim sering menempelkan +label semacam itu pada penyu untuk tujuan penelitian, tetapi +aluminium itu berbeda, tak seperti pekerjaan peneliti. + + Dinaikkannya penyu itu ke perahu, dipotongnya akar +bahar yang mengikat aluminium ke kaki penyu. Sejurus ke- +mudian dia tertawa membaca bahasa Inggris tak keruan dari +tulisan yang digerus pada lempeng aluminium itu. + + Belitong, 2 Desember, 1990. + This from Sabari, please help for information where my son Zor- + ro and the woman Marlena binti Markoni. Loss, no clear where. + Marlena my X wife, Zorro no X son, he my son always, to be + continue, forever. + Happy news for give to Sabari, Belantik Village, close SD Inpres + (the president instruction school basic), east Belitong Island, Indo- + nesia. SOS, mei dei, help, urgent, emergency, danger, your good will + give back to you again by God, sorry before and after, thank you no + limit. Sincerely yours, + very very sad, Indonesia lonely man, Sabari. + Sahabat Pena +dan Hikayat +6 Kota + +DENGAN sedih, kepada Ukun dan Tamat, Jon berkisah soal +rumah tangganya yang berakhir tak menyenangkan dengan +Lena. Bahwa Lena kecewa sehingga tak mau memberi tahu +Jon ke mana dia akan pergi. + + “Kalau kalian menemukan Lena dan Zorro, kabari +aku,” kata Jon sedih. “Dan, bilang sama mereka, aku selalu +rindu.” Matanya berkaca-kaca. + + “Usah khawatir, Saudara Jon,” bujuk Ukun. + “Segera setelah kami menemukan mereka, akan kami +kabari Saudara Jon dalam tempo sesingkat-singkatnya.” + Meski berat, Jon harus berpisah dengan Ukun dan Ta- +mat. Orang-orang Belitong itu harus melanjutkan perjalanan +untuk mencari Lena dan Zorro. Perasaan sedih, tentu tak per- +lu dibicarakan lagi karena sudah pasti. + 318 ~ Andrea Hirata + + Untuk memudahkan pencarian, Jon memberi mereka +selembar foto. Ada Lena, Zorro, dan Jon sendiri dalam foto +keluarga yang manis bertabur senyum itu. + + Berpedoman pada surat-surat Lena, tujuan Ukun dan +Tamat berikutnya adalah Bengkulu. Setelah dua hari dua ma- +lam di dalam bus, mereka memasuki Bengkulu dan terkejut +melihat umbul-umbul serta iring-iringan besar orang memu- +kul-mukul beduk. Semakin dalam masuk ke kota, semakin +meriah. + + Tamat teringat akan cerita Lena dalam suratnya kepada +Zuraida. Inikah yang dimaksud Lena dengan Festival Tabot? +Sebuah festival Islami, festival terbesar di Bengkulu, diada- +kan setiap tahun selama sepuluh hari untuk memperingati +wafatnya Imam Hussain, cucu Rasulullah di Padang Karbe- +la. Seperti melihat Masjid Baiturachman, Tamat dan Ukun +merasa beruntung tiba di Bengkulu saat Festival Tabot yang +memesona. + + Kemudian, mereka berjumpa dengan seorang tokoh +bernama Manikam, yang berkata bahwa dia juga selalu ingin +tahu di mana Lena dan Zorro berada. + + “Memang pernah Lena meneleponku, tapi sekadar me- +nanyakan kabarku, apakah aku baik-baik saja. Waktu itu dia +bilang dia di Tanjung Karang, tak memberi alamat jelas.” + + Manikam bersimpati pada upaya Ukun dan Tamat +mencari Lena dan Zorro demi Sabari. Dia ingin membantu +sedapat-dapatnya. Dia juga menyukai Ukun yang baik tutur + Ayah ~ 319 + +katanya, yang selalu mengucapkan kami haturkan terima kasih +tak terkira. + + “Mungkin Lena ada di Tanjung Karang, Palembang, +Jambi, Padang, Bukittinggi, atau Singkep karena kawan- +kawan penanya ada di sana. Tapi, tak mungkin Singkep, ter- +lalu jauh, harus menyeberangi laut, apalagi Lena bepergian +dengan anak kecil.” + + Ukun membuka Kamus Umum Bahasa Indonesia, lalu ber- +tanya dengan mantap: + + “Gerangan apa yang membuat Kakanda Manikam me- +ngetahui daripada semua keadaan itu?” + + “Mungkin karena saya pernah menjadi suaminya.” + Manikam bilang, Lena senang bepergian, senang berka- +wan, senang berkorespondensi. Sahabat penanya tersebar di +banyak daerah. Beberapa surat dari sahabat penanya masih +datang ke alamat rumah Manikam. + Tamat gembira mendengar informasi itu sekaligus getir. +Sebab, dia tahu mencari Lena dan Zorro akan sangat sulit, tak +semudah dibayangkan. Dulu waktu masih di Belitong mereka +pikir paling jauh Lena hanya akan sampai ke Medan, lalu me- +reka akan membujuknya agar pulang sebab Sabari mau gila. +Seumpama Lena tak mau pulang, silakan, tak apa-apa, paling +tidak Zorro bisa diajak pulang. Kalau keduanya tak mau pu- +lang, silakan, tak apa-apa juga. Toh, negeri ini sudah merdeka +lebih dari lima puluh tahun, orang bebas menentukan pilih- +an. Yang penting mereka telah berusaha menemukan Lena + 320 ~ Andrea Hirata + +dan Zorro. Itu kewajiban seorang kawan. Kalau nanti mereka +pulang tidak membawa Lena atau Zorro dan Sabari menjadi +gila, silakan juga, tak apa-apa. + + Kenyataan sungguh berbeda. Begitu gampang mende- +ngar Manikam menyebut enam kota tadi, tetapi sesungguhnya +kota-kota itu terpisah ribuan kilometer, sedangkan satu-satu- +nya pedoman untuk mencari Lena hanyalah dari surat-surat +sahabat penanya yang masih tertinggal di rumah Manikam. +Hanya itu, tak ada cara lain. Tamat curiga, jangan-jangan +Marlena sudah menikah lagi dengan salah seorang sahabat +penanya. + + Manikam tak mau memberi harapan kosong kepada +orang-orang kampung yang naif itu. Sungguh sulit mencari +seseorang hanya lewat sahabat pena. + + “Sebaiknya, kalian pulang saja ke Belitong.” + “Terima kasih atas saran Abang, tapi seisi Kampung Be- +lantik telah mengantar kami di Pelabuhan Tanjong Pandan. +Tak mungkin kami pulang begitu saja, lagi pula, tak terba- +yangkan apa yang akan kukatakan kepada Sabari. Kami akan +mendatangi sahabat-sahabat pena itu, apa pun yang akan ter- +jadi,” kata Tamat. + Ukun tercenung, lalu bersabda, “Sauh telah diangkat, +layar telah terkembang, ayam jantan telah berkokok, ayam +betina telah berkotek, bebek telah ber-kwek-kwek, bintang telah +bersinar, bulan juga, takkanlah kiranya kami putar haluan.” + Ayah ~ 321 + +Berhari-hari mereka terbanting-banting dalam bus kelas eko- +nomi, akhirnya sampai di Terminal Bus Raja Basa, Tanjung +Karang. + + Mereka mendatangi alamat sahabat pena Lena di Krui. +Orang itu adalah lelaki setengah baya, beranak empat, be- +kerja sebagai pencari getah damar, istrinya perajin kain tapis. +Sayangnya, dia tak tahu di mana Lena. Katanya setelah me- +nerima surat Lena dari Medan, Lena tak pernah lagi memba- +las suratnya. Kata orang itu, dia telah berkawan pena dengan +Lena sejak mereka masih kelas empat SD. + + “Bersahabat pena kian sedikit peminatnya. Ini hobi in- +dah yang semakin kesepian. Sahabat pena akan segera pu- +nah, mirip telegram.” + + Sahabat pena di Metro dan Tulang Bawang memberi +informasi yang sama soal Lena. Meski kecewa, di Lampung- +lah Ukun menemukan berliannya wejangan Bu Norma ten- +tang kekayaan bahasa. Penjelajahan mereka dari Krui ke Tu- +lang Bawang meliputi wilayah Lampung pesisir, Pubian, dan +Abung dengan perbendaharaan kata yang berbeda. Ukun +merasa berwisata bahasa. + + Dari Stasiun Pasar Bawah mereka naik kereta dengan +tujuan akhir Stasiun Kertapati, Palembang. + + Ada tiga sahabat pena Lena di sana, yakni pedagang ca- +bai keriting di pasar induk, penjaga toko kelontong di Bom + 322 ~ Andrea Hirata + +Baru, dan dosen di Universitas Sriwijaya, Bukit Besar. Semua +mengatakan menerima surat terakhir dari Lena waktu dia +masih di Medan. + + Ukun dan Tamat senang berjumpa dengan sahabat +pena karena mereka punya kepribadian yang sama, yakni +ramah, penolong, amat menghargai persahabatan, dan lihai +berbahasa. Para sahabat pena memahami bahwa terdapat +seni yang indah dalam surat-menyurat. + + Mereka selalu menawari untuk tinggal, tetapi Ukun dan +Tamat tak bisa beristirahat sebelum menemukan Lena dan +Zorro. Mereka menemukan kesan yang amat baik tentang +sahabat pena, mengapa dewasa ini tak ada lagi orang bersa- +habat pena? + + Meninggalkan Palembang dengan kecewa, mereka ke +Jambi. Karena persediaan uang menipis, mereka berhemat +dengan naik bus kelas ekonomi dari kota ke kota. Jika kema- +laman, mereka tidur di terminal. Adakalanya mereka me- +numpang truk. Mereka mulai menerapkan strategi makan +sehari sekali, di warung nasi termurah. Tak lama kemudian +strategi itu meningkat menjadi makan dua hari sekali. + + Perjalanan yang berat, tidur melingkar seperti tupai di +sembarang tempat, jarang makan dan mandi, Ukun dan Ta- +mat compang-camping. Dalam waktu singkat mereka tampak +macam gelandangan, tak lebih bagus daripada keadaan Sa- +bari di Belitong. + Ayah ~ 323 + + Jambul Tamat ala James Dean yang masih tampak wak- +tu di Medan, telah lenyap dari pandangan mata. Bau minyak +sinyong-nyong berganti menjadi bau matahari, bau pakaian +yang jarang diganti, dan bau orang miskin. + + Kemeja lengan panjang mereka sudah luntur warnanya. +Ikat pinggang besar bermanik-manik itu telah diganti menja- +di tali rafia yang diikat kencang, simpul mati, karena celana +cutbrai menjadi kebesaran sebab keduanya telah kurus ku- +rang makan. + + Sisir telah rontok gigi-giginya, saputangan telah berubah +menjadi lap montir motor untuk mengelap busi. Sepatu jenggel +ala biduan orkes Melayu yang mengilap dan mendebarkan +itu telah berubah menjadi sandal jepit Daimatu. Yang masih +tampak gagah hanya koper aluminium yang kuncinya juga +sudah minggat sehingga koper itu harus diikat tali rami. + + Meski kusut masai, berantakan, kurang makan, dan bau +tengik, Ukun tak pernah kehilangan keanggunannya dalam +berbahasa. Ditunjukkannya foto kepada sopir bus malam, +sambil membuka Kamus Umum Bahasa Indonesia yang tebal itu. + + “Dalam pada melintasi kota demi kota, adakah kiranya +Kakanda Sopir pernah melihat perempuan manis berlesung +pipit dalam foto ini?” + + Kepada Pak Pos Kantor Pos Muaro Bungo, Ukun ber- +tanya, “Dalam pada mengemban tugas mengantarkan ama- +nah, adakah Kakanda pernah melihat orang-orang dalam +foto ini?” + 324 ~ Andrea Hirata + + Pak Pos menatap Ukun. “Tiadalah saya pernah meli- +hatnya. Namun, seumpama saya melihatnya, tentulah tersirat +dalam hati saya untuk menyampaikan pada pihak-pihak yang +ada di dalam foto itu, bahwasanya dua orang pemuda dari +negeri seberang samudra nan bergelora sedang mencari me- +reka, oh, dada saya berdebar-debar dibuatnya.” + + “Tak terperikan rasa terima kasihku, Kakanda.” Ukun +memeluk Kamus Umum Bahasa Indonesia kuat-kuat. + + Masih di Jambi, di sebuah kios pangkas rambut, Ukun +bertanya sambil memperlihatkan foto itu. + + “Aku kenal orang ini!” kata orang itu. + Ukun dan Tamat terperanjat. + “Ini JonPijareli, bukan?! Gitaris dari Medan!” + Tukang pangkas rambut lainnya merubung foto itu. + “‘La Bamba’!” teriak salah seorangnya sambil menyanyi- +kan lagu yang liriknya dapat membuat mulut kusut itu. Yang +lain ikut menari dan menyanyikan lagu runyam itu, meski tak +jelas apa yang mereka ucapkan. Rupanya Jon pernah memu- +kau publik Jambi dengan lagu itu. + “Kalian kenal dengan JonPijareli?” tanya orang tadi. + “Oh, dia kawan kami,” jawab Ukun bangga. + “Benarkah?” + Sayangnya tak seorang pun mengenali Lena dan Zorro. +Namun, paling tidak sejak itu Ukun dan Tamat mengenal sisi +lain JonPijareli, yaitu ternyata dia masyhur seantero Sumatra. +Dia adalah selebritas Sumatra. + Ayah ~ 325 + +Benar kata Bu Norma, tak terbilang besarnya manfaat bagi +Ukun dan Tamat karena menggunakan bahasa Indonesia +sebaik-baiknya. Meski banyak salahnya, tetapi mereka selalu +diterima dan ditolong siapa pun sepanjang jalan karena ber- +bahasa seperti itu memberi kesan yang baik tentang mereka. + + Pasti sering tidak praktis, tetapi Ukun telah pandai ber- +siasat. Dalam situasi darurat, Kakanda disingkatnya menjadi +Kanda. Diperlihatkannya foto itu kepada sopir bus ALS yang +bergegas mau berangkat. + + “Kiranya Kanda pernah melihat perempuan nan padat +ini?” Ringkas, padat, dan tetap anggun. + + Sayangnya semua usaha masih tak menghasilkan apa +pun. Sebenarnya, sudah pintar cara mereka mencari Lena. +Mereka selalu bertanya kepada pak pos karena pak pos men- +jalani jalan antar yang tetap, setiap hari selama bertahun- +tahun. Maka, mereka tahu warga lama dan baru. Mereka +tahu anak yang baru lahir dan orang yang baru meninggal. +Tugas mereka yang mulia membuat mereka dicintai dan sa- +ling kenal dengan semua orang. + + Mereka juga memperlihatkan foto kepada penjual tiket +bus, kereta, kapal, dan lokasi-lokasi wisata sebab Marlena se- +nang berwisata. Mereka mengunjungi KUA di setiap kota, +untuk bertanya kalau-kalau ada data nikah Marlena. + 326 ~ Andrea Hirata + + Lena dan Zorro masih tak tahu rimbanya. Raib macam +ditelan bumi. Keadaan Ukun dan Tamat semakin menyedih- +kan. Orang-orang udik itu macam mesin yang terlalu berat +bekerja. Mereka selalu lelah, haus, dan lapar. Tamat melihat- +lihat lagi alamat sahabat pena Lena. Pesimis dia melihat tiga +tempat yang harus mereka kunjungi, yaitu Padang, Bukitting- +gi, dan Singkep. Masihkah mereka sanggup menempuh per- +jalanan itu? + + Sahabat pena terakhir yang mereka kunjungi di Jambi +adalah pengusaha percetakan kecil. Untuk mengenang perke- +nalan yang singkat dan manis, orang itu bermaksud mencetak +kartu nama untuk Ukun dan Tamat. + + Orang-orang kampung yang bahkan tak pernah terpikir +akan punya kartu nama itu merasa takjub. + + “Kartu nama kiranya diperuntukkan kepada golongan +orang pintar, para pejabat negara, orang politik, para peda- +gang peniaga, para pemborong, dan kaum amtenar. Boleh- +kah khalayak awam semacam saya dan mitra saya ini punya +daripada kartu nama?” Ukun bertanya. + + “Tentu, Bang, boleh saja, kartu nama untuk semua +orang, segala usia.” + + “Bagaimana isi kartu nama itu nanti, Bang?” tanya Ta- +mat. + + “Ah, macam biasalah, macam orang-orang lain tu, ada +nama, alamat, jabatan.” + + “Jabatan?” + Ayah ~ 327 + + “Tentu, misalnya direktur, asisten apoteker, kepala bagi- +an ini dan itu, profesi, apa saja.” + + “Atas perkenan Abang, tugas sehari-hari saya adalah +menggulung dinamo, adapun daripada mitra di sebelah saya +ini, adalah tukang kipas satai di restoran satai kambing muda +Afrika,” Ukun menjelaskan. + + Orang itu merenung. + “Kurasa tak perlulah itu ada di kartu nama, cukup nama +dan alamat saja. Silakan tulis nama dan alamat jelas.” Orang +itu menyerahkan kertas dan pulpen. + Ukun dan Tamat menyingkir ke meja sebelah sana. Gu- +gup mereka waktu bermusyawarah. Kertas dan pulpen dise- +rahkan kembali ke orang tadi. Orang itu membacanya dan +tersenyum. Dia pergi. + Tak lama kemudian dia kembali membawa dua kotak +berisi kartu nama. Ukun dan Tamat menerimanya dengan +takzim dan mengucapkan ribuan terima kasih. Itulah akhir +pencarian Ukun dan Tamat di Jambi. + Dalam perjalanan naik bus ke Padang, Ukun dan Tamat +terpesona mengamati kartu nama mereka. Tak pernah mere- +ka membayangkan dalam hidup mereka sebagai tukang gu- +lung dinamo dan tukang kipas satai suatu ketika akan punya +kartu nama. Mungkin dalam profesi itu hanya mereka di du- +nia yang punya kartu nama. Berulang-ulang Ukun membaca +kartu nama itu: Maulana Hasan Magribi (Ukun), kawan JonPijare- +li, gitaris top dari Medan. + Stolen Generation + +PATRICK Mundara memberi tahu Larissa bahwa ayahnya +hilang. + + “Gone, just like that, gone!” kata sepupunya itu gusar. + Larissa berusaha tenang. Bukan baru sekali-dua kali, jika +bertengkar dengan ibunya, ayahnya pergi ke rumah saudara- +saudaranya, tak bilang-bilang. Larissa telah melihat ayahnya +berubah akhir-akhir ini. Dia menjadi pendiam dan sering +melamun. Larissa cemas. Dia tak masuk kuliah berikutnya, +mahasiswi Biologi di Charles Darwin University itu pulang. + Di rumah, dilihatnya wajah ibunya tegang. + “Your oldman,” katanya jengkel. + “Sudah di Alice Spring!” + Oh, jauhnya? + “Ini gara-gara bertengkarkah?” + Mommy menggeleng. + “Jadi, mengapa Ayah jauh-jauh ke sana?” + Ayah ~ 329 + + “Tanyalah sendiri.” + Larissa menelepon bibinya di Alice Spring, yang mem- +benarkan bahwa Pak Tua Niel sudah bercokol di rumahnya. + “Macam orang linglung keadaannya,” kata bibinya. + “Kasihkan telepon kepadanya.” + Niel tak mau menerima telepon. + “Kalau begitu, tanya dia, mengapa dia kabur, bikin kelu- +arga cemas saja, cepat pulang, jangan macam-macam, sudah +tua, nanti repot semua orang.” + Terdengar gerung-gerung suara bibi Larissa bicara de- +ngan Niel. + “Riss, katanya dia tak mau pulang.” + “Mengapa?” + Terdengar lagi gerung-gerung suara. + “Katanya, dia mau mencari orang Indonesia, sebelum +ketemu, katanya, dia tak mau pulang.” + Sekarang Larissa yang linglung. Ibunya berdiri tegak di +sampingnya, menguping semua pembicaraan tadi. Larissa +menutup telepon. + “Mom, ada soal apa dengan Indonesia ini?” + Ibu Larissa berkisah soal pesan yang dibawa seekor pe- +nyu dan ditemukan Niel. Mulut Larissa ternganga. Mommy +menyimpan kisah itu dari anak-anaknya karena malu akan +sikap konyol Niel yang menganggap serius penyu itu. + “Itu perbuatan orang-orang iseng saja, barangkali yang +membuat pesan itu sedang terkekeh-kekeh di Indonesia sana, + 330 ~ Andrea Hirata + +atau boleh jadi dari mana saja. Namun, ayahnya mengang- +gap, dari miliaran manusia di bumi ini, dirinya telah terpilih +untuk menerima pesan itu, dia merasa diberi tugas dari langit +untuk mencari orang-orang Indonesia itu. Tiba-tiba dia me- +rasa bagaikan seorang nabi, dapatkah kau bayangkan itu?” + + Mulut Larissa ternganga makin lebar waktu ibunya +memperlihatkan pelat aluminium bertulisan pesan itu dan +melihat tanggalnya. Kata ibunya, Niel telah membawa pelat +itu ke sana kemari dan bertanya kepada orang-orang apakah +mereka mengenal orang Indonesia bernama Zorro dan Mar- +lena. Dia bertanya ke kantor pos, ke polisi, ke keluarga-kelu- +arga Indonesia, bahkan ke kantor imigrasi. + + “Memalukan sekali, bukan?” + “Kapan Ayah menemukan pesan ini?” + “Minggu lalu.” + Larissa menatap ibunya. + “Sadarkah Mommy, pesan ini sudah berumur hampir +tujuh tahun!” + Hari itu pula Larissa berangkat ke Alice Spring untuk +menjemput ayahnya. + +Tentu saja kisah Niel, seekor penyu, dan upaya konyolnya +mencari orang-orang Indonesia itu langsung menjadi komedi + Ayah ~ 331 + +yang menyegarkan di komunitas Aborigin Hodgson Cove. Ja- +dilah dia bulan-bulanan. + + Gayle Rifkin, Annie Brown, Matthew Tarrti adalah ka- +wan-kawan kental Niel sejak kecil, mereka biasa berkumpul di +James Pardy’s Pub setiap Sabtu sore. Sejak Niel menemukan +penyu itu, dia tak lagi berkumpul dengan mereka. Kawan- +kawannya menertawakan Niel sepanjang sore. Dongeng Pak +Tua Niel, Zorro, dan Penyu Ajaib, begitu kelakar mereka. Jika +berjumpa dengan Niel di dermaga, mereka melukis huruf Z +di udara, lalu tertawa terpingkal-pingkal. Kian hari kian ba- +nyak orang yang mengolok Pak Tua Niel. + + Larissa sendiri jadi mengerti mengapa dalam minggu- +minggu terakhir itu ayahnya jadi pendiam dan banyak mela- +mun. Di satu sisi, ayahnya pasti merasa terbebani oleh pesan +yang dianggapnya tak main-main, di sisi lain, dia malu diper- +olok masyarakat. Usai melaut, Niel tinggal di rumah saja. + + Larissa, satu-satunya anak perempuan dalam keluarga +itu, sangat dekat dengan ayahnya. Ditepuk-tepuknya pundak +ayahnya, diyakinkannya bahwa penyu itu tak bisa dianggap +serius. Bahwa di laut adalah hal biasa para nelayan menemu- +kan benda-benda yang aneh. Bahwa ayahnya telah menjadi +bahan olok-olok dan dia iba melihat ayahnya diperlakukan +seperti itu. Ayahnya menatapnya. + + “Penyu itu telah berkelana hampir tujuh tahun, ia bisa +ke mana saja, ke Samudra Atlantik, Samudra Pasifik, ia bisa +ke Amerika Selatan, ia bisa ke Hawaii, bahkan Antartika. Ia + 332 ~ Andrea Hirata + +bisa mati karena usia tua, ia bisa saja digempur kawanan hiu, +bisa dilahap buaya muara. Ribuan nelayan ada di sepanjang +pesisir benua ini, mengapa ia tersangkut di pukat si Tua Niel +ini? Membawa pesan dari Indonesia? Kau tahu, Riss, semua +hal terjadi untuk sebuah alasan. Orang-orang Indonesia yang +hilang itu pasti ada di utara Australia.” + + Niel memperlihatkan lagi pelat aluminium itu. + “Bacalah ini baik-baik, Sabari ini benar-benar sedang +mencari anaknya.” + Larissa membacanya lagi. Ayahnya benar, meski dalam +bahasa Inggris yang rusak, tetapi jika tulisan di pelat itu di- +baca berulang-ulang, memang terasa seperti ratapan seorang +ayah kehilangan anaknya. + +Pukul 10.00 pagi itu, Niel sudah berdandan rapi. Dandanan +yang membuat Larissa dan Mommy terperangah. Niel me- +ngenakan pakaian terbaiknya, dari bawah sampai ke atas. Se- +patu mengilap, berdasi besar berwarna megah, mengenakan +jas, tak peduli udara panas. Belum tentu setahun sekali Niel +tua berdandan seperti itu. Biasanya untuk acara-acara yang +sangat penting saja. Ketika ditanya mau ke mana, dia hanya +tersenyum, tak menjawab. Diambilnya topi pandora-nya, lalu +ditentengnya koper kecil, tak tahu isinya apa. + Ayah ~ 333 + + Mommy dihinggapi perasaan yang pahit, jangan-jangan +soal penyu itu telah membuat suaminya sakit ingatan. Melalui +kaca jendela, Larissa dan Mommy melihat Niel tua berjalan +menuju barat, ke arah pusat Kota Darwin. + + Pikiran Larissa tak jauh dari pikiran ibunya, segera dia +mengganti pakaian, lalu menyambar kunci mobil. Tak lama +kemudian dia sudah berada di dalam mobil sedan Datsun bu- +tut, PL411, 1967. + + Pelan-pelan Larissa meluncur, dari jauh dilihatnya ayah- +nya berjalan di trotoar. Dia ingin membuntuti ayahnya, ingin +tahu apa yang akan dilakukannya. Setelah beberapa lama, di- +lihatnya ayahnya menyeberangi jalan, berjalan lagi dan ber- +henti di depan pagar yang tinggi. Tampak ayahnya berbicara +dengan seseorang, lalu masuk ke pekarangan sebuah gedung. +Larissa melaju pelan melewati bangunan itu dan terkejut me- +ngetahui gedung itu adalah Gedung Perwakilan Indonesia. +Ayahnya pasti bertanya tentang orang-orang Indonesia yang +hilang itu. + + Larissa menunggu ayahnya di seberang jalan di muka +gedung itu. Tak lama kemudian ayahnya keluar dan berjalan +melalui jalan dia datang tadi. Larissa mengikutinya. + + “Pop, Pop!” panggilnya. + Niel terkejut. + “Masuk ke mobil, ayo pulang.” + Niel terus berjalan. + “Ayo, masuklah.” + 334 ~ Andrea Hirata + + “Kau tak percaya,” kata ayahnya. + “Ya, aku tak percaya, tapi masuklah.” + Niel menolak. Dia terus melangkah. Beberapa orang +melambai kepada Niel dan menanyakan soal penyu itu. La- +rissa tahu mereka meledek ayahnya. + “Ayolah, Pop, masuk ke mobil, kita pulang.” + Niel terus berjalan. + Sampai di rumah, Mommy yang menganggap Niel su- +dah keterlaluan, langsung menggempur Pak Tua. Kesabar- +annya habis karena dia tak tahan mendengar gunjingan te- +tangga bahwa suaminya sudah sinting. Dia malu jadi bahan +tertawaan. Pak Tua malah berkata takkan berhenti mencari +anak yang hilang bernama Zorro itu meski seluruh Australia +menertawakannya. Mommy membanting pintu. + Malam itu Larissa terjebak kesenyapan. Senyap yang +menyakitkan karena pertengkaran ayah dan ibunya tadi si- +ang. Sepanjang sore, belum ada perdamaian. Mommy tak +mau bicara dengan Pak Tua. + Malam beranjak. Gerung burung hantu menambah se- +nyap suasana. Larissa masuk ke kamar untuk melihat ayah- +nya. Ayahnya sudah jatuh tertidur. Di dekatnya ada foto. +Ayahnya pasti memeluk bingkai foto itu sebelum tidur, kini +terlepas dari pelukannya dan tergeletak di sampingnya. + Larissa sudah sering melihat foto itu karena telah lama +tergantung di dinding. Foto itu adalah foto lama keluarga, hi- +tam putih, di dalam foto itu ada ayah ayahnya, ibu ayahnya, + Ayah ~ 335 + +kakak sulung ayahnya, dan ayahnya sendiri. Waktu foto itu +diambil, Niel baru berusia lima tahun dan abangnya, Jerome +Wuruninga, berusia delapan tahun. + + Larissa mengamati foto itu dan tiba-tiba sesuatu seakan +menyambarnya. Dia teringat akan salah satu tragedi kema- +nusiaan terbesar di Australia, yakni saat pemerintah Australia +memisahkan secara paksa anak-anak Aborigin dari orangtua +mereka. Anak-anak itu kemudian disebut stolen generation, ge- +nerasi yang dicuri. Hingga saat ini ayahnya tak tahu di mana +abangnya itu dan tak tahu ke mana harus mencarinya. + Musibah + +UANG hampir habis. Perjalanan makin berat bagi Ukun dan +Tamat. Namun ajaib, mencantumkan keterangan di kartu +nama bahwa JonPijareli adalah kawan mereka, sedikit banyak +membuat mereka terbantu. Satpam membolehkan mereka +tidur di terminal, kernet bus tersenyum menerima bayaran +ongkos semampu mereka, penjaga masjid membolehkan +menginap, warung-warung nasi memberi diskon. + + Tiga sahabat pena Lena di Padang, yaitu seorang polisi, +ibu rumah tangga, dan wasit sepak bola, tak dapat memberi +jalan terang soal Lena. Begitu pula sahabat-sahabat pena di +Bukittinggi. + + Sambil menatap Jam Gadang, Tamat mengempaskan +koper aluminium itu. Mereka memeluk diri sendiri untuk +mengatasi dingin Bukittinggi. Persis Sabari yang luntang-lan- +tung awut-awutan di Belitong, keadaan Ukun dan Tamat mo- +rat-marit menyedihkan. Dulu mereka menduga akan menje- + Ayah ~ 337 + +lajah Sumatra paling lama sebulan, nyatanya sudah lebih dari +dua bulan. Harapan satu-satunya tinggal Singkep. + + Karena lelah dan gagal bertubi-tubi, Singkep menge- +cilkan hati mereka. Apalagi, teringat kata Manikam bahwa +Lena tak mungkin ke Singkep sebab jauh dan harus menyebe- +rangi laut, belum menghitung dia membawa anak kecil. + + “Tapi, kita harus ke sana, Boi,” kata Ukun menyema- +ngati Tamat, menyemangati dirinya sendiri sebenarnya. + + “Kita harus menyelesaikan apa yang telah kita mulai. +Kalau gagal di sana, baru kita pulang.” + + Getir Tamat mendengar kata gagal. Ngeri dia memba- +yangkan Sabari berjalan hilir mudik di Pasar Belantik tanpa +menyadari bahwa dirinya tak bercelana. Namun, situasi me- +reka runyam. Persoalannya bukan hanya harapan yang kecil +untuk menemukan Lena dan Zorro di Singkep, melainkan +ada soal pelik lain, yaitu duit sudah habis. Neraca keuangan +mereka bolehlah disebut defisit tingkat gawat. Namun, takkan +mereka menyerah demi kawan mereka, Sabari. Mereka men- +cari kerja di kawasan Pasar Aur Kuningan Bukittinggi. + + Menggulung dinamo memerlukan keterampilan khusus +yang tak sembarang orang bisa. Perlu pengalaman bertahun- +tahun untuk bisa ahli. Di sisi lain banyak orang perlu tukang +gulung dinamo. Oleh karena itu, dengan mudah Ukun men- +dapat pekerjaan. Adapun Tamat, dengan menerapkan prin- +sip bersedia bekerja apa saja asal diberi makan, tak terlalu +susah pula mendapat pekerjaan. + 338 ~ Andrea Hirata + + Rupiah demi rupiah mereka kumpulkan untuk dapat +berlayar ke Singkep serta membiayai ongkos pulang ke Beli- +tong dari Singkep nanti. Akhirnya, jumlah yang mereka per- +lukan terkumpul. + +Sambil tersenyum lebar, Larissa membuka pintu sedan Dat- +sun 1967-nya, yang pedal gasnya harus diperlakukan dengan +tingkat membelai pacar baru sebab jika terlalu kasar mene- +kannya, mobil biru mentah itu pandai terbatuk-batuk. Niel +masuk ke mobil, lalu mereka meluncur ke Koolpinyah, untuk +mencari informasi soal Lena dan Zorro. + + Di sana mereka mengunjungi rumah keluarga paman +Larissa dari pihak ibunya, yang menerima mereka dengan +sikap menahan tawa. Mereka kemudian bertanya tentang +Lena dan Zorro pada beberapa keluarga Indonesia, dengan +asumsi, di kota kecil seperti Koolpinyah, orang asing sebangsa +biasanya saling kenal. Sayangnya tak ada yang kenal. + + Sesuai perjanjian antara Larissa dan ayahnya, mereka +akan mencari informasi tentang Lena dan Zorro di kota-kota +di northern teritory saja. Karena begitulah tanda yang dibaca oleh +Pak Tua Niel lewat pesan yang dibawa penyu itu. Sementara +itu, antarsanak saudara saling menelepon untuk mengantisi- +pasi kedatangan mereka, lalu berjanji untuk bertukar cerita +konyol soal pencarian orang Indonesia itu sehingga mereka +bisa terbahak-bahak. + Ayah ~ 339 + + Larissa dan ayahnya mencari informasi mulai dari Lud- +milla di barat, sampai ke Humpty Doo di timur, lalu ke Ho- +ward Springs di utara, sampai ke ujung selatan, Mandorah. +Mereka bertanya ke kantor pemerintah dan keluarga-keluar- +ga Indonesia. Nihil hasilnya, tentu saja. + + Larissa tahu apa yang mereka lakukan akan sia-sia dan +dia tahu bahwa dia sedang diperolok. Namun, rasa sayang +kepada ayahnya, dan apa yang dirasakan ayahnya akibat ke- +hilangan saudara, membuatnya membutakan mata dan me- +nulikan telinga. + + Setelah hampir tiga minggu berkelana mencari Marlena +dan Zorro, Niel dan Larissa pulang ke Darwin. + + “Karena yang kalian cari adalah khayalan, kalian takkan +menemukannya. Orang-orang yang ada dalam pesan itu ada- +lah tokoh-tokoh komik, mereka hanya ada dalam kepala Pak +Tua Niel yang pikun. Penyu yang membawa pesan itu juga +sudah tua, sama pikunnya dengan Niel.” Begitu pendapat Pa- +man Matthew Tarrti, yang tak lain adik ibu Larissa sendiri. + + Meledaklah tawa keluarga dan tetangga. + “Kau kan mahasiswi, bukankah kau yang seharusnya +lebih rasional dalam hal ini?” Gayle Rifkin menohok Larissa. + Sepupu-sepupu Larissa menyarankan agar Niel me- +nangkap lagi penyu, lalu mengikat pesan di kakinya, menga- +barkan pencarian mereka yang gagal. Tawa meledak lagi. + Niel sendiri merasa lebih tenang karena telah melakukan +sesuatu untuk mencari seorang anak yang hilang. Kegagalan + 340 ~ Andrea Hirata + +yang pahit adalah lebih baik daripada hanya berpangku ta- +ngan. Dimintanya Larissa menulis surat untuk Sabari. Sebu- +ah surat yang mengabarkan bahwa dia telah mencoba men- +cari Lena dan Zorro sekuat kemampuannya, seantero northern +teritory, tetapi tak berhasil. Oleh karena itu, dia minta maaf, +dan semoga suatu hari nanti Sabari menemukan anaknya. + + Larissa melihat alamat seadanya yang tertulis di pelat +aluminium itu, dia berkecil hati. Tak mungkin surat bisa sam- +pai dengan alamat seperti itu, tetapi sekali lagi, dia tak mau +melukai hati ayahnya. Surat dikirim ke Indonesia. Jawaban +tak kunjung muncul. Niel dan Larissa semakin menjadi bu- +lan-bulanan. + +Adapun Ukun dan Tamat, setelah menempuh perjalanan se- +lama dua hari dua malam, akhirnya tiba di Singkep. + + Langsung mereka menuju alamat sahabat pena Lena di +sebuah kampung di daerah Dabo. Jauhnya kampung itu, me- +reka naik beragam kendaraan, mulai dari bus mini, angkutan +desa, mobil bak pengangkut sayur, truk tambang, dan akhir- +nya berjalan kaki belasan kilometer. + + Menjelang sore mereka sampai di kampung itu, tetapi +merasa heran karena kampung itu sangat sepi, seperti kam- +pung yang telah ditinggalkan manusia. + Ayah ~ 341 + + Mereka berjalan menyusuri jalan yang panjang. Rumah- +rumah tipikal permukiman buruh tambang berhadap-hadap- +an. Terdengar bunyi radio atau televisi dari rumah-rumah +yang tertutup. Warung-warung juga tutup. Sesekali orang +melintas cepat naik sepeda dengan wajah cemas. Begitu se- +dih suasana, sampai kambing-kambing yang diikat di pagar +rumah tampak murung. Ayam-ayam yang berkeliaran tak +banyak ribut. Anjing duduk termangu-mangu, jangankan +menyalak, menggerung saja tidak. Terasa benar kampung itu +sedang dilanda duka yang mendalam. + + Ukun mau bertanya apa yang terjadi, tetapi tak ada si- +apa-siapa. Tiba-tiba melintas sesorang perempuan menyebe- +rangi jalan, ingin ke rumah tetangganya. Ukun menghampiri­ +nya. + + “Maaf, Kakanda, gerangan apa yang sedang terjadi? +Mengapa sepi sekali?” Mata perempuan itu merah karena +habis menangis. + + “Mengapa bersedih?” tanya Tamat. + Perempuan itu heran menatap Ukun dan Tamat. + “Tak tahukah kalian ada musibah?” + Tamat terkejut. + “Musibah apa, Kak?” + “Lady Diana meninggal!” + 25 Km/Jam + +SABARI yang tengah berjalan, tiba-tiba pak pos menikung +di depannya, menyerahkan sepucuk surat dan langsung me- +luncur lagi. + + Sabari langsung membaca surat itu. Tanpa Yth. ini-itu, +tanpa menanyakan kabar, keadaan musim atau harga-harga +di pasar, surat itu singkat saja. + + Ri, kami sudah menemukan Lena dan Zorro. + Kami akan membawa Zorro pulang naik kapal kayu dari Pelabuh- +an Dabo dan akan merapat di Tanjong Pandan, sore, 7 September 1997. +Demikian, supaya maklum. + Seumpama Kakanda .... + + Sabari menggigil. + Begitu saja, tangkas dan ringkas. Sabari agak bingung +membaca kata seumpama Kakanda ... yang tak selesai dan terco- + Ayah ~ 343 + +ret-coret setelahnya. Pasti Ukun mau menambahkan satu-dua +kalimat, tetapi surat itu dirampas Tamat dan langsung dikirim. + + Hari itu juga, waktu bersepeda dengan santai menuju +pasar, Zuraida terperanjat karena seorang pria tiba-tiba te- +lah berada di sampingnya, berlari mengikuti kecepatan sepe- +danya. Pria itu berambut pendek model tentara. Rambut di +atas telinga kiri dan kanannya dicukur habis, yang tertinggal +hanya rambut di bagian atas sehingga kepala orang itu ma- +cam ditudungi tempurung kelapa. Dia tak berkumis, tak pula +berjenggot, wajahnya klimis licin macam mangkuk Tiongkok. + + Zurai merasa kenal dengan orang itu. Dia berpikir ke- +ras, Siapakah orang itu? Orang itu tersenyum lebar. + + “Sabari!” Zurai menjerit. + Senyum Sabari semakin lebar. Larinya semakin kencang +sehingga melewati Zurai. + “Ri, kaukah itu, Boi?!” + Sabari tak menjawab, dia terus berlari sambil tersenyum. + Zurai terpana karena baru kemarin melihat Sabari awut- +awutan macam hantu akar baru keluar dari pohon aren. + “Kejadian apa lagi, Ri?” Zurai curiga akhirnya Sabari +menjadi gila, tetapi sebagian dirinya senang melihat Sabari +mendadak berubah. + “Ri, kau tidak gila lagi, ya?!” + Sabari malah menambah kecepatan. Maka, tampaklah +perlombaan orang berlari melawan orang bersepeda. Zurai +memanggil-manggil. + 344 ~ Andrea Hirata + + Mereka melewati orang-orang yang berjalan, mendo- +rong gerobak, bersepeda, dan naik motor. Perlombaan aneh +itu ditontoni orang dari pinggir jalan. Saat itu juru antar surat +pengadilan agama sedang meluncur dengan syahdu naik mo- +tor bebek lawasnya. Dia pun heran melihat orang bersorak- +sorai di pinggir jalan, dan terkejut melihat seorang pria berlari +dan seorang perempuan bersepeda berkelebat hanya sehasta +darinya, dekat sekali sehingga dia merasa angin dari dua so- +sok yang memelesat itu. + + Tak tahu apa yang merasukinya, kontan juru antar su- +rat terpancing. Sudah lama ditunggunya kesempatan untuk +menguji kemampuan motor bebek tuanya itu, kesempatan +emas itu akhirnya tiba. Langsung di-geber-nya gas motornya +untuk mengejar Sabari dan Zurai. Motor kuno itu menjerit- +jerit. + + Melihat ada pesaing baru, Sabari dan Zurai terbakar. +Para penonton di pinggir jalan semakin riuh. Ada yang me- +nyemangati Sabari, ada yang berpihak kepada Zurai, yang +paling banyak adalah pendukung juru antar. + + Menjelang kawasan pasar, perlombaan makin seru. Sa- +bari masih di depan, Zurai lekat di belakangnya, pontang- +panting mengayuh sepeda yang juga butut, krontang-krontang +bunyinya. Keringatnya bercucuran, jilbabnya berkibar-kibar +tak keruan. Di sampingnya, juru antar memacu sepeda motor +sambil menundukkan badan bak pembalap motor GP. Na- +mun sayang, meski telah memutar gas sampai tak dapat lagi + Ayah ~ 345 + +diputar, dia kecewa melihat spidometer, kecepatannya hanya +mampu mencapai 25 kilometer per jam. + + Akhirnya, ketiga pembalap liar itu memasuki kawasan +pasar. Sabari telah mencapai akselerasi yang sempurna. Zu- +rai tersenyum kalah. Dilihatnya dari jauh Sabari memelesat +macam kijang. Tak lama kemudian Zurai mendengar bunyi +motor terbatuk-batuk. Nun di belakang sana dilihatnya seo- +rang pengendara motor bebek berhelm bulat meminggirkan +motornya yang mogok. + Api Neraka + +Surat dari Tamat membuat Sabari yang hampir senewen +sekonyong-konyong menjadi waras kembali, bahkan lebih +waras daripada orang yang paling waras. Senyum yang te- +lah terkunci selama delapan tahun dalam mulutnya, tiba-tiba +melompat-lompat keluar macam anak-anak tupai berlomba +keluar dari liangnya. + + Tak lagi tampak lelaki linglung hilir mudik macam orang +hilang uang di kawasan pasar ikan karena Sabari sudah pu- +lang, mencukur rambut, jenggot, dan kumisnya, mandi dan +menggosok gigi. Seperti JonPijareli yang merasa terlahir kem- +bali setelah kedatangan Tamat dan Ukun, Sabari pun terlahir +kembali gara-gara surat Tamat. + + Bertahun-tahun Sabari telah meninggalkan rumahnya +karena dia tak tahan akan kenangan di rumah itu. Kini dia +kembali. + Ayah ~ 347 + + Diamatinya pekarangan, rumput berlomba tinggi de- +ngan ilalang. Pohon delima, yang di bawahnya dulu Zorro, +Abu Meong, dan Marleni senang bermain, telah tumbuh +tinggi. Ayunan yang dibuat Sabari untuk Zorro dan ditautkan +di dahan delima itu talinya telah putus, terkulai menyedihkan. + + Pohon gayam di belakang rumah pasti sudah didiami +bangsa-bangsa hantu. Atap rumah telah menjadi sarang- +sarang burung kinantan, tokek dan cicak berebut kuasa. Siku- +siku tiang didiami tupai. Beberapa ekor bengkarung gendut +pasti suka menggunakan rumah yang diabaikan itu untuk satu +pesta yang tak senonoh. Mendengar langkah Sabari di be- +randa, berhamburan mereka dari dalam rumah, menyusup di +bawah pintu dan meloncat melalui celah jendela. Hewan itu, +elok rupanya, cabul jiwanya. + + Senang tak terkira Sabari bertemu kembali dengan +radion­ya yang telah berdebu. Yang pertama dilakukannya +adalah berutang batu baterai di warung tetangga. Radio itu +masih berfungsi dengan baik. Siang itu pas siaran musik pele- +pas lelah. Lagu dangdut berdenyut-denyut. Sabari memutar +tombol volume sehingga kandas, lalu semua hal, dia sendiri, +radio itu, hewan-hewan, termasuk rumah reyotnya, seolah +bergoyang-goyang. + + Diiringi dentum musik, Sabari membetulkan atap. Te- +lur-telur burung kinantan yang belum menetas, beserta sa- +rangnya, dipindahkannya ke pohon delima. Rumput yang +tinggi dibabat. Dinding papan yang terlepas dipaku kembali. +Sepeda yang telah lama tersandar merana, diperbaiki. + 348 ~ Andrea Hirata + + Sabari dilanda perasaan senang yang tak mampu dilu- +kiskannya dengan kata-kata ketika membereskan tempat ti- +dur Zorro. Diciuminya bantal dan selimut yang dulu dipakai +anaknya itu. + + Segala hal disapu, dibersihkan, disikat. Rumah yang di- +tinggalkan, lalu dikuasai hewan liar, kini didudukinya kem- +bali. Jika lelah, dibacanya lagi surat Tamat itu, semangatnya +meletup lagi. + + Telah lama Sabari tak duduk sendiri di bangku di beran- +da rumahnya. Satu hal yang dulu sering dilakukannya untuk +merenungkan nasib. Malam itu dia duduk di situ. Abu Meong +berbaring malas di pangkuannya. Bahkan, malas untuk seka- +dar mengibaskan ekor. Nun di balik padang ilalang di depan +sana, Sabari melihat purnama telah bangkit. + + Malam beranjak lambat dan langit semakin terang. Be- +gitu terang sehingga Sabari dapat melihat tulisan Tamat di +surat itu, yang telah dihafalnya, kata demi kata, semua titik +dan komanya. Sabari tak tahu drama apa lagi yang akan me- +landanya, tetapi anaknya akan segera pulang. Sabari tak da- +pat menggambarkan perasaannya. + + Di pasar, Sabari minta pekerjaan apa saja dari siapa saja. +Kuli panggul hanya memanggul sekarung terigu, dia sanggup +dua karung. Dia membersihkan perahu, mengangkat peti es, +mendorong gerobak, memikul sayur-mayur, membantu ibu- +ibu berbelanja. Dia bekerja seperti tak ada lagi hari esok kare- +na dia punya rencana yang manis. + Ayah ~ 349 + + Setelah seminggu bekerja habis-habisan, Sabari berha- +sil mengumpulkan sejumlah uang. Sabtu pagi itu dia ngebut +bersepeda ke ibu kota kabupaten untuk melaksanakan renca- +nanya. + + Di dalam toko anak-anak, jantungnya berdebar mem- +baca daftar panjang barang-barang yang ingin dibelinya: tas +punggung, botol air minum, topi rajutan, kaus kaki, dan sa- +rung tangan berenda. Topi dibelinya dua sebab dalam pikir- +annya dia akan sering mengajak Zorro naik sepeda. Dia juga +membeli sandal, sepatu, berbagai mainan, celana, dan baju +yang semuanya berukuran kecil. Tak sedikit pun dia terpikir +bahwa Zorro sudah besar. + + Usai berbelanja, sambil bersiul-siul dia bersepeda me- +nuju kawasan tempat banyak restoran dan tenda penjaja ma- +kanan. Terus terang saja disampaikan kepada orang-orang di +restoran itu bahwa jika boleh dia mau meminta daftar me- +nunya sebab anaknya senang dininabobokan dengan cerita +tentang makanan. + + Orang-orang itu mulanya merasa heran, tetapi siapakah +yang dapat menolak permintaan seorang ayah demi anaknya? +Sabari takjub mendapat daftar menu yang unik zaman seka- +rang, misalnya pempek kapal tanker, bakso rudal ulang-alik, +nasi goreng dunia akhirat, pecel lele bus kota, lemper tanpa +dosa, es teh antartika, dan sambal api neraka. Sabari melon- +jak membayangkan serunya kisah yang akan diceritakannya +kepada Zorro nanti. + 350 ~ Andrea Hirata + + Setiap malam Sabari menyusun barang-barang untuk +Zorro dan daftar menu itu. Disusunnya dengan rapi di atas +meja rotan di samping tempat tidur Zorro. Adakalanya telah +rapi, dibongkarnya kembali, lalu disusunnya lagi, sambil ter- +senyum-senyum sendiri. + + Akan tetapi, tak ayal, di balik euforia yang tak tertang- +gungkan itu, Sabari merasa pahit memikirkan seandainya ka- +pal kayu itu tak jadi merapat. Dua hari sekali dia bertanya +kepada pegawai kantor syahbandar. Kalau bukan lantaran +pegawai itu telah mengenal Sabari dan tahu apa yang telah +dilalui lelaki malang itu, dan bahwa dia sedang menunggu +anaknya, dia takkan bersabar ditanyai dan menjawab hal +yang sama berulang-ulang. + + “Begitu menurut jadwal, Pak Cik, tapi Pak Cik tahu sen- +diri, musim selatan begini, bisa saja berubah. Bisa saja kapal +berteduh dulu di Kayu Arang atau menunda pelayaran dari +Dabo.” Dia bicara apa adanya karena tak mau memberi ha- +rapan palsu. + + Sabari menunduk dalam. + “Janganlah cemas, Pak Cik. Anak Pak Cik pasti pulang.” + Dua hari kemudian, Sabari datang lagi. + Piala + +TERSENYUM-SENYUM Sabari melihat pengumuman +yang tertempel di warung kopi bahwa akan ada lomba mara- +ton dalam rangka perayaan kemerdekaan. Seseorang terbetik +dalam kalbunya, Zorro, dia mau ikut lomba. + + Mulailah dia berlatih. Saban subuh dia berlari, sepan- +jang hari dia bekerja membanting tulang, sore dia berlari +lagi, malamnya dia mengarang puisi dan kisah-kisah untuk +menyambut anaknya nanti. Sabari menemukan irama hidup +yang menarik. + + Orang-orang masih ingat prestasi fenomenal Sabari +dulu, waktu dia menjadi juara maraton, menumbangkan Di- +namut, sang juara bertahan, yang dicurigai orang punya ilmu +pelanduk. Di warung-warung kopi ramai orang membicara- +kan come back-nya Sabari. Kekisruhan asmara dan prahara ru- +mah tangga yang berlarut-larut membuatnya gantung sepatu +sekian lama, akhirnya dia kembali. + 352 ~ Andrea Hirata + + Telinga Dinamut berdiri. Dia telah bertarung dengan +banyak pelari, tetapi kesumatnya adalah Sabari. Ditingkat- +kannya latihan tiga kali lebih keras daripada biasanya. Sabari +tahu Dinamut mau menggulungnya. Sabari gugup. Tak ada +pilihan lain selain berlatih keras juga. + + Waktu itu, seperti biasa, Sabari duduk di bawah pohon +kersen, di depan kios pangkas rambut Darmawan, lokasi ter- +hormat tempat para kuli serabutan selalu berkumpul sambil +memegang sabit, palu, pacul, linggis, atau sekop. Di situlah +mereka menunggu juragan toko memanggil untuk meng- +angkat ini-itu, menunggu ibu rumah tangga minta bantuan +memanggul segunung belanjaan, menunggu sopir mobil pi- +kap mengajak dua atau tiga kuli untuk merobohkan rumah +tua atau membabat rumput. Adakalanya seorang berpakaian +rapi, bermulut manis, bermata licik mengajak semua kuli, un- +tuk berdemo. Upahnya lebih bagus daripada menggali sumur. + + “Jangan menoleh!” Orang itu membentak. + Sabari terkejut melihat seseorang di belakangnya, me- +munggunginya. Sepintas tampak orang itu tinggi besar seperti +Arnold Swasanaseger dalam film Terminator. Lehernya seperti +pohon kelapa. Lengannya berbongkah-bongkah macam batu +granit di Pantai Tanjong Tinggi. + “Kataku jangan menoleh!” + Sabari ketakutan. + “Saya tak pernah ikut demo, Pak.” + “Benar kamu tak pernah ikut demo?!” + Ayah ~ 353 + + “Ya, Pak.” + “Dusta!” + “Tidak, Pak.” + “Tadi kau bilang ya, sekarang kau bilang tidak, omong +kosong!” + Sabari bingung. + “Jadi, sebenarnya ya apa tidak?!” + Sabari gemetar. + “Masih ingat suara saya?!” + Sabari mencoba mengingat. + “Coba berkata lagi.” + “Masih ingat suara saya?!” + “Kurang banyak.” + “Maksudnya?!” + “Bapak bicara kurang banyak, jadi susah saya mengi- +ngatnya.” + Tak lama kemudian terdengar nyanyian lagu India yang +lembut mendayu-dayu. Sabari terlempar ke masa lampau, +masa SMA. Dia ingat seorang sahabat yang gemar menya- +nyikan lagu itu. Sabari menoleh, orang tegap itu tersenyum +lebar. + “Toharun!” + Senyum Toharun makin lebar. + “Lama sekali tak berjumpa, Kawan.” Toharun memeluk +Sabari. + Sabari merasa seakan-akan tulang-tulangnya patah. + 354 ~ Andrea Hirata + + “Apa kabarmu, Boi?” + Mereka takjub bisa berjumpa kembali. Setor-setor cerita +rupanya selama ini Toharun berada di Karimun, mengajar +Olahraga di sebuah MTs. + “Jadi, cita-cita kau mau menjadi Menteri Olahraga su- +dah gagal, Boi?” + Toharun mengangguk. + “Tapi, tentu kau senang mengajar Olahraga karena me- +mang itu hobimu, bukan?” + “Pekerjaan terbaik seluruh dunia ini, Boi. Aku pindah +lagi ke Belitong sekarang, mau bekerja dan menetap di Be- +lantik saja. Ingin mengajar Olahraga di sekolah atau menjadi +pelatih.” + “Sudah berkeluargakah?” + “Tentu.” + Lalu, terdengar anak-anak kecil memanggil-manggil, +Ayah, Ayah, dan dari dalam kios pangkas rambut itu berlarian +tiga anak lelaki ke arah Toharun dengan potongan rambut +sama dengan potongan rambut ayah mereka. Mereka pun te- +gap-tegap seperti ayahnya. + “Tiga laki-laki, Boi. Kau, bagaimana, Kawan? Apakah +sudah punya anak?” + Sabari tersenyum bangga. + “Sebentar lagi, Run, sebentar lagi aku punya anak lagi.” + Sabari berkunjung ke rumah Toharun dan terkagum- +kagum melihat berbagai piagam penghargaan dan piala yang + Ayah ~ 355 + +pernah diraih raskal 4 itu. Dia bahkan pernah ikut PON me- +wakili Provinsi Sumatra Selatan untuk cabang jalan cepat. + + Rupanya Toharun telah menelaah bentuk-bentuk latih- +an keras yang dilakukan Dinamut. + + “Jangan cemas. Aku akan melatihmu, Boi. Kau akan ku- +buat tangguh macam pelari dari Kenya.” + + Sabari senang bukan buatan karena menemukan pela- +tih. Disalaminya Toharun kuat-kuat. Sejak itu tiap hari Sabari +kena gencet Toharun. + +“Hebat! Kau lebih cepat daripada musang yang paling sehat +sekalipun!” kata Toharun menyemangati Sabari yang ngos- +ngosan. Setelah seminggu ditekan Toharun habis-habisan, +catatan waktu Sabari cukup memuaskan. + + “Tapi, kalau mau mengalahkan Dinamut, dan menja- +di juara, harus lebih cepat lagi.” Toharun memencet-mencet +tombol stopwatch. “Kau harus berlatih lebih militan, dua kali +lebih keras daripada Dinamut!” + + Sementara di situ, Sabari berusaha mengumpul-ngum- +pulkan nyawanya. + + Diam-diam Toharun sering mengintip Dinamut ber- +latih. Dilihatnya Dinamut berlatih di dermaga, berlari sam- +bil menyeret tiga ban truk bekas yang diikat dengan tali di +pinggang. Toharun menyuruh Sabari berlari sambil menyeret +truk. + 356 ~ Andrea Hirata + + Dinamut menyeret kursi, Sabari menyeret meja. Dina- +mut menyeret meja, Sabari menyeret lemari. Dinamut me- +nyeret setandan pisang, Sabari menyeret batang pisang. Di- +namut menyeret gerobak bakso, Sabari menyeret gerobak +pemulung besi. + + Dinamut berlari sambil menggendong kambing. Meski +tak mampu, Toharun menekan Sabari agar berlari sambil +menggendong sapi, anaknya paling tidak. Dinamut berlari di +pinggir Sungai Lenggang yang banyak ular, Toharun meme- +rintahkan Sabari berlari di pinggir Sungai Buta, yang banyak +buaya, Sabari berlari terpontal-pontal. + + Juru antar surat pengadilan agama sering melihat Sabari +berlari melintasi pasar. Dia masih mengenali Sabari. Sore itu +Sabari beristirahat di jembatan setelah digojlok Toharun ber- +lari mengelilingi pasar tujuh kali. Juru antar menghampirinya. + + “Tentu Bung masih ingat denganku,” sapa juru antar +sambil menjulurkan tangan. + + Sabari menyalaminya, berusaha mengingat wajah yang +ramah itu. + + Bertahun-tahun hidup dalam kekalutan, saraf-saraf +ingatan Sabari sempat kusut. Wajah di depannya pernah +hinggap dalam kepalanya, kini dia lupa. Namun, ingatan Sa- +bari pulih melihat sepeda motor bebek tua Yamaha V-80 itu. +Sebab, tak ada lagi orang yang memakai motor seperti itu. +Beberapa bagian motor yang dicat sendiri dengan cat kuda +terbang juga tak gampang dilupakan. + Ayah ~ 357 + + Sabari tersenyum. Semuanya jelas, orang itulah dulu +yang pernah bertanya kepadanya soal gratifikasi, hukum per- +tama Tuan Newton. + + “Semua benda akan jatuh karena daya tarik bumi,” kata +Sabari. + + Mereka tertawa, lalu terurai-urailah obrolan demi obrol­ +an, sampai pada soal lomba maraton. + + “Aku ingin menjadi juara pertama, Pak,” kata Sabari +dengan tenang, tetapi suaranya mengandung tenaga dalam. + + “Aku ingin mendapat piala, piala itu akan kupersembah- +kan untuk anakku, Zorro.” + + Juru antar terharu. Dia tahu apa yang telah dialami Sa- +bari. Baginya, piala itu adalah persembahan yang indah dari +seorang ayah untuk anaknya. + +Sungguh kejam latihan dari Toharun, tetapi nyata kemajuan +yang dirasakan Sabari. Maka, dia tak pernah mengeluh, lagi +pula piala maraton itu begitu manis untuk menjadi hadiah +selamat datang bagi anaknya nanti. Karena latihan super- +keras itu, Sabari semakin yakin dia akan menggondol juara +pertama. Penat tubuhnya lenyap jika Sabari membayangkan +menyerahkan piala itu kepada Zorro di pelabuhan nanti. + + Malam itu Sabari melamun di beranda. Senyap. Daun- +daun delima gemeresik ditiup angin. Kian hari angin semakin + 358 ~ Andrea Hirata + +kencang karena musim selatan hampir sempurna. Musim se- +latan yang indah. Sabari ingat, masa kecil dulu, dia, Tamat, +dan Ukun selalu menunggu musim selatan. Karena itulah +waktu mereka bermain layangan, berlari bebas di lapangan. + + Akan tetapi, Sabari sedih karena teringat bahwa mereka +tak bisa membeli layangan atau tak mampu membeli bahan- +bahan untuk membuat layangan maka mereka menunggu +putusnya layangan yang dimainkan anak-anak lain di lapang- +an bola. Mereka menunggu di padang ilalang di utara karena +angin selatan berarti angin yang bertiup dari selatan. Hanya +dengan cara itu mereka bisa bermain layangan. Dan, kini Sa- +bari semakin sedih sebab angin kencang musim selatan selalu +membuat kapal tak berlayar, akankah 7 September nanti dia +berjumpa dengan Zorro? Dada Sabari sesak. + + Dalam kesenyapan yang pedih dan keputusasaan yang +menikam itu, nun di kejauhan Sabari mendengar kucing me- +ngeong sayup-sayup sampai. Abu Meong yang sedang tidur- +tiduran di tungku terbuka matanya. Suara kucing yang semu- +la kecil dan jauh semakin jelas karena terbawa angin. Telinga +Abu Meong berdiri. Sabari memandang ke arah suara kucing +itu. Tak lama kemudian dia terkejut melihat seekor kucing +berjalan memasuki pekarangan rumah. Kucing itu menge- +ong-ngeong lagi. Abu Meong meloncat dari tungku, lalu ber- +lari menuju beranda, di ambang pintu ia terpaku melihat ku- +cing yang baru datang itu. Sabari pun berlari menyongsong +kucing itu. + Ayah ~ 359 + + “Marleniii, oh, Marleniii .... Dari mana saja kau, Boi?” + Marleni yang telah hilang selama delapan tahun akhir- +nya pulang. Betina itu mengibas-ngibaskan ekornya dengan +manja, mata lendut tanpa dosanya mendelik-delik genit. Mau +pingsan Abu Meong dibuatnya. + Merdeka + +AKHIRNYA, perlombaan maraton yang ditunggu-tunggu +itu tiba. Ramai orang di halaman MPB (Markas Pertemuan +Buruh), di sanalah garis start. Garis finis di taman balai kota, +di ibu kota kabupaten. Jarak kedua garis terpisah hampir em- +pat puluh kilometer, sesuai jarak umum perlombaan maraton +yang ditetapkan PBB. + + Lomba lari adalah olahraga paling asyik dan paling me- +rakyat. Tidak seperti perlombaan lain yang cerewet aturan, +perlombaan lari bersifat praktis, adil, sederhana, langsung, +umum, bebas, tanpa rahasia. Inilah satu-satunya lomba yang +semua pesertanya langsung masuk final. Usia, tak terbatas. +Anak yang baru bisa berjalan, taruhlah sebelas bulan, sila +ikut. Orang tua yang sudah susah berjalan, takkan dilarang +untuk mendaftar. + + Pakaian, bebas merdeka. Boleh pakai sarung, boleh pa- +kai piama, boleh pakai kostum badut, atau seragam kerja. + Ayah ~ 361 + +Seandainya mampu menanggung malu dan siap berurusan +dengan penegak hukum, mau tidak berpakaian juga boleh. + + Mau pakai sepatu atau tidak, itu urusan rumah tangga +peserta, panitia takkan ikut campur. Yang penting berlari se- +telah bunyi tembakan pistol palsu, lalu berlarilah kau sekuat +jiwa dan ragamu. Mau berlari tanpa mengikuti jalan yang di- +tentukan panitia juga boleh, asal bersedia tidak diberi hadiah +seandainya menang. Lomba lari memperingati Hari Kemer- +dekaan adalah ekspresi paling manis dari kemerdekaan itu +sendiri. + + Maka, berbondong-bondonglah keluarga bahagia atau +berpura-pura bahagia ikut lomba lari itu. Ini hiburan sambil +gerak badan. Banyak badut dan orang berkostum aneh-aneh. +Mereka adalah pelari tanpa nomor peserta, yang setelah satu +atau dua kilometer akan berubah menjadi pejalan kaki. Tak +soal, semua gembira merayakan kemerdekaan. Bendera me- +rah putih berkibar di mana-mana. Meriah. + + Tak terhitung banyaknya pelari amatir dengan misi yang +mulia, yakni menyelesaikan lomba. Mereka sadar bahwa +mustahil jadi juara, tekad mereka hanya menaklukkan garis +finis, untuk menaklukkan mereka sendiri sesungguhnya. Se- +perti Pendidikan Moral Pancasila di sekolah, lomba lari juga +pembentuk karakter. + + Bagian yang mendebarkan adalah para pelari sesungguhnya +yang memang datang ke arena untuk melipat satu sama lain, +dengan satu tujuan, dan satu tujuan saja, yaitu meraih piala + 362 ~ Andrea Hirata + +megah berkilauan, empat tingkat, berpita merah putih, men- +julang macam Menara Eiffel. Itulah lambang supremasi olah- +ragawan Melayu. Pemenangnya, tak peduli siapa dia, pemu- +lung, geladangan, atau bramacorah, akan menjadi anak emas +kebanggaan kampung. Akan menjadi atlet mewakili Kabupa- +ten Belitong ke tingkat provinsi. Bisa petantang-petenteng ke +sana kemari dengan baju training bertulisan kontingen provinsi di +punggungnya. Jika dipakai menonton organ tunggal, dijamin +gampang dapat kenalan. Di antara mereka bercokollah Dina- +mut dan Sabari, dua musuh bebuyutan, seteru lama. + + Nomor peserta tergantung di leher mereka. Cara pema- +nasannya saja mendebarkan. Tak sekadar memutar-mutar +batang leher seperti orang-orang awam itu, mereka melaku- +kan lari di tempat secara cepat. Mereka berdesak-desakan di +bibir garis start dengan wajah serius. Tak seperti pelari pe- +lengkap penghibur tadi, cengengesan saja. + + Asap persaingan mengepul tebal. Setiap tahun jumlah +pelari sesungguhnya itu selalu meningkat. Pelari muda yang tang- +guh terus bermunculan. Tahun ini ratusan jumlahnya, jumlah +terbesar yang pernah tercatat. Tak sabar mereka ingin men- +jajal tenaga dan teknik berlari dalam jarak yang menciutkan +nyali. + + Ribuan orang hiruk pikuk. Suitan dan tepuk tangan +membahana menyambut teriakan komentator lomba yang +bertengger di anjungan nan tinggi, dikelilingi speaker TOA +yang mengarah ke empat penjuru angin. Dia mengumumkan + Ayah ~ 363 + +jadwal lomba, pesan-pesan sponsor, anak kecil yang terlepas +dari orangtua, dan nama-nama besar pelari maraton kebang- +gaan kabupaten. + + Setiap kali nama disebut, orang-orang bersorak-sorai, +terutama nama para pelari yang diunggulkan. + + “Juara bertahan kita, pelari kawakan tiada banding, Di- +namuuuttt ....” Gegap gempita tepuk tangan. + + “Pelari yang telah lama hilang tak tahu rimbanya, akhir- +nya kembali, Sabariiiiii ....” Gempar, hanya satu kata itu yang +dapat melukiskannya. Lebih gempar daripada sambutan ke- +pada Dinamut tadi. + + Dinamut menatap Sabari dengan tajam. Halilintar me- +nyambar-nyambar dalam kepalanya. + + Salah seorang penonton yang bertepuk tangan paling +keras saat nama Sabari disebut adalah juru antar surat dari +pengadilan agama. + + “Bung! Bung!” panggilnya dari pinggir jalan. + Sabari menghampirinya. + “Kutunggu Bung di garis finis!” Ditunjukkannya radio +kecil, melalui siaran radio lokal dia akan mengikuti lomba itu. +“Doaku selalu bersama Bung!” + Juru antar telah melihat kerasnya latihan Sabari di ba- +wah gemblengan Toharun. Sedikit pun dia tak ragu Sabari +akan menggondol gelar juara dan meraih piala untuk anak- +nya. + “Aku orang pertama yang akan menyalami Bung di garis +finis nanti! Kutunggu Bung di sana!” + 364 ~ Andrea Hirata + + Sabari tersenyum lebar sambil mengacungkan jempol +kepada penggemar terbesarnya itu. Juru antar bergegas ke +tempat parkir. Setelah dua belas kali diengkol, mesin motor- +nya hidup. Dia memelesat ke taman balai kota. + + Semua kegaduhan di stadion didengar Zuraida melalui +radio lokal sambil menyetrika pakaian. Dibesarkannya vo- +lume radio sebab suara penyiar, live dari lokasi start lomba, +tenggelam dalam sorak-sorai penonton, jerit anak-anak, bu- +nyi mainan, teriakan panitia melalui megafon, sempritan pe- +luit polisi menertibkan penonton, dan lagu keras di sela-sela +suara komentator. Zurai membayangkan betapa ramainya +suasana. Dia ingin ke sana, tetapi banyak pakaian yang harus +disetrika dan piring kotor yang harus dicuci. + + Izmi pun ingin ke lokasi start, tetapi banyak pesanan ja- +hitan yang harus diselesaikan. Dia juga mendengar semuanya +melalui radio yang diletakkan di atas mesin jahit. Waktu ko- +mentator menyebut nama Sabari, dia membekapkan tangan- +nya di dada dan dia terkejut mendengar bunyi letupan pistol. + + Berhamburanlah ribuan pelari, persis pedagang kaki +lima diuber polisi pamong praja. Penonton bersorak gegap +gempita sambil mengibarkan bendera merah putih. Para pe- +lari berebut mengambil posisi terdepan. Jumlah mereka yang +banyak membuat mereka beradu siku. + + Pada saat bersamaan, nun jauh di Medan, 1.200 kilome- +ter terpisah dari Pulau Belitong, JonPijareli dan band-nya siap +merekam lagu andalan mereka, “Aku Berlari”. Delapan be- + Ayah ~ 365 + +las tahun mereka telah menunggu kesempatan itu. Kris Dep +menghajar drum dengan hantaman 4/4 dan tempo paling ti- +dak 200 beat per minute, satu entakan rock masa kini yang cepat +dan keras minta ampun. Dengan satu gerakan tangkas Jon +menyambar mik lalu melolong aku berlariiiiii, aku berlariii, aku +berlariiiiii .... Suaranya lantang mengiringi ribuan pelari yang +berhamburan di Belitong. + + Sesuai arahan Toharun, Sabari harus menahan diri. +Tidak perlu terlalu bernafsu seperti rombongan besar para +pelari kemarin sore yang tak berpengalaman itu. Ini lari jarak +jauh, Bung! + + “Ingat, Ri!” pesan Toharun. “Jarak tempuh empat puluh +kilometer. Sepuluh kilometer pertama, cukuplah kau berada +di rombongan ketiga dari terdepan. Sepuluh kilometer kedua, +masuk rombongan kedua. Sepuluh kilometer ketiga, masuk +rombongan pertama. Berarti sisa tujuh setengah kilometer. +Dua setengah kilometer berikutnya kau paling tidak di urut- +an kedelapan dalam rombongan pertama itu. Satu koma dua +kilometer berikutnya kau harus menduduki urutan keenam. +Satu koma empat kilometer selanjutnya, urutan keempat. +Sisanya ....” Toharun pusing sendiri. “Pandai-pandai kaulah +membaginya, yang penting kau juara!” + + “Baiklah, Run.” + Sabari berlari dengan konsisten menjaga petuah pela- +tih. Kendaraan polisi pengawal lomba sesekali melolongkan +sirene. Sepanjang jalan orang-orang bertepuk tangan sambil + 366 ~ Andrea Hirata + +meneriakkan nama Sabari. Dia adalah pelari jempolan yang +baru come back dan masih punya penggemar sisa kejayaan +masa lampau. Sabari tak membalas sapa para penggemar- +nya, tidak pula tersenyum sebab kata Toharun tersenyum da- +pat memboroskan tenaga secara percuma. Dielu-elukan pe- +nonton, langkah Sabari menjadi ringan. Dia berlari dengan +semangat Spartan. Ah, seandainya Zorro ada di sini! + + Pertarungan di rombongan ketiga sangat ketat karena +Dinamut ada pula di sana. Sabari terus-menerus diintainya +dengan dada penuh kesumat. Bulat tekadnya untuk memper- +malukan Sabari sore ini dan mengembalikan harga dirinya +yang telah porak-poranda selama bertahun-tahun. + + Toharun bersepeda mengikuti Sabari dari sisi jalan. Se- +sekali dia memberi instruksi kepada anak didiknya. + + “Satu napas setiap empat langkah, Boi!” + Tak tahu dari mana Toharun mendapat teori aneh itu. +Teori itu gampang diucapkan, tetapi amat susah dilaksana- +kan. Risikonya tinggi. Jika salah menghitungnya, nyawa bisa +melayang. Sabari berusaha menaati perintah gurunya. + Akibatnya memang manjur, sepuluh kilometer pertama, +Sabari unggul di rombongan ketiga, meski di sana bercokol +seluruh pelari kelas satu, termasuk Dinamut. Masuk sepuluh +kilometer kedua, pelari tak berpengalaman yang tadi terlalu +bernafsu mulai rontok dan para pelari pelengkap penghibur +sudah tak tampak batang hidungnya. + Penyiar radio yang mengikuti pelari dan memberi lapor- +an pandangan mata dari bak mobil pikap berseru-seru me- + Ayah ~ 367 + +lihat para pelari di rombongan kedua melakukan semacam +sprint, yakni berlari cepat dalam jarak pendek untuk meraih +posisi terdepan. Yang membuat penyiar tegang adalah dalam +sprint itu Dinamut bersikut-sikutan dengan Sabari. Satu per- +saingan ketat penuh bara api. Penyiar berteriak lagi karena +Sabari berhasil memenangi sprint itu dan langsung memim- +pin rombongan kedua. + + Zurai melompat dari tempat duduk. Izmi mengangkat +kedua tangannya tinggi-tinggi, begitu pula juru antar yang +tengah menunggu Sabari di garis finis. Tak hanya mereka, +orang-orang yang mendengar radio di rumah-rumah, di pe- +rahu-perahu sambil memancing, di bengkel-bengkel perusa- +haan timah, orang-orang yang nongkrong di muka rumah +dan perempatan, manusia tak tahu adat yang lagi pacaran +di seberang Bendungan Pice dan membawa radio, para sipir +penjara, pasien, dokter dan perawat di rumah sakit, tukang +sortir di kantor pos, satpam-satpam, pedagang makanan pa- +kai gerobak, dan terutama orang-orang di warung-warung +kopi, bersorak gegap gempita untuk Sabari. Yang menjago- +kan Dinamut menutup wajah mereka dengan tangan. + + Sabari semakin mantap. Dia telah menemukan irama +langkahnya, mencapai akselerasinya dan berlari laksana ki- +jang, mirip lirik lagu yang dilantakkan JonPijareli nun di Me- +dan sana, dalam gemuruh distorsi gitar rock, dentaman drum +yang bertalu-talu, dan tendangan bas bertubi-tubi. Boros +Akinmusire berjingkrak-jingkrak, Obet Glasper dan JonPija- +reli serentak bersorak. + 368 ~ Andrea Hirata + + Bagaikan seekor kijang + Aku berlari di tengah padang + Tak ada yang dapat mengadang + Halangan akan kuterjang + Aku berlari kencang + Berlari kencang sehingga aku terbang + Aku berlari kencang, aku terbang + + Dinamut panas hati, panas kepala. Digenjotnya tunjang- +an kaki dan melejitlah dia melewati Sabari. Para pendukung- +nya di warung-warung kopi bersorak macam orang dirasuki +setan. Giliran pendukung Sabari tersenyum pahit. Tentu tokoh +kita tidak membiarkan begitu saja perbuatan Dinamut yang +kurang ajar itu. Dia juga menggenjot tungkainya, tetapi seperti +diungkapkan dengan agak histeris oleh penyiar radio, Sabari +gagal mendapatkan momentum dan tersuruk ke belakang. + + Sejurus kemudian Sabari bingung melihat bayangan- +bayangan berkelebat dengan cepat di sisi kiri-kanannya. De- +tik berikutnya dia mendapati dirinya telah dilewati oleh lima, +bahkan mungkin sepuluh pelari. Zuraida, Izmi, dan juru an- +tar tercengang dekat radio. + + Begitu cepat semuanya berubah, tahu-tahu penyiar me- +ngabarkan bahwa Sabari telah berada di posisi buntut rom- +bongan kedua. Toharun berteriak-teriak tak keruan. Sabari +mencoba menambah akselerasi, tetapi gagal. Dilihatnya Di- +namut dan pelari lainnya telah jauh di depan. + Ayah ~ 369 + + Selanjutnya, tak terdengar lagi penyiar radio menyebut +nama Sabari. Nama Dinamut dan pelari lain menguar di ra- +dio. Pendukung Dinamut berjingkrak-jingkrak. Zuraida ter- +henyak di tempat duduk. Izmi tersandar pasrah. Juru antar +mengecilkan volume radio dan mengantonginya. Para peng- +gemar Sabari di berbagai kantor dan tempat tadi termangu. +Mereka menunggu penyiar menyebut lagi nama Sabari, hal +itu tak pernah terjadi. + + Sabari sadar bahwa persaingan yang amat ketat menga- +kibatkan lajunya tak seimbang sejak start. Dia terlalu cepat di +awal dan bahwa strateginya hanya cocok untuk lari berjarak +paling jauh dua puluh kilometer. Dan, bahwa maraton disedi- +akan nasib untuk mereka yang muda dan punya nyawa berla- +pis-lapis. Dan, bahwa dunia sudah banyak berubah. Dia terla- +lu terfokus kepada Dinamut, padahal pelari muda jauh lebih +dahsyat. Gizi mereka lebih baik, dan bahwa mereka yang di- +besarkan dengan diminumi air tajin saja, tidaklah akan banyak +peluangnya dalam dunia yang edan ini. Masih tersisa belasan +kilometer, Sabari tak yakin dapat menyelesaikannya. + + Satu per satu pelari mengundurkan diri. Mereka ming- +gir, lalu terbaring lelah di pinggir jalan. Maraton adalah olah- +raga yang memerlukan stamina luar biasa dan tekad baja pu- +tih. Hanya atlet-atlet bermental besi yang mampu menggapai +finis. Matahari sore yang masih panas mencabik-cabik para +pelari. Bayangan kemenangan dan piala menguap dari kepa- +la Sabari. + 370 ~ Andrea Hirata + + Semakin banyak pelari berguguran, termasuk Dinamut. +Dia juga tak sanggup bersaing dengan para pelari muda. Na- +mun, Sabari tetap berlari meski tak secepat tadi. Napasnya +berat. Kakinya sakit karena tadi terlalu dipacu. Mereka yang +melihatnya menduga dia akan segera berhenti, tetapi aneh, +dia tak menyerah. Akhirnya, Sabari tak melihat lagi pelari di +depannya. Para penonton di pinggir jalan juga semakin sedi- +kit. + + “Sudahlah, Boi, berhenti saja!” perintah Toharun dari +atas sepeda. + + Sabari membelot dari perintah pelatihnya itu. Dia tetap +berlari, sendirian dan menyedihkan. + + Suasana amat berbeda di taman balai kota. Ribuan pe- +nonton bersorak-sorai menyambut enam pelari terakhir yang +berbelok anggun di belokan sebelum memasuki jalur menuju +gerbang taman balai kota. Juru antar sedih karena tak melihat +Sabari di antara enam pelari calon juara itu. + + Suara gaduh mencapai puncaknya saat seorang pelari +yang bertubuh tinggi, atletis, dan masih sangat muda mene- +rabas pita di garis finis. Dialah si kijang itu. Diangkatnya piala +empat tingkat itu tinggi-tinggi, berkilauan. + + Secepat orang-orang berkumpul di taman balai kota un- +tuk menyaksikan para juara, secepat itu pula mereka menghi- +lang. Dalam sekejap taman balai kota menjadi sepi. + + Juru antar tetap menunggu. Matanya lekat menatap be- +lokan tadi. Masih diharapnya Sabari berbelok di situ. Meski +jauh tertinggal, Sabari akan disambutnya bak seorang juara. + Ayah ~ 371 + +Akan disalaminya dengan kuat sesuai janjinya di garis start +tadi. Namun, hampir satu jam dia menunggu, Sabari tak kun- +jung muncul. Belokan itu kosong melompong seperti perasa- +an juru antar. + + Dengan lesu juru antar berjalan ke tempat parkir. Di- +engkolnya motor bututnya. Karena sudah kebiasaan, dia se- +ring bertaruh dengan motornya sendiri, berapa kali motor- +nya diengkol baru hidup. Setelah diengkol delapan belas kali, +motor tua itu hidup. Dia sedih bukan hanya karena Sabari +tak mampu mencapai finis, melainkan juga karena kalah ber- +taruh dengan motornya. Tadi dia memasang angka delapan +kali engkol, motornya bilang di atas itu. Motor menang. + + Juru antar pulang melewati Jalan Sriwijaya, Tanjong +Pandan. Tak ada lagi harapan untuk Sabari, tetapi dia tak +mematikan radio kecil di saku bajunya. Dia berharap ada ka- +bar lagi soal Sabari meski hal itu mustahil sebab radio pun tak +lagi menyiarkan lomba itu. Yang disiarkan kini adalah prog­ +ram rohani Islam, anak-anak kecil mengaji Al-Quran, acara +rutin menjelang magrib. + + Juru antar melewati jajaran kantor pemerintah. Kantor +DPRD dan kantor bupati, teringat akan Sabari yang bersusah +payah latihan demi mempersembahkan piala untuk anaknya, +lalu dia teringat akan ayahnya sendiri. + + Dulu ayahnya pernah bekerja di kantor semacam itu +dan menjadi orang yang sangat tak disukai karena tak pernah +mau diajak curang. Ayahnya yang jujur malah sering kena + 372 ~ Andrea Hirata + +fitnah. Ayahnya mengundurkan diri, lalu bekerja sebagai tu- +kang reparasi radio dan televisi dari rumah ke rumah. Begitu +miskin sehingga tak mampu punya kios sendiri. Ayahnya su- +dah meninggal. + + Motor juru antar meluncur pelan, sesekali terbatuk- +batuk. Anak kecil mengaji terdengar di radio di sakunya. Dia +teringat selalu mencium tangan ayahnya usai diajari ayahnya +mengaji. Dia rindu ingin mencium tangan ayahnya lagi. + + Tanpa diketahui juru antar, nun belasan kilometer dari +garis finis, Sabari masih terus berlari. + + “Berhenti saja, Ri!” perintah Toharun. “Tak ada guna- +nya lagi!” + + “Oi, mau ke mana kau, Boi? Lomba sudah selesai. Pa- +nitianya saja sudah pulang!” teriak penonton di pinggir jalan, +disambut gelak tawa penonton lainnya. + + “Mengapa kau terus berlari macam orang gila, Ri?” te- +riak orang lainnya disambut gelak tawa lagi. + + Akan tetapi, meski berlari semakin pelan sebab kakinya +semakin sakit, meski diejek-ejek, Sabari menolak untuk ber- +henti. Karena, dia teringat akan anaknya. Yang tak tahan die- +jek malah Toharun. Dibelokkannya sepeda, minggat. + + Matahari masih membara. Sabari memasuki jalan raya +yang panjang seakan tak berujung. Fatamorgana menari-nari +di atas aspal yang panas, mengejek dan mematahkan se- +mangat Sabari untuk berhenti. Sabari tetap berlari. Sepatu +murah yang dipakainya membuat kakinya semakin sakit. Di- +bukanya sepatu, dilemparkannya ke pinggir jalan. Dia tahu + Ayah ~ 373 + +tindakan itu bisa fatal sebab untuk mencapai finis paling tidak +dia masih harus berlari lima belas kilometer. Sabari tak punya +pilihan lain, sepatu itu menggigit kakinya setiap kali dia me- +langkah. + + Kendaraan berlalu-lalang di dekatnya. Ditinggalkan +pelatihnya, ditinggalkan siapa saja, Sabari berlari sendiri. +Orang-orang di pinggir jalan heran melihat seorang pelari +masih tetap melanjutkan lomba. Nomor peserta tergantung di +lehernya. Pastilah dia bukan sembarang pelari. Mereka yang +tak mengenal Sabari bertanya-tanya, siapakah pelari itu? + + Matahari mengendap. Malam menjelang. Telapak kaki +Sabari melepuh, lalu berdarah. Bercak-bercak darah terting- +gal di aspal. Meski kakinya perih dan napasnya tersengal- +sengal, meski sampai finis malam nanti, Sabari bertekad un- +tuk terus berlari karena dia teringat akan anaknya. Dia tak +mau menyerah demi Zorro. Seorang ayah, tak boleh menyerah demi +anaknya, begitu kata hati Sabari. + + Akhirnya, malam turun. Sabari berlari di antara kenda- +raan yang berlalu-lalang. Bayangan Zorro berkelebat-kelebat. +Bayangan saat dia bercerita meninabobokan anaknya, saat +anaknya kali pertama memanggilnya Aya dan saat anaknya +diambil darinya. + + Berjam-jam Sabari berlari tertatih-tatih karena me- +nahan perih kakinya, akhirnya nun jauh di sana dilihatnya +kerlap-kerlip lampu gerbang Kota Tanjong Pandan. Orang- +orang di pinggir jalan semakin banyak memperhatikannya. + 374 ~ Andrea Hirata + + Usai membantu anaknya mengerjakan PR, juru antar +kembali menghidupkan radio. Disimaknya berita tentang tin- +dak pidana korupsi, tiba-tiba penyiar radio lokal memotong +siaran dengan semacam breaking news, yaitu soal seorang pe- +lari maraton yang terus melanjutkan berlari, menolak untuk +menyerah meski lomba sudah selesai dan para juara sudah +ditentukan. Penyiar menyebut nomor peserta pelari itu. Juru +antar terpana. + + “Bung Sabari!” Tanpa ambil tempo, dia bergegas me- +nyambar kunci motor bebeknya. Berita yang sama juga di­ +dengar oleh Izmi. + + Juru antar berdoa agar motornya tidak rewel. Doanya +terkabul, sekali engkol motornya langsung melengking. Dia +ngebut macam orang dikejar iblis. Kecepatannya sangat men- +cemaskan, 25 kilometer per jam. + + Izmi terpana di depan radio. Betapa dia kagum akan +semangat Sabari. Lalu, dia teringat pernah melihat di tele- +visi para juara maraton diselimuti bendera negara. Baginya +Sabari adalah juara. Bergegas dia mengambil bendera, lalu +disambarnya sepeda. + + Di taman balai kota, orang-orang ramai berkumpul ka- +rena kabar tentang pelari yang bertekad menaklukkan garis +finis itu telah menyebar. Radio lokal kembali melakukan si- +aran pandangan mata. Suasana tak kalah meriah dari saat +menunggu juara tadi sore. + Ayah ~ 375 + + Juru antar kembali ke posisi tadi sore tempat dia me- +nunggu Sabari. Matanya tak lepas menatap belokan terakhir +itu dan kali ini dia takkan kecewa. Tak lama kemudian terde- +ngar gemuruh tepuk tangan dan sorak-sorai, lalu muncullah +Sabari berlari terseok-seok di belokan itu. Orang-orang ber- +lari mengikutinya di belakang. Juru antar terpaku melihat Sa- +bari berlari dengan menyeret kaki kirinya yang berdarah, wa- +jahnya pucat, keadaannya compang-camping. Tepuk tangan +tak henti-henti untuk Sabari. Izmi berlari mendekati Sabari +dan menyelimutinya dengan bendera merah putih. Sabari +meliriknya. Dia lelah dan kesakitan, tetapi dia tersenyum. + + Menjelang garis finis, Sabari berlari semakin cepat sam- +bil mengangkat bendera di atas kepalanya. Bendera merah +putih berkibar-kibar. Orang-orang berteriak menyambutnya +Merdeka! Merdeka! + Biru + +JIKA ada orang yang tak menjadi juara, tetapi lebih terkenal +daripada sang juara, orang itu adalah Sabari. Di mana-mana +orang-orang menyalaminya, bahkan seteru lamanya, Dina- +mut, menyalaminya dengan erat. Di warung-warung kopi tak +jeda-jeda Toharun membanggakan Sabari. + + “Juara sejati, anak didikku itu. Juara sejati!” katanya. + Pamor Sabari sebagai kuli serabutan melambung sedi- +kit. Dia tak ambil pusing soal itu. Fokusnya tetap pada ka- +pal kayu dari Pelabuhan Dabo yang akan membawa Zorro +pulang. Semakin dekat dengan Hari H, semakin tak keruan +perasaannya. + Tak lagi memusingkan pegawai kantor syahbandar kare- +na ditanyai pertanyaan yang sama berkali-kali, tiga hari men- +jelang jadwal merapatnya kapal kayu itu, Sabari tak lagi ber- +tanya. Sebab, dia tak sanggup mendengar kabar yang akan +mengecilkan hatinya. + Ayah ~ 377 + + Selama tiga hari itu dia susah tidur. Mau makan tak la- +par, mau minum tak haus. Mau tak makan, lapar, mau tak mi- +num, haus. Mau berjalan, tetapi juga mau duduk saja. Mau +duduk, tetapi mau berjalan. Lelah berbaring, tetapi hanya +bisa tergeletak di atas dipan. + + Adakalanya Sabari merasa Zorro sudah berada di dalam +kamar, lalu dia membaca kisah tentang keluarga langit dan +puisi merayu awan. Begitu dilihatnya tempat tidur itu kosong, +dia menutup wajahnya dengan tangan. Sungguh repot kea- +daannya sehingga para tetangga cemas. Dugaan mereka, jika +kapal itu tak jadi merapat, Sabari mungkin akan lebih gila +daripada orang yang paling gila di dunia ini. + + Sabtu yang mendebarkan, yang seakan telah ditunggu +Sabari seumur hidupnya itu akhirnya tiba. Sabari bangun +lebih pagi daripada makhluk mana pun sebab semalam dia +memang tak bisa tidur. + + Pagi-pagi sekali juru antar datang ke rumah Sabari dan +membawa hadiah yang istimewa, yaitu sebuah piala kecil. Pi- +ala itu dibelinya di pasar. + + “Terima kasih banyak, Pak,” kata Sabari. + “Hanya piala kecil, Bung, tapi bagiku Bung adalah jua- +ra. Bung adalah ayah paling hebat yang pernah kukenal da- +lam hidupku.” + Kapal itu baru akan merapat nanti sore, tetapi sejak +pagi Sabari telah bersiap-siap. Disetrikanya baju dan celana +terbaiknya, disemirnya sepatu. Boncengan dari rotan sudah + 378 ~ Andrea Hirata + +disematkan di setang sepeda. Dulu untuk membonceng Zor- +ro, kini untuk membonceng Abu Meong yang juga akan ikut +menjemput Zorro. Balon-balon gas, yang berwarna sama de- +ngan balon gas yang dipegang Zorro delapan tahun yang lalu, +saat dia dibawa Lena dari taman balai kota, diikat di setang +sepeda. Terakhir, dikalungkannya dua medali penghargaan +karyawan terbaik dari pabrik Markoni. + + Tengah hari, Sabari berangkat ke dermaga dengan me- +nyandang tas plastik berisi piala dan berkalung dua medali. +Abu Meong duduk di keranjang rotan. Tak berhenti menge- +ong karena dia memang paling suka kalau diajak jalan-jalan. +Balon-balon gas berkibar-kibar. Meriah. + + Udara cerah, angin bertiup pelan. Jantung Sabari ber- +dentum setiap kali dia mengayuh sepeda. Tak pernah dia +merasa segugup itu. Dilintasinya padang ilalang yang tengah +berbunga, bak buih di tengah samudra. Namun, nun di langit +barat sana awan gelap mengapung rendah. + + Pegawai kantor syahbandar mengatakan bahwa bisa +saja kapal kayu itu tak merapat jika cuaca buruk. Sabari ce- +mas karena di tengah suhu yang panas itu sesekali berembus +angin yang dingin, berasal dari barat, satu tanda hujan lebat +akan turun, boleh jadi menjadi badai. + + Sabari mengucap seribu doa, dia sangat ingin berjum- +pa dengan anaknya. Awan di barat semakin gelap, semakin +rendah. Dia ingat puisi merayu awan yang pernah diajarkan + Ayah ~ 379 + +ayahnya, disenandungkannya puisi itu pelan-pelan. Ajaib, +perlahan-lahan awan gelap beranjak ke selatan. + + Sabari sampai di pelabuhan. Masih pukul 3.00 sore dan +masih sangat panas. Tegak dia berdiri di samping sepedanya. +Piala telah dikeluarkan dari dalam tas dan dipegangnya de- +ngan gagah. Dia telah gagal mempersembahkan piala besar +juara lomba maraton untuk anaknya, piala kecil itu dianggap- +nya cukup mewakili perasaannya. Dua medali besar, berkilau- +an, tergantung di leher. Balon-balon gas yang terikat di setang +sepeda, berwarna-warni, menyundul-nyundul angin dengan +lucu. Sabari hanya sendiri, sebab, kalaupun jadi, kapal kayu +itu baru akan merapat pukul 5.00 sore nanti. + + Sabari memandang ke arah semenanjung karena jika +ada kapal datang pasti langsung tampak di semenanjung itu. +Keringatnya bercucuran, bajunya basah, dia tak peduli. Dia +tak ingin berteduh. Dia akan berdiri menunggu sampai kapal +itu tiba. Abu Meong juga tetap duduk di boncengan rotan, +memandang ke semenanjung seakan tahu tuannya sedang +menunggu kapal itu. + + Satu jam lebih Sabari menunggu. Dia cemas karena truk +yang biasa datang ke dermaga untuk mengangkut kayu tak +juga muncul. Dia membujuk diri dengan mengatakan kepa- +da dirinya sendiri bahwa mungkin kapal itu tidak membawa +kayu dari Dabo, tetapi akan membawa kayu dari Belitong. +Sehingga, truk-truk itu tak datang. Walau begitu, dia mulai + 380 ~ Andrea Hirata + +dihinggapi perasaan pahit. Kemudian, datanglah beberapa +orang yang sepertinya juga menunggu kapal kayu itu. + + Semakin sore makin banyak orang ke dermaga. Diam- +diam juru antar juga datang. Diparkirnya motor dekat para +tukang ojek di pojok sana. Dari jauh dilihatnya Sabari berdiri +di samping sepeda sambil memegang piala. Dia telah mende- +ngar dari Sabari bahwa dia cemas kapal itu tak merapat. + + Hampir dua jam Sabari berdiri tegak, tak ada tanda-tan- +da kapal akan tiba. Dia lelah karena gugup berkepanjangan, +tetapi dia akan terus menunggu meski sampai malam nanti. +Juru antar sedih melihat harapan besar Sabari yang mungkin +akan terempas lagi sore ini. Dia khawatir membayangkan apa +yang akan terjadi pada lelaki malang itu jika tak berjumpa +dengan anaknya. + + Keadaan semakin menyedihkan karena satu per satu +orang mulai pulang. Juru antar mendengar obrolan yang ter- +lontar dari mereka bahwa kapal itu takkan datang. Dengan +hampa ditatapnya orang-orang yang berjalan meninggalkan +dermaga. Namun, tiba-tiba dia terkejut mendengar sirene +kapal. Orang-orang yang beranjak pulang itu berbalik dan +berlarian kembali ke dermaga. Juru antar melihat wajah Sa- +bari berdiri dengan tegang, tubuhnya tegak macam tentara +bersiap. + + Dada Sabari berdegup melihat sebuah kapal berbelok +di semenanjung sana. Dia terpana sehingga tak menyadari +kapal itu memasuki pelabuhan dan tahu-tahu sudah dekat se- + Ayah ~ 381 + +kali dengannya. Dia telah menunggu semua ini terjadi selama +delapan tahun dan ketika semuanya benar-benar terjadi di +depannya, tubuhnya gemetar. + + Anak buah kapal melemparkan tambang yang disambut +seorang kuli pelabuhan. Tambang diikatkan di tambatan ka- +pal. Pintu lambung kapal terbuka. Kuli pelabuhan tadi men- +julurkan keping-keping papan yang akan menjadi titian para +penumpang dari kapal ke dermaga. + + Tak lepas Sabari menatap penumpang yang keluar satu +per satu melalui pintu itu. Umumnya mereka orang-orang de- +wasa, lelaki dan perempuan. Tak lama kemudian dilihatnya +seorang anak melangkah ke luar. Dia terpana karena lang- +sung mengenali kemeja yang dikenakan anak itu. Sabari me- +rasa kakinya tak menginjak bumi. + + Amiru pun langsung mengenali laki-laki yang berdiri di +samping sepeda sambil memegang piala itu. Dia berlari me- +nyongsongnya, Aya! Aya! panggilnya. + + Zorro, Zorro! panggil Sabari, tetapi tak ada suara yang da- +pat keluar dari mulutnya. + + Amiru memeluk ayahnya erat-erat. Dia mencium bau +yang selalu menjadi misteri baginya, bau yang selalu menya- +yangi dan melindunginya. Kini dia tahu, bau itu adalah bau +ayahnya. Dipeluknya ayahnya semakin erat. Air mata anak +dan ayah itu berlinang-linang. + + Juru antar terharu melihat Sabari memeluk anaknya se- +akan tak mau melepasnya lagi. Dia tersenyum melihat Sabari + 382 ~ Andrea Hirata + +berusaha mengangkat anaknya tinggi-tinggi, tetapi anaknya +sudah besar sehingga dia terhuyung-huyung. Sabari menye- +rahkan piala kecil dan balon gas kepada Amiru. Abu Meong +berputar-putar mengelilingi mereka. Sesekali terlontar sua- +ra aya, aya dan kucing mengeong. Tamat dan Ukun meniti +jembatan papan tadi dengan langkah penuh kemenangan. +Bergantian mereka memeluk Sabari. Pada masing-masing ka- +wannya itu, Sabari mengalungkan medali keemasan. + + Juru antar bersyukur semuanya telah berlangsung de- +ngan baik. Dia kembali ke motornya. Diengkolnya motor itu +berkali-kali, gagal. Dia ingin memeriksa busi, tetapi terkejut +melihat tangannya telah berubah menjadi biru. Sepeda mo- +tornya juga. Dia menoleh sekeliling dan terpana karena se- +mua hal: sungai, semenanjung, dermaga, bangunan, kapal, +perahu, bakau, sepeda, semuanya berwarna biru. Orang- +orang menunjuk ke atas. Juru antar takjub melihat seluruh +langit telah berubah menjadi biru. + Janji Lama + +SALAH satu hal pertama yang dilakukan Sabari adalah +mengajak Amiru ke Restoran Modern. Dipesannya makanan +dari menu yang dulu diceritakannya untuk pengantar tidur +anaknya itu, nasi goreng luar negeri terutama. Beban berat +terlepas dari pundaknya karena janji lamanya kepada Zorro +telah tunai. + + Marlena mengizinkan Amiru tinggal bersama Sabari. +Setiap waktu Sabari mensyukuri hal itu. Ayah dan anak itu +langsung tak terpisahkan seperti dulu. Mereka pun kembali +ke kebiasaan lama, Sabari bercerita dan berpuisi menjelang +Zorro tidur. Bedanya, sekarang Amiru juga bisa bercerita dan +berpuisi untuk ayahnya. + + Terharu Sabari mendengar anaknya menyitir puisi-puisi +karyanya sendiri. Seperti ayahnya, Amiru pun punya buku +puisinya sendiri. Terkejut Sabari melihat beruntai-untai puisi +yang telah ditulis Zorro sejak kelas dua SD. Si kecil itu amat + 384 ~ Andrea Hirata + +terampil dengan kata-kata, lebih terampil daripada dirinya +sendiri. Jika dia berkata, matanya bersinar memancarkan ke- +cerdasan berbahasa. Setiap malam dibacanya puisi tentang +tempat-tempat yang pernah disinggahinya, guru-guru dan +kawan-kawan yang pernah dikenalnya. + + Sabari terlempar ke tempat-tempat yang jauh: Pang- +kal Pinang, Toboali, Bengkulu, Medan, Batanghari, Siak, +Rengat, Bengkalis, Pariaman, Indragiri Hulu, Bagan Siapi- +api, Tanjung Pinang, Singkep, Dabo. Takjub dia akan per- +jalanan anaknya dan terpukau akan puisi-puisi perjalanan- +nya. Kalimat berhias ditaburkan Zorro, dilekak-lekuk setiap +kata tumbuhlah sayap, lalu beterbangan seantero rumah bak +kupu-kupu. + + Sebuah puisi telah ditulis Zorro untuk ayahnya. Ayah, ju- +dul puisi itu. + + Kulalui sungai yang berliku + Jalan panjang sejauh pandang + Debur ombak yang menerjang + Kukejar bayangan sayap elang + Di situlah kutemukan jejak-jejak untuk pulang + Ayahku, kini aku telah datang + Ayahku, lihatlah, aku sudah pulang + + Sepanjang Amiru berpuisi, Sabari terharu karena bang- +ga melihat betapa besar anaknya melihat dirinya sendiri da- + Ayah ~ 385 + +lam diri Sabari, dan betapa besar dia melihat mendiang ayah- +nya di dalam diri Zorro. Sabari rindu berbalas puisi dengan +ayahnya. Namun, kini dia senang karena dapat pula berbalas +puisi dengan anaknya. + + Kebiasaan lama lainnya yang mereka ulangi adalah se- +tiap Sabtu sore Sabari membonceng Amiru naik sepeda ke +taman balai kota. Kebiasaan sederhana yang amat indah. + + Persis kebiasaan Sabari dan mendiang ayahnya. Sabari +dan Amiru pantang diberi umpan. Sepatah kalimat puisi +ayah, langsung disambar anaknya, begitu pun sebaliknya. + + Jalan menanjak, Amiru ingin turun karena ayahnya ke- +sulitan memboncengnya. Dia bukanlah anak kecil lagi. + + “Jangan, Nak, jangan turun, Ayah sanggup.” + Sepeda terseok-seok, tambah berat lantaran melawan +angin. + “Sudahlah, Ayah, aku turun saja.” + “Jangan, Boi, sebentar lagi.” Keringat Sabari bercucur- +an, tetapi dia berhasil menaklukkan tanjakan. Sepeda melun- +cur turun tanpa dikayuh. Amiru memeluk pinggang ayahnya. +Sabari merasa seperti dipeluk awan. Dadanya mengembang, +senyumnya berbunga-bunga. Sepeda melewati jembatan, Sa- +bari memandangi permukaan sungai yang tenang. + Dalam diam, riakmu tertawan, katanya pelan. + Amiru tersenyum. Karena bahagia yang tak dapat kau sembu- +nyikan, balas Amiru. + Sabari menyambung: + 386 ~ Andrea Hirata + + Engkaukah itu sungai? + Yang berbicara kepadaku + Bersekutu dengan waktu + Membuatku malu? + + Amiru menyambut: + + Aku adalah sungai + Aku adalah anak belibis + Aku adalah awan-awan sisik Januari + Tak ada, tak ada + Meski kau tenggelamkan aku di dasarmu + Tak ada bahagia yang dapat kau sembunyikan dariku + Sweet + +PULANG dari petualangan epik mereka di Sumatra, Tamat +kembali menjadi tukang kipas di warung satai kambing muda +Afrika. Ukun juga kembali menjadi tukang gulung dinamo, +dan Sabari kembali menjadi kuli serabutan yang penuh integ­ +ritas di Pasar Belantik. + + Akhirnya, Tamat dan Ukun menemukan jodoh setelah +berkenalan dengan perempuan di pantai barat pada Februari. +Mereka sering menghabiskan waktu di warung kopi Solider +dan selalu dengan seru berkisah tentang perjalanan mereka +menjelajahi Sumatra, pengalaman mereka melihat Masjid +Baiturachman di Banda Aceh, pertemuan yang amat menge- +sankan dengan para sahabat pena, penemuan kampung unik +yang penduduknya penggemar Lady Diana dan terutama +persahabatan dengan JonPijareli, gitaris top dari Medan. Je- +maah pendengar tetapnya adalah juru antar surat pengadilan +agama dan Toharun, yang meski tua, tetap gagah seperti Ar- + 388 ~ Andrea Hirata + +nold Swasanaseger dalam film Terminator III: Kebangkitan Me- +sin-Mesin. + + Amiru segera menjadi cucu kesayangan Markoni dan +istrinya. Kepada orang-orang, Markoni selalu berkata bahwa +kecerdasan Amiru berasal mula darinya. Amiru hampir tamat +SMP ketika datang sepucuk surat yang aneh untuk Sabari. + + Sabari tak kenal pengirim surat itu, tak kenal prangko- +nya, amplopnya juga lain dari yang biasa dilihatnya dan ada +bahasa Inggris-nya. Surat itu mungkin berasal dari luar nege- +ri. Diserahkannya surat itu kepada Amiru, biarlah anaknya +yang mengerti bahasa Inggris membacanya. Amiru menga- +mati amplop surat. + + From: Larissa Sweet Wuruninga + 374 Hodgson Cove, Darwin + Northtern Territory + Australia + + To: Indonesia Lonely Man, Sabari + SD Inpres (President instruction school basic) + Belantik Village, Belitong Island + Indonesia + + Amiru menatap ayahnya. + “Apakah Ayah punya sahabat pena di Australia?” + Sabari menggeleng. + Ayah ~ 389 + + Sepanjang sore, dengan bantuan kamus bahasa Inggris +yang dulu dibelikan ibunya di Tanjung Pinang, Amiru meng- +artikan kata demi kata dalam surat itu. Dia terpana membaca +kisah tentang seorang ayah yang mencari anaknya dengan +mengirim pesan melalui seekor penyu. Setelah tujuh tahun +penyu itu mengelana samudra, akhirnya nun jauh di Austra- +lia seseorang menemukannya. Dia pun terperangah memba- +ca bahwa ayah Larissa percaya bahwa Zorro dan ibunya ada +di Darwin. Oleh karena itu, dia mencari Zorro dan ibunya di +berbagai kota di wilayah utara Australia. Namun, Zorro dan +Lena tak ditemukan di sana, untuk itu ayahnya minta maaf +dan berharap semoga Sabari dan Zorro dapat bertemu lagi. +Di dalam surat itu juga ada kalimat-kalimat yang digarisba- +wahi yaitu pertanyaan dari Larissa sendiri, apakah benar ada +orang bernama Sabari, Marlena, dan Zorro. + + Amiru bertanya kepada ayahnya soal penyu itu. Sabari +membenarkan semuanya. Bahwa memang dia yang mengi- +rim pesan itu. Mereka memutuskan untuk membalas surat. +Amiru menulis surat semampunya dalam bahasa Inggris. Su- +rat dikirim disertai foto Amiru dan ayahnya. + +Dua bulan kemudian, Larissa terkejut menerima surat dari +Indonesia. Matanya terbelalak melihat nama pengirim surat +itu. Tiga hari kemudian dia mengundang makan malam selu- + 390 ~ Andrea Hirata + +ruh anggota keluarga dan kawan-kawan dekat ayahnya. Ang- +gota keluarga berdatangan dari seputar Darwin. + + Usai makan malam, di tengah keriuhan, Larissa menge- +tuk gelas dengan sendok, meminta suasana tenang. Dia berdi- +ri dan mengatakan bahwa dia ingin membaca sepucuk surat. + + Semua telah tenang, Larissa mengeluarkan sepucuk su- +rat dari saku bajunya. Dibukanya surat itu pelan-pelan. Di- +pandanginya ayahnya yang duduk sendiri di pojok situ. Laris- +sa mulai membaca. + + Dear Larissa Sweet Wuruninga, + My name is Zorro, I am the son of Indonesia Lonely Man, Sabari. + + Semua yang hadir terperanjat dan saling pandang. Pa- +man Matthew Tarrti yang paling tak percaya Sabari benar +ada, ternganga mulutnya. Ibu Larissa menutup mulut dengan +tangan. Gayle Rifkin, Annie Brown, dan David Pwominga +yang selalu menertawakan Brother Niel soal penyu dan Zor- +ro, yang menganggapnya sudah pikun, berdiri terpaku. + + Me and my father would like to say thank you because you and your + father look for me. After live separated for 8 years, 20 days, now I + am with my father again and I am happy. + I would like to say many words but I still study English, I hope + next time I can write letter with more words for you and your father. + Maybe when I study at senior high school and I understand tenses. + Ayah ~ 391 + + Larissa berhenti membaca karena terharu. + + For now, I just would like to say thank you very much. + Sincerely yours, + Very very happy, son Zorro and father Sabari. + + Larissa memperlihatkan foto Zorro saling memeluk +pundak dengan Sabari, tersenyum lebar. Orang-orang me- +lihat foto itu dengan pandangan tak percaya. Brother Niel +Wuruninga yang duduk di pojok situ juga tersenyum kepada +orang-orang yang terpana. Sesekali dipandangnya foto masa +kecilnya bersama saudara sulungnya, Jerome Wuruninga. + Purnama +Kedua Belas + +AMIRU tetap tinggal di Belitong bersama Sabari sampai +menamatkan SMA. Setelah itu, dia merantau ke Bogor un- +tuk mengikuti kursus elektronika. Aku bekerja di kantor pos +Bogor sebagai tukang sortir dan sering menemukan surat de- +ngan alamat kampung halamanku sendiri, Belantik, Belitong. +Surat itu dikirim Amiru untuk ayahnya. Dari situlah aku ber- +kenalan dengan Amiru. + + Bersahabat dengan Amiru sangat mengesankan. Dia +pintar dan berhati baik. Dia lulus terbaik dari kursus itu. Tiga +lulusan terbaik akan langsung diterima bekerja di sebuah per- +usahaan elektronik terkenal di Jakarta, tetapi Amiru ingin se- +gera pulang untuk mengurus ayahnya. + + Tampak benar dia merasa beruntung menjadi seorang +anak yang mendapat kesempatan untuk mengurus orangtua. +Dari Amiru aku belajar bahwa tak semua orang mendapat +berkah untuk mengabdi kepada orangtua. Karena Amiru, ke + Ayah ~ 393 + +mana pun aku merantau, setiap ada kesempatan, sesingkat +apa pun, aku pulang untuk melihat ayah dan ibuku. + + “Apa yang akan kau kerjakan di Belitong, Miru?” tanya- +ku. + + “Aku mau membuka kios reparasi elektronik, seperti kios +Bang Syarif Miskin,” katanya sambil tersenyum. “Apalagi, +sekarang aku sudah tahu cara kerja gelombang radio.” Dia +tersenyum lagi. + + Sesuai dengan rencananya, Amiru membuka kios repa- +rasi elektronik di Pasar Belantik. Nama kiosnya pun sama de- +ngan nama kios Syarif Miskin, Gaya Baru. Setiap hari Sabari +membantunya di kios itu. Tekun dia menyolder, membuka, +atau menguatkan baut-baut, mengelap apa pun yang bisa di- +lap dan tentu saja menggulung kabel-kabel. Tak bisa dia me- +lihat kabel yang centang perenang. + + Setelah lama saling berkirim surat, pada 2011, Larissa +dan ayahnya, Brother Niel Wuruninga, mengunjungi Bali. +Setelah itu, mereka mengunjungi Sabari dan Amiru di Be- +litong. Mereka adalah orang asing pertama yang mengun- +jungi Kampung Belantik. Oleh karena itu sambutan untuk +mereka luar biasa. Rumah Sabari ramai. Tetangga berebut +melihat penduduk asli Australia itu melalui jendela dan terpe- +sona menyaksikan Brother Niel meniup didgeridoo, alat musik +tradisional Aborigin yang kemudian ditinggalnya sebagai ke- +nang-kenangan. Sabari pun memberi Brother Niel gendang +kelinang. Gendang musik Melayu kuno yang hampir punah. + 394 ~ Andrea Hirata + +Setiap tahun, jika kemarau datang dan ilalang berbunga, +Sabari selalu pergi ke padang di pinggir kampung. Lama di- +pandanginya ilalang yang meliuk-liuk ditiup angin selatan. +Berpuluh tahun telah berlalu, kerinduan kepada Lena masih +tergenang dalam dadanya. + + Sering Amiru menemani ayahnya berjalan-jalan sore. +Begitu dekat hubungan mereka sehingga Amiru tak sungkan +bertanya apakah ayahnya masih mencintai ibunya? + + “Ingat, Boi, dalam hidup ini semuanya terjadi tiga kali. +Pertama aku mencintai ibumu, kedua aku mencintai ibumu, +ketiga aku mencintai ibumu.” + + Selama April, Sabari selalu duduk sendiri di bangku di +beranda hingga jauh malam. Dilihatnya telapak tangan kiri- +nya. Sinar purnama kedua belas menerangi telapak tangan- +nya, menerangi hatinya. Tangan kanannya erat menggeng- +gam pensil. Dia merindukan Lena, sangat rindu sehingga dia +sulit bernapas. Sering Amiru melihat ayahnya tidur sambil +menggenggam pensil itu. + + Hanya dengan Lena, Sabari pernah menikah. Itulah +pernikahan pertama dan terakhirnya. Dalam pernikahan itu +hanya empat kali dia pernah berjumpa dengan Lena, tetapi +dia tetap mencintai Lena, hanya Lena, hingga akhir hayat- +nya. Pertengahan 2013, Sabari meninggal dunia. + Ayah ~ 395 + + Makam Sabari sering dilihat orang karena di pusaranya +ada puisi Biarkan aku mati dalam keharuman cintamu. Orang-orang +yang berziarah selalu mampir ke makamnya. Amiru-lah yang +meminta pembuat pusara untuk mengukir puisi ayahnya itu. + + Amiru kerap mengunjungi tiga orang lain yang pernah +menjadi ayahnya, yang mencintainya dengan cara mereka +masing-masing, yaitu Manikam, JonPijareli, dan Amirza. Dia +pun selalu berkomunikasi dengan kedua adik tirinya, Amirta +dan Amirna. + + Marlena sempat pulang ke Belitong dan berjumpa lagi +dengan ayah, ibu, dan saudara-saudaranya. Beberapa waktu +setelah berjumpa dengan Lena, Markoni meninggal. + + Sampai tua Lena masih rajin berkirim surat kepada sa- +habat-sahabat penanya. Mereka telah berkenalan sejak masih +SD dan SMP. Barangkali Marlena dan para sahabat penanya +adalah generasi terakhir manusia menjalin persahabatan me- +lalui surat. + + Lena tetap berumah tangga dengan Amirza dan tinggal +di Dabo hingga tutup usia akhir 2014. Sebelum meninggal, +dalam sakitnya Lena berpesan untuk dimakamkan di Belan- +tik. + + “Dekat makam Sabari,” katanya kepada Amiru. + “Kalau tak dapat di sampingnya, tak apa-apa, tapi di +dekatnya.” Amiru tercenung dalam kesedihan. Mungkin ter­ +inspirasi oleh puisi di makam Sabari, sambil tersenyum malu +Lena meminta Amiru menulis sesuatu juga di pusaranya. + 396 ~ Andrea Hirata + + “Tulisan apa, Ibunda?” + “Di bawah namaku, tulislah, purnama kedua belas.” + Amiru terhenyak, dia tahu begitulah ayahnya dulu sela- +lu memanggil ibunya ketika mereka baru berjumpa. Amiru +menggenggam tangan ibunya kuat-kuat. + Baru-baru ini seorang kawan bertanya kepadaku, apa +benar kata orang ada makam bertulisan purnama kedua belas +di Belantik? Kujawab ya, aku sendiri pernah melihatnya. Dia +bertanya lagi, makam siapakah itu? Bagaimana riwayatnya? +Aku tak dapat berkata-kata. Meski berusaha, aku tak dapat +menemukan satu kata pun untuk memulai kisah cinta Sabari +dan Marlena, kisah cinta paling hebat yang pernah kuketahui +seumur hidupku. + Katalog Karya +Andrea Hirata + Dapatkan karya-karya Andrea Hirata + edisi bahasa Indonesia + Tetralogi Laskar Pelangi + +“Laskar Pelangi, salah satu dari 45 buku yang mempengaruhi +Indonesia.” +—45 Buku yang Mempengaruhi Indonesia, Media Indonesia + “Tidak pernah ada yang bisa mengalahkan kekuatan cinta yang +murni dan tulus. Cinta yang mendalam menebarkan energi po- +sitif yang tidak hanya mengubah hidup seseorang, tetapi juga +menerangi kehidupan orang banyak.” + +—Kompas + Dapatkan koleksi berharga Laskar Pelangi +edisi internasional. Semua novel tersedia + + di amazon.com + + Germany edition-Publisher: Hanser Berlin + Germany edition-Publisher: Hanser Berlin + +“Novel Laskar Pelangi versi bahasa Jerman menarik perhatian +publik Swiss. Malah untuk pinjam di perpustakaan saja, pem- +baca harus masuk waiting list. Di toko buku tertentu juga keha- +bisan stok, untuk meminjam versi cakram padat (compact disc) +yang di Swiss dikenal sebagai hoerbuch, karya Andrea Hirata +ini harus dipesan jauh-jauh hari. ‘Novelnya masih dipinjam +orang,’ kata salah seorang petugas di perpustakaan Lucerne.” +—Koran Sindo, 24 November 2013 + Laskar Pelangi- + International Bestseller + +Turkey edition-Publisher: butik Yayincilik + “This fine story about strength and resilience against the odds, +and the power of hope … seems only a matter of time before a +director brings this story to cinemas in the West.” +—The Economist + Turkey edition-Publisher: butik Yayincilik + +“Andrea Hirata has written an endearing, simple and conversa- +tional prose … inspiring story.” +—The Guardian UK + “Andrea Hirata’s closely autobiographical debut novel [...] pro- +mises to captivate audiences across the globe. This is classic +storytelling in the spirit of Khaled Hosseini’s The Kite Runner: +an engrossing depiction of a milieu we have never encountered +before, bursting with charm and verve.” +—Farrar, Straus and Giroux (FSG), New York + “Inspiring and closely autobiographical tale … Ikal and his +band of plucky cohorts face obstacles large and small, and the +reader can’t help but root for them to get the education-and +life-they deserve. The setting is as compelling and memorable +as the characters, and a rare window into a world we know +little about.” +—Harper Collins + “Incredibly moving and full of hope, Rainbow Troops swept In- +donesia off its feet, selling over five million copies and becoming +the highest-selling book in its history. It will sweep you away +too.” +—Penguin + Novel Laskar Pelangi edisi internasional tersedia + di www.amazon.com + + Info: www.andrea-hirata.com + Dapatkan Audio Book Laskar Pelangi + Edisi Australia dan Jerman + +The Rainbow Troops – Audio Die Regenbogentruppe – Audio +books books +Publisher : Bolinda, Sidney, Publisher : Hörbuch Hamburg + Read by : Sebastian Rudolph, + Australia. +Read by : Kenneth Moraleda, German actor. + The Lion King, + + War House musical + actor. + Karya-karya Andrea Hirata lainnya + Dapatkan novel kedua Andrea Hirata + edisi internasional, The Dreamer + +“Electrifying, a brilliant author.” +—Lesley Ann Wheeler, American author and poet + diff --git a/storage/app/books/hijrah.pdf b/storage/app/books/hijrah.pdf new file mode 100644 index 0000000..9ff642e --- /dev/null +++ b/storage/app/books/hijrah.pdf @@ -0,0 +1 @@ + diff --git a/storage/app/books/ipas.pdf b/storage/app/books/ipas.pdf new file mode 100644 index 0000000..76ba610 --- /dev/null +++ b/storage/app/books/ipas.pdf @@ -0,0 +1,2403 @@ +Lampiran 1 Modul Ajar +A. Modul Ajar Siklus I + + MODUL AJAR KURIKULUM MERDEKA 2024 + IPAS SD KELAS 4 SIKLUS I + +INFORMASI UMUM + +A. IDENTITAS MODUL + +Penyusun : Alifia Navrielda Putri +Instansi : SDN Patihan +Tahun Penyusunan : Tahun 2024 +Jenjang Sekolah : SD +Mata Pelajaran : Ilmu Pengetahuan Alam dan Sosial +Fase/Kelas : B / 4A +Bab/Tema : 6. Indonesiaku Kaya Budaya +Materi Pembelajaran : Keberagaman Budaya Indonesia +Alokasi Waktu : 1 kali pertemuan/ 3x35 menit + +B. CAPAIAN PEMBELAJARAN (CP) + + Peserta didik mengenal keragaman budaya, kearifan lokal, sejarah (baik + tokoh maupun periodisasinya) di Indonesia serta menghubungkan dengan + konteks kehidupan saat ini. + +C. PROFIL PELAJAR PANCASILA + +  Beriman, bertakwa kepada Tuhan YME dan berakhlak mulia. +  Berkebhinnekaan global. +  Mandiri +  Gotong royong. +  Kreatif +  Bernalar kritis. + +D. SARANA DAN PRASARANA + +  Sumber Belajar + + 1. Buku Guru (Kementerian Pendidikan, Kebudayaan, Riset, Dan + Teknologi Republik Indonesia, 2021 Ilmu Pengetahuan Alam dan + Sosial untuk Sekolah Dasar Kelas IV, Penulis: Amalis Fitri, dkk) + + 2. Buku Siswa (Kementerian Pendidikan, Kebudayaan, Riset, Dan + Teknologi Republik Indonesia, 2021 Ilmu Pengetahuan Alam dan + Sosial untuk Sekolah Dasar Kelas IV, Penulis: Amalis Fitri, dkk) + + 96 + 97 + + Alat dan Bahan + 1. Lembar Kerja Peserta Didik (LKPD) + 2. Laptop + 3. Proyektor + 4. LCD + +E. TARGET PESERTA DIDIK + +  Peserta didik reguler/tipikal: umum, tidak ada kesulitan dalam mencerna + dan memahami materi ajar. + +  Peserta didik dengan pencapaian tinggi: mencerna dan memahami dengan + cepat, mampu mencapai keterampilan berfikir aras tinggi (HOTS), dan + memiliki keterampilan memimpin. + +F. JUMLAH PESERTA DIDIK + + Peserta didik berjumlah 16 orang. + +G. MODEL/METODE/MEDIA/PENDEKATAN PEMBELAJARAN + + Model Pembelajaran : Project Based Learning + + Metode : Demonstrasi, diskusi, tanya jawab dan penugasan + + Media Pembelajaran : Video Pembelajaran + + Pendekatan : Saintific, TPACK + +KOMPONEN INTI + +A. TUJUAN KEGIATAN PEMBELAJARAN + +  Tujuan Pembelajaran + 1. Peserta didik dapat menginterpretasikan keberagaman budaya + yang ada di Indonesia melalui pengamatan video dengan tepat. + 2. Peserta didik dapat menganalisis keberagaman budaya yang ada + di Indonesia melalui tayangan video dengan baol.. + 3. Peserta didik dapat mengevaluasi keberagaman budaya yang ada di + Indonesia melalui kegiatan diskusi kelompok dengan benar. + 4. Peserta didik dapat membuat peta keberagaman budaya yang ada di + Indonesia melalui pengamatan contoh dengan tepat. + +B. PEMAHAMAN BERMAKNA + +Meningkatkan pemahaman peserta didik untuk mengetahui keberagaman +budaya yang ada di Indonesia. + +C. PERTANYAAN PEMANTIK + 1. Dari tayangan video yang kalian amati tadi, apa yang ada dipikiran + kalian? + 2. Apa manfaat keberagaman budaya? + 3. Sebagai pelajar, cara apa yang bisa kalian lakukan agar dapat membantu + melestarikan keberagaman di Indonesia? + 98 + +D. KEGIATAN PEMBELAJARAN + + Kegiatan Pendahuluan (10 menit) + 1. Guru memberikan salam dan secara acak memberikan kesempatan + + kepada salah satu peserta didik untuk memimpin berdoa bersama sesuai + dengan agama dan kepercayaanya masing-masing sebelum pembelajaran + dilaksanakan. + 2. Peserta didik bersama guru menyanyikan lagu nasional (Garuda + Pancasila). + 3. Guru menyapa dan mengecek kehadiran peserta didik. (communication) + 4. Guru bertanya jawab dengan peserta didik terkait materi yang akan + disampaikan hari ini. (apersepsi) + 5. Guru menyampaikan tujuan pembelajaran. + + Kegiatan Inti (85 menit) + Tahap 1. Penentuan Pertanyaan/Permasalahan Mendasar + 1. Guru memberikan pertanyaan terbuka “kalian lebih suka menarikan + + tarian tradisional daerah atau tari modern?” dan guru juga + mempertanyakan “mengapa banyak orang yang lebih menyukai tarian + modern?” (menanya) + 2. Guru menjelaskan sedikit mengenai keberagaman budaya. Peserta didik + mendengarkan. + 3. Guru memberikan stimulus dengan menayangkan video, peserta didik + mengamati video tersebut tentang keberagaman budaya. (mengamati, + TPACK) + 4. Peserta didik diminta menyimak sedikit penjelasan yang berhubungan + dengan video yang telah diamati. + 5. Peserta didik diarahkan untuk mengemukakan pendapat atau pertanyaan + berkaitan dengan apa yang disampaikan guru. (communication, Critical + Thinking Skills) + + Tahap 2. Mendesain Perencanaan Proyek + 6. Peserta didik dibagi menjadi beberapa kelompok yang terdiri dari 4 + + siswa. + 7. Guru membagikan LKPD. + 8. Peserta didik mendengarkan penjelasan proyek tentang kegiatan peserta + + didik yang akan dilakukan dalam LKPD. (communication) + 9. Guru memberikan kesempatan untuk menanyakan hal yang belum + + dipahami siswa. + + Tahap 3. Menyusun Jadwal + 10. Guru menjelaskan cara kerja dan bahan apa saja yang dibutuhkan untuk + + menyelesaikan proyek peta keberagaman. (mengamati) + 99 + +11. Guru meminta peserta didik dalam kegiatan pembelajaran dengan + bekerjasama dalam kelompoknya. Peserta didik berdiskusi menyusun + rencana pembuatan proyek. + +12. Guru dan peserta didik menyepakati waktu penyelesaian. +Tahap 4. Memonitoring Peserta Didik dan Kemajuan Proyek +13. Guru memantau keaktifan peserta didik selama melaksanakan proyek dan + + realisasi kemajuan proyek. +14. Peserta didik diberi kesempatan untuk bertanya atau berkonsultasi kepada + + guru apabila mengalami kesulitan. (communication, Critical Thinking + Skills) +15. Peserta didik diminta melanjutkan kegiatan penyelesaian proyek yang + akan didiskusikan dan menyelesaikan tugas sesuai arahan yang sudah + dituangkan dalam LKPD. (Creativity and Innovation, collaboration, + Critical Thinking Skills) + +Tahap 5. Menguji Hasil +16. Peserta didik menyusun bahan laporan untuk presentasi kelompok. + + (communication) +17. Guru memantau keterlibatan peserta didik dan mengukur ketercapaian + + standar. + +Tahap 6. Evaluasi Pengalaman Belajar +18. Peserta didik dibimbing tentang bagaimana cara memaparkan hasil + + proyek di depan kelas. +19. Masing-masing kelompok diminta untuk mempresentasikan hasil proyek. +20. Peserta didik dan kelompok lain memberikan tanggapan/umpan balik + + mengenai hasil presentasi. (communication, Critical Thinking Skills) +21. Guru melakukan kegiatan ice breaking untuk mengembalikan semangat + + belajar. +22. Guru memberikan penguatan hasil presentasi yang telah dilakukan. +23. Guru memberikan apresiasi kepada setiap kelompok dan penghargaan + + bagi kelompok belajar yang paling aktif dan hasil diskusi yang paling + baik. +24. Guru memberikan soal tes kemampuan berpikir kritis kepada siswa untuk + dikerjakan secara individu. + +Kegiatan Penutup (10 menit) +1. Guru bersama peserta didik melakukan refleksi pembelajaran mengenai + + materi pembelajaran pada pertemuan ini. +2. Peserta didik diminta untuk menyampaikan perasaannya selama + + mengikuti pelajaran. (communication) + 100 + +3. Guru memberikan kesempatan kepada peserta didik untuk + menyampaikan kesimpulan yang didapat dari keberagaman budaya di + Indonesia. + +4. Guru menutup pelajaran dan secara bergantian memberikan + + kesempatan kepada peserta didik lain untuk memimpin berdoa bersama + setelah selesai pembelajaran. + + Mengetahui, Madiun, 22 Mei 2024 + Guru Kelas 4A Mahasiswa + +DEWI NOVITA SARI, S.Pd. ALIFIA NAVRIELDA PUTRI +NIP. 19891117 202221 2 014 NIM. 2002101147 + +E. REFLEKSI + + TABEL REFLEKSI UNTUK PESERTA DIDIK + +N No Pertanyaan Jawaban + 1. Bagaimana materi yang kalian rasa paling + 2. sulit? + 3. Apa yang kalian lakukan untuk dapat lebih + 4. memahami materi ini? + Apakah kalian memiliki cara sendiri untuk + 5. memahami materi ini? + Kepada siapa kalian akan meminta bantuan + untuk memahami materi ini? + Jika kalian diminta memberikan bintamg 1 + sampai 5, berapa bintang yang akan kalian + berikan pada usaha yang kalian lakukan untuk + memahami materi ini? + + TABEL REFLEKSI UNTUK GURU + +N No Pertanyaan Jawaban + 1. Apakah 100% peserta didik mencapai tujuan + pembelajaran? Jika tidak. Berapa persen kira- + 2. kira peserta didik yang mencapi pembelajaran? + Apa kesulitan yang dialami peserta didik + sehingga tidak mencapi tujuan pembelajaran? + Apa yang akan anda lakukan untuk membantu + peserta didik? + 101 + + Apakah terdapat peserta didik yang tidak +3. fokus? Bagaimana cara guru agar mereka bisa + + fokus pada kegiatan berikutnya? + +F. ASESMEN/PENILAIAN + Penilaian dapat dilihat melalui tabel berikut ini. + +No. Aspek Bentuk Waktu Pelaksanaan Instrumen + + Setelah Lembar Tes + +1. Pengetahuan Tes pembelajaran (terlampir) + + selesai + + Pada saat Lembar + +2. Keterampilan Pengamatan pembelajaran Pengamatan + + (terlampir) + +G. KEGIATAN PENGAYAAN DAN REMEDIAL + +Pengayaan +Peserta didik dengan nilai rata-rata dan nilai di atas rata-rata mengikuti +pembelajaran dengan mengerjakan soal pengayaan untuk memaksimalkan hasil +yang didapatkan. + +Remedial +Peserta didik yang belum menguasai CP akan melakukan pengulangan materi +dengan pendampingan baik secara individu maupun kelompok. Pendampingan +dapat dilakukan oleh guru atau dengan menerapkan pembelajaran teman sebaya +dan memberikan tugas tambahan untuk memperbaiki hasil belajar. + 102 + +LAMPIRAN +A. BAHAN BACAAN GURU & PESERTA DIDIK + + Kekayaan Budaya Indonesia +A. Keberagaman Budaya + + Indonesia merupakan negara kepulauan. Masing-masing pulau tersebut +didiami oleh suku bangsa tersendiri. Indonesia memiliki banyak susku bangsa +dan adat istiadat yang berbeda-beda, maka Indonesia disebut negara yang +memilik banyak keberagaman. Bangsa Indonesia dibangun dari sejumlah +perbedaan atau keberagaman. Keberagaman Indonesia meliputi suku bangsa, +agama, budaya, dan adat istiadat. Keragaman budaya di Indonesia meliputi, +rumah adat, pakaian tradisonal, tarian adat, upacara adat, alat musik dan lagu +daerah, senjata adat, dan makanan tradisional khas daerah. + + Bentuk keragaman budaya Indonesia antara lain sebagai berikut. +1. Upacara Adat + + Upacara adat merupakan upacara yang berhubungan dengan adat + istiadat masyarakat. Upacara adat dilestarikan secara turun temurun dari + generasi ke generasi. Contoh upacara adat adalah, upacara belian yang + dilakukan suku dayak dari kalimatan dan pasola yang dilakukan oleh + masyarakat Nusa Tenggara Timur. + +2. Rumah Adat + Rumah adat merupakan bangunan tempat tinggal yang menjadi ciri + + khas suatu daerah. Rumah adata masing-masing daerah memiliki keunikan + dan kekhasan yang mengandung filosofi luhur budaya setempat. Contoh + 103 + + rumah adat antara lain, rumah gadang dari Sumatera Barat, rumah + tongkonan dari Sulawesi Selatan, rumah honai dari Papua. + +3. Pakaian Adat + Setiap suku bangsa di Indonesia memiliki gaya busana dan corak + + yang berbeda, baik yang dari segi bentuk, bahan, model maupun warnanya. + Pakaian adat biasanya digunakan saat upacara adat seperti upacara + perkawinan dan pertunjukan seni tradisional. Contoh pakaian adat, yaitu + baju cele dari Maluku, paksian dari Bangka Belitung. + +4. Tarian Adat + Tarian daerah merupakan tarian yang tumbuh dan berkembang di + + suatu daerah. Gerakan tarian daerah menunjukkan kearifan daerah + setempat. Contoh tarian adat antara lain seudati dari Nangru Aceh + Darussalam, lenso dari Maluku, dan maengket dari Sulawesi Utara. + 104 + +5. Makanan Khas Daerah + Indonesia memiliki kuliner beraneka ragam yang berupa makanan + + khas daerah yang beraneka rupa dan rasa. Contoh makanan khas daerah + adalah gudeg dari Yogyakarta, papeda dari Papua, dan es slendang mayang + dari Jakarta. + +B. MEDIA + Video Pembelajaran Animasi + Link Youtube: https://youtu.be/xqeN3CqufNA?si=B8t-ZgGsId7E2Oos + +C. INSTRUMEN PENILAIAN +1. SOAL +a. Pengetahuan + + Terlampir + 105 + +b. Keterampilan + + Anggota Kelompok: + + 1. 3. + + 2. 4. + + Bacalah petunjuk pengerjakan tugas proyek peta keberagaman bersama + + kelompokmu! + + 1. Siapkan alat dan bahan berikut untuk mengerjakan tugas proyek! + + a) Gunting d) Atlas + + b) Lem e) Buku/koran/majalah + + c) Pensil warna + + 2. Baca atlas atau buku literatur lainnya dan cari tahu provinsi yang ada + di pulau pilihan kelompok kalian! + + 3. Gambarlah pulau yang telah kalian dapatkan! + 4. Setelah itu, ambilah gambar-gambar mengenai keberagaman budaya + + (rumah adat, pakaian adat, makanan tradisional) yang ada di pulau + tersebut. + 5. Setelah digunting, tempelkan gambar-gambar tersebut di pulau pilihan + kalian! + 6. Jika sudah selesai, gabungkan dengan kelompok lain sehingga menjadi + peta keragaman Indonesia yang utuh. +Setiap kelompok mempresentasikan pulaunya dengan ragam budayanya! + +2. PEDOMAN PENILAIAN + +a. Penilaian Pengetahuan (Sumatif) + +Kelas : IV + +Pelajaran/BAB: IPAS/ 6. Indonesia Kaya Budaya + +Topik : B. Kekayaan Budaya Indonesia + +Bentuk Soal : Uraian + + Nomor Soal Jumlah + Skor +No Nama 1 2 + + ab c d e abc d e + +1. ARK +2. AIF +3. ER +4. IAPS +5. JRFP +6. KDS +7. RDM +8. SYC +9. TFS +10. VNF +11. VPRS + 106 + +12. ZZL +13. MAFH +14. AAD +15. FMA +16. FGCS + + RUBRIK SKOR PENILAIAN TES KEMAMPUAN + + BERPIKIR KRITIS SISWA + + Indikator Nomor Keterangan Skor + Kemampuan Soal +Berpikir Kritis + +Interpretation  Tidak menjawab 0 +(Interpretasi) 1. a  Menjawab tetapi tidak tepat 1 + 2. a  Menjawab tetapi kurang 2 + 3 + tepat +  Menjawab dengan tepat + +Analysis  Tidak menjawab 0 +(Analisis) 1 + 1. b  Menjawab tetapi salah 2 + 2. b semua 3 + +  Hanya menyebutkan 1 + +  Menyebutkan lebih dari 1 + +Evaluation  Tidak menjawab 0 +(Evaluasi) 1 + 1. c  Menjawab tetapi tidak tepat 2 + 2. c  Menjawab tetapi kurang 3 + + tepat + +  Menjawab dengan tepat + +Inference 1. d  Tidak menjawab 0 + +(Kesimpulan) 1. e  Menjawab tetapi tidak tepat 1 + + 2. d  Hanya menyebutkan 1 benar 2 + + 2. e  Menyebutkan 3 benar semua 3 + +Skor maksimal : 30 + +Penilaian : ℎ ℎ × 100 + ℎ + +Panduan Konversi Nilai: Predikat Klasifikasi + + Konversi Nilai A SB (Sangat Baik) + (skala 0-100) B B (Baik) + C C (Cukup) + 90-100 D K (Kurang) + 80-89 + 70-79 + 0-69 + 107 + +b. Penilaian Keterampilan (Formatif) + + LEMBAR PENILAIAN PENGAMATAN HASIL PROYEK + +N No Nama Siswa dapat Kriteria Siswa dapat Total + Menggambar menempelkan Skor + 1. ARK Pulau dengan Siswa dapat Seluruh + 2. AIF menggunting gambar + 3. ER tepat keberagaman + 4. IAPS pulau sesuai dengan + 5. JRFP SB B C K provinsinya + 6. KDS SB B C K SB B C K + 7. RDM + 8. SYC + 9. TFS + 10. VNF + 11. VPRS + 12. ZZL + 13. MAFH + 14. AAD + 15. FMA + 16. FGCS + + RUBRIK PENILAIAN PENGAMATAN + +No. Kriteria Sangat Baik Cukup Perlu + Baik Bimbingan +1. Kesesuaian 3 2 + Menggam- 4 Dapat Kurang 1 + bar Pulau Dapat menggam- dapat Belum + menggam- bar dengan menggambar mampu + bar pulau benar, dan dengan benar menggambar + dan jelas. dan jelas. pulau dan + memberi memberi + warna warna perlu + dengan bimbingan + benar, guru atau + jelas, dan orang tua. + tepat. + 108 + +2. Kemam- Dapat Dapat Kurang Belum + +puan menggun- menggun- dapat mampu + +menggun- ting ting menggun- menggunting + +ting keragaman keragaman ting keragaman + +keragaman budaya budaya keragaman budaya + +budaya dengan dengan dengan dengan + + benar, rapi benar. benar, jelas benar, jelas + + dan tepat. dan tepat. dan tepat. + +3. Kemam- Dapat Dapat Kurang Belum + +puan menempel- menempel dapat mampu + +menempel- kan kan beberapa menempel menempel + +kan gambar seluruh gambar kan seluruh kan seluruh + +keberaga- gambar keberagaman gambar gambar + +man sesuai keberaga- sesuai keberagaman keberagaman + +dengan man sesuai dengan sesuai sesuai + +provinsi- dengan provinsi atau dengan dengan + +nya provinsi pulaunya provinsi atau provinsi atau + + atau dengan tepat. pulaunya pulaunya + + pulaunya dengan tepat. dengan tepat. + + dengan + + tepat dan + + jelas. + +Skor maksimal : 12 + + () = × 100 + + +Panduan Konversi Nilai: + + Konversi Nilai Predikat Klasifikasi + (skala 0-100) + A SB (Sangat Baik) + 90-100 B B (Baik) + 80-89 C C (Cukup) + 70-79 D K (Kurang) + 0-69 + +D. GLOSARIUM + +Budaya +Pikiran, akal, budi, hasil, adat istiadat, atau sesuatu yang sudah menjadi kebiasaan +yang suka diubah-ubah. + +Capaian pembelajaran + +Adalah kemampuan yang diperoleh melalui internalisasi pengetahuan, sikap, +keterampilan, kompetensi, dan akumulasi pengalaman belajar peserta didik. + 109 + +Daerah +Wilayah (kekuasaan, pemerintahan, pengawasan, dan sebagainya). +Indonesia +Negara dengan berbagai suku bangsa yang mendiami kepulauan. +Kearifan Lokal +Nilai-nilai luhur yang berlaku dalam tata kehidupan masyarakat untuk melindungi +dan mengolah lingkungan hidup secara lestari. +Keberagaman +Perbedaan-perbedaan yang ada dalam kehidupan bermasyarakat. +Kebudayaan +Keseluruhan hasil cipta, rasa, karsa dalam bentuk bahasa, seni, ekonomi, teknologi, +ekspresi beragama, cara kerja, dan sistem. +Metode pembelajaran +Merupakan cara yang dilakukan guru untuk mewujudkan suasana belajar dan proses +pembelajaran agar peserta didik mencapai kompetensi dasar atau seperangkat +indikator yang telah ditetapkan. +Model pembelajaran +Merupakan kerangka konseptual yang melukiskan prosedur yang sistematis dalam +mengorganisasikan pengalaman belajar untuk mencapai tujuan belajar. +Nasionalisme +Paham tentang bangsa yang mengandung kesadaran tentang cinta dan semangat +tanah air, memiliki rasa kebanggan sebagai bangsa dan memelihara kehormatan +bangsa. +Pelajar Pancasila +Perwujudan pelajar Indonesia sebagai pelajar sepanjang hayat yang memiliki +kompetensi global dan berperilaku sesuai dengan nilai-nilai Pancasila, dengan enam +ciri utama: beriman, bertakwa kepada Tuhan Yang Maha Esa, dan berakhlak mulia, +berkebinekaan global, bergotong royong, mandiri, bernalar kritis, dan kreatif. +Pengayaan +Adalah kegiatan yang diberikan kepada peserta didik kelompok cepat agar mereka +dapat mengembangkan potensinya secara optimal dengan memanfaatkan sisa waktu +yang dimilikinya. +Penilaian +Proses pengumpulan dan pengolahan informasi untuk mengukur pencapaian hasil +belajar peserta didik. +Peserta didik +Anggota masyarakat yang berusaha mengembangkan potensi diri melalui proses +pembelajaran yang tersedia pada jalur, jenjang, dan jenis pendidikan tertentu. +Rumah Adat +Bangunan tempat tinggal yang menjadi ciri khas suatu daerah. +Refleksi +Aktifitas pikir dan rasa dalam rangka menilasi situasi diri atau situasi lingkungan +untuk menumbuhkan kesadaran yang lebih baik dalam mengaktualisasikan diri. + 110 + + Suku bangsa + Kesatuan hidup atau sekelompok manusia yanga memiliki kesamaan sistem + interaksi, sistem norma, dan identitas yang sama yang menyatukan. + Tujuan pembelajaran + Merupakan gambaran proses dan hasil belajar yang diharapkan dicapai oleh peserta + didik sesuai dengan capaian pembelajaran. + Upacara Adat + Kegiatan sacral yang berhubungan dengan adat istiadat masyarakat + +E. DAFTAR PUSTAKA + +Amalia Fitri, dkk. 2022. Buku Panduan Guru Ilmu Pengetahuan Alam dan Sosial untuk + SD Kelas IV. Jakarta: Kementerian Pendidikan, Kebudayaan, Riset dan + Teknologi. + +Amalia Fitri, dkk. 2022. Buku Panduan Siswa Ilmu Pengetahuan Alam dan Sosial untuk + SD Kelas IV. Jakarta: Kementerian Pendidikan, Kebudayaan, Riset dan + Teknologi. + + Mengetahui, Madiun, 22 Mei 2027 + Guru Kelas 4A Mahasiswa + +DEWI NOVITA SARI, S.Pd. ALIFIA NAVRIELDA PUTRI +NIP. 19891117 202221 2 014 NIM. 2002101147 + 111 + +B. Modul Ajar Siklus II + + MODUL AJAR KURIKULUM MERDEKA 2024 + IPAS SD KELAS 4 SIKLUS II + +INFORMASI UMUM + +A. IDENTITAS MODUL + +Penyusun : Alifia Navrielda Putri +Instansi : SDN Patihan +Tahun Penyusunan : Tahun 2024 +Jenjang Sekolah : SD +Mata Pelajaran : Ilmu Pengetahuan Alam dan Sosial +Fase/Kelas : B / 4A +Bab/Tema : 6. Indonesiaku Kaya Budaya +Materi Pembelajaran : Keberagaman Budaya Indonesia +Alokasi Waktu : 1 kali pertemuan/ 3x35 menit + +B. CAPAIAN PEMBELAJARAN (CP) + + Peserta didik mengenal keragaman budaya, kearifan lokal, sejarah (baik + tokoh maupun periodisasinya) di Indonesia serta menghubungkan dengan + konteks kehidupan saat ini. + +C. PROFIL PELAJAR PANCASILA + +  Beriman, bertakwa kepada Tuhan YME dan berakhlak mulia. +  Berkebhinnekaan global. +  Mandiri +  Gotong royong. +  Kreatif +  Bernalar kritis. + +D. SARANA DAN PRASARANA + +  Sumber Belajar + + 1. Buku Guru (Kementerian Pendidikan, Kebudayaan, Riset, Dan + Teknologi Republik Indonesia, 2021 Ilmu Pengetahuan Alam dan + Sosial untuk Sekolah Dasar Kelas IV, Penulis: Amalis Fitri, dkk) + + 2. Buku Siswa (Kementerian Pendidikan, Kebudayaan, Riset, Dan + Teknologi Republik Indonesia, 2021 Ilmu Pengetahuan Alam dan + Sosial untuk Sekolah Dasar Kelas IV, Penulis: Amalis Fitri, dkk) + + Alat dan Bahan + 1. Lembar Kerja Peserta Didik (LKPD) + 2. Laptop + 112 + +3. Proyektor +4. LCD + +E. TARGET PESERTA DIDIK + +  Peserta didik reguler/tipikal: umum, tidak ada kesulitan dalam mencerna + dan memahami materi ajar. + +  Peserta didik dengan pencapaian tinggi: mencerna dan memahami dengan + cepat, mampu mencapai keterampilan berfikir aras tinggi (HOTS), dan + memiliki keterampilan memimpin. + +F. JUMLAH PESERTA DIDIK + + Peserta didik berjumlah 16 orang. + +G. MODEL/METODE/MEDIA/PENDEKATAN PEMBELAJARAN + + Model Pembelajaran : Project Based Learning + + Metode : Demonstrasi, diskusi, tanya jawab dan penugasan + + Media Pembelajaran : Video Pembelajaran + + Pendekatan : Saintific, TPACK + +KOMPONEN INTI + +H. TUJUAN KEGIATAN PEMBELAJARAN + +  Tujuan Pembelajaran + 1. Peserta didik dapat menginterpretasikan keberagaman budaya + yang ada di Indonesia melalui pengamatan video dengan tepat. + 2. Peserta didik dapat menganalisis keberagaman budaya dan cara + melestarikannya melalui tayangan video dengan baik. + 3. Peserta didik dapat mengevaluasi keberagaman budaya dan cara + melestarikannya melalui kegiatan diskusi kelompok dengan + benar. + 4. Peserta didik dapat membuat komik keberagaman budaya dan cara + melestarikannya melalui pengamatan contoh dengan tepat. + +I. PEMAHAMAN BERMAKNA + +Meningkatkan pemahaman peserta didik untuk mengetahui keberagaman +budaya yang ada di Indonesia. + +J. PERTANYAAN PEMANTIK + 1. Dari tayangan video yang kalian amati tadi, apa yang ada dipikiran + kalian? + 2. Apa manfaat keberagaman budaya? + 3. Sebagai pelajar, cara apa yang bisa kalian lakukan agar dapat membantu + melestarikan keberagaman di Indonesia? + +K. KEGIATAN PEMBELAJARAN + +Kegiatan Pendahuluan (10 menit) + 113 + +1. Guru memberikan salam dan secara acak memberikan kesempatan + kepada salah satu peserta didik untuk memimpin berdoa bersama sesuai + dengan agama dan kepercayaanya masing-masing sebelum pembelajaran + dilaksanakan. + +2. Peserta didik bersama guru menyanyikan lagu nasional (Garuda + Pancasila). + +3. Guru menyapa dan mengecek kehadiran peserta didik. (communication) +4. Guru bertanya jawab dengan peserta didik terkait materi yang akan + + disampaikan hari ini. (apersepsi) +5. Guru menyampaikan tujuan pembelajaran. + +Kegiatan Inti (85 menit) +Tahap 1. Penentuan Pertanyaan/Permasalahan Mendasar +1. Guru memberikan pertanyaan terbuka “mengapa sekarang ketika + + peringatan hari besar seperti hari Kartini, hari pendidikan kita harus + menggunakan pakaian adat?” dan guru juga mempertanyakan “apa + pentingnya melestarikan keberagaman budaya?” (menanya) +2. Guru menjelaskan sedikit mengenai keberagaman budaya. Peserta didik + mendengarkan. +3. Guru memberikan stimulus dengan menayangkan video, peserta didik + mengamati video tersebut tentang cara melestarikan dan pentingnya + keberagaman budaya. (mengamati, TPACK) +4. Peserta didik diminta menyimak sedikit penjelasan yang berhubungan + dengan video yang telah diamati. +5. Peserta didik diarahkan untuk mengemukakan pendapat atau pertanyaan + berkaitan dengan apa yang disampaikan guru. (communication, Critical + Thinking Skills) + +Tahap 2. Mendesain Perencanaan Proyek +6. Peserta didik dibagi menjadi beberapa kelompok yang terdiri dari 4 + + siswa. +7. Guru membagikan LKPD. +8. Peserta didik mendengarkan penjelasan proyek tentang kegiatan peserta + + didik yang akan dilakukan dalam LKPD. (communication) +9. Guru memberikan kesempatan untuk menanyakan hal yang belum + + dipahami siswa. + +Tahap 3. Menyusun Jadwal +10. Guru menjelaskan cara kerja dan bahan apa saja yang dibutuhkan untuk + + menyelesaikan proyek peta keberagaman. (mengamati) +11. Guru meminta peserta didik dalam kegiatan pembelajaran dengan + + bekerjasama dalam kelompoknya. Peserta didik berdiskusi menyusun + rencana pembuatan proyek. +12. Guru dan peserta didik menyepakati waktu penyelesaian. + 114 + +Tahap 4. Memonitoring Peserta Didik dan Kemajuan Proyek +13. Guru memantau keaktifan peserta didik selama melaksanakan proyek dan + + realisasi kemajuan proyek. +14. Peserta didik diberi kesempatan untuk bertanya atau berkonsultasi kepada + + guru apabila mengalami kesulitan. (communication, Critical Thinking + Skills) +15. Peserta didik diminta melanjutkan kegiatan penyelesaian proyek yang + akan didiskusikan dan menyelesaikan tugas sesuai arahan yang sudah + dituangkan dalam LKPD. (Creativity and Innovation, collaboration, + Critical Thinking Skills) + +Tahap 5. Menguji Hasil +16. Peserta didik menyusun bahan laporan untuk presentasi kelompok. + + (communication) +17. Guru memantau keterlibatan peserta didik dan mengukur ketercapaian + + standar. + +Tahap 6. Evaluasi Pengalaman Belajar +18. Peserta didik dibimbing tentang bagaimana cara memaparkan hasil + + proyek di depan kelas. +19. Masing-masing kelompok diminta untuk mempresentasikan hasil proyek. +20. Peserta didik dan kelompok lain memberikan tanggapan/umpan balik + + mengenai hasil presentasi. (communication, Critical Thinking Skills) +21. Guru melakukan kegiatan ice breaking untuk mengembalikan semangat + + belajar. +22. Guru memberikan penguatan hasil presentasi yang telah dilakukan. +23. Guru memberikan apresiasi kepada setiap kelompok dan penghargaan + + bagi kelompok belajar yang paling aktif dan hasil diskusi yang paling + baik. +24. Guru memberikan soal tes kemampuan berpikir kritis kepada siswa untuk + dikerjakan secara individu. + +Kegiatan Penutup (10 menit) +1. Guru bersama peserta didik melakukan refleksi pembelajaran mengenai + + materi pembelajaran pada pertemuan ini. +2. Peserta didik diminta untuk menyampaikan perasaannya selama + + mengikuti pelajaran. (communication) +3. Guru memberikan kesempatan kepada peserta didik untuk + + menyampaikan kesimpulan yang didapat dari keberagaman budaya di + Indonesia dan cara melestarikannya. + 115 + +4. Guru menutup pelajaran dan secara bergantian memberikan + + kesempatan kepada peserta didik lain untuk memimpin berdoa bersama + setelah selesai pembelajaran. + + Mengetahui, Madiun, 29 Mei 2027 + Guru Kelas 4A Mahasiswa + +DEWI NOVITA SARI, S.Pd. ALIFIA NAVRIELDA PUTRI +NIP. 19891117 202221 2 014 NIM. 2002101147 + +L. REFLEKSI + + TABEL REFLEKSI UNTUK PESERTA DIDIK + +N No Pertanyaan Jawaban + 1. Bagaimana materi yang kalian rasa paling + 2. sulit? + 3. Apa yang kalian lakukan untuk dapat lebih + 4. memahami materi ini? + Apakah kalian memiliki cara sendiri untuk + 5. memahami materi ini? + Kepada siapa kalian akan meminta bantuan + untuk memahami materi ini? + Jika kalian diminta memberikan bintamg 1 + sampai 5, berapa bintang yang akan kalian + berikan pada usaha yang kalian lakukan untuk + memahami materi ini? + + TABEL REFLEKSI UNTUK GURU + +N No Pertanyaan Jawaban + 1. Apakah 100% peserta didik mencapai tujuan + 2. pembelajaran? Jika tidak. Berapa persen kira- + 3. kira peserta didik yang mencapi pembelajaran? + Apa kesulitan yang dialami peserta didik + sehingga tidak mencapi tujuan pembelajaran? + Apa yang akan anda lakukan untuk membantu + peserta didik? + Apakah terdapat peserta didik yang tidak + fokus? Bagaimana cara guru agar mereka bisa + fokus pada kegiatan berikutnya? + 116 + +M. ASESMEN/PENILAIAN + Penilaian dapat dilihat melalui tabel berikut ini. + +No. Aspek Bentuk Waktu Pelaksanaan Instrumen + + Setelah Lembar Tes + +1. Pengetahuan Tes pembelajaran (terlampir) + + selesai + + Pada saat Lembar + +2. Keterampilan Pengamatan pembelajaran Pengamatan + + (terlampir) + +N. KEGIATAN PENGAYAAN DAN REMEDIAL + +Pengayaan +Peserta didik dengan nilai rata-rata dan nilai di atas rata-rata mengikuti +pembelajaran dengan mengerjakan soal pengayaan untuk memaksimalkan hasil +yang didapatkan. + +Remedial +Peserta didik yang belum menguasai CP akan melakukan pengulangan materi +dengan pendampingan baik secara individu maupun kelompok. Pendampingan +dapat dilakukan oleh guru atau dengan menerapkan pembelajaran teman sebaya +dan memberikan tugas tambahan untuk memperbaiki hasil belajar. + 117 + +LAMPIRAN +A. BAHAN BACAAN GURU & PESERTA DIDIK + + Kekayaan Budaya Indonesia +A. Keberagaman Budaya + + Indonesia merupakan negara kepulauan. Masing-masing pulau tersebut +didiami oleh suku bangsa tersendiri. Indonesia memiliki banyak susku bangsa +dan adat istiadat yang berbeda-beda, maka Indonesia disebut negara yang +memilik banyak keberagaman. Bangsa Indonesia dibangun dari sejumlah +perbedaan atau keberagaman. Keberagaman Indonesia meliputi suku bangsa, +agama, budaya, dan adat istiadat. Keragaman budaya di Indonesia meliputi, +rumah adat, pakaian tradisonal, tarian adat, upacara adat, alat musik dan lagu +daerah, senjata adat, dan makanan tradisional khas daerah. Bentuk keragaman +budaya Indonesia antara lain sebagai berikut. +1. Upacara Adat + + Upacara adat merupakan upacara yang berhubungan dengan adat + istiadat masyarakat. Upacara adat dilestarikan secara turun temurun dari + generasi ke generasi. Contoh upacara adat adalah, upacara belian yang + dilakukan suku dayak dari kalimatan dan pasola yang dilakukan oleh + masyarakat Nusa Tenggara Timur. + +2. Rumah Adat + Rumah adat merupakan bangunan tempat tinggal yang menjadi ciri + + khas suatu daerah. Rumah adata masing-masing daerah memiliki keunikan + dan kekhasan yang mengandung filosofi luhur budaya setempat. Contoh + rumah adat antara lain, rumah gadang dari Sumatera Barat, rumah + tongkonan dari Sulawesi Selatan, rumah honai dari Papua. + +3. Pakaian Adat + Setiap suku bangsa di Indonesia memiliki gaya busana dan corak + + yang berbeda, baik yang dari segi bentuk, bahan, model maupun warnanya. + Pakaian adat biasanya digunakan saat upacara adat seperti upacara + perkawinan dan pertunjukan seni tradisional. Contoh pakaian adat, yaitu + baju cele dari Maluku, paksian dari Bangka Belitung. + 118 + +4. Alat Musik Daerah + Alat musik daerah merupakan alat musik khas yang biasa dibunyikan + + saat mengiringi lagu atau tarian tradisional setempat. Alat musik daerah + memiliki ciri khas masing-masing sesuai keadaan alam setiap daerah. + Contoh alat musik daerah Antara lain angklung dari Jawa Barat dan sasando + dari Nusa Tenggara Timur + +5. Tarian Adat + Tarian daerah merupakan tarian yang tumbuh dan berkembang di + + suatu daerah. Gerakan tarian daerah menunjukkan kearifan daerah + setempat. Contoh tarian adat antara lain seudati dari Nangru Aceh + Darussalam, lenso dari Maluku, dan maengket dari Sulawesi Utara. + +6. Senjata Tradisional + Beberapa daerah mempunyai senjata tradisional sebagai pelengkap + + dalam acara adat tertentu. Senjata tradisional juga digunakan sebagai + properti tari daerah. Contoh senjata tradisional antara lain, keris dari Jawa + Tengah, Mandau dari Kalimantan Barat, dan celurit dari Jawa Timur. + 119 + +7. Makanan Khas Daerah + Indonesia memiliki kuliner beraneka ragam yang berupa makanan + + khas daerah yang beraneka rupa dan rasa. Contoh makanan khas daerah + adalah gudeg dari Yogyakarta, papeda dari Papua, dan es slendang mayang + dari Jakarta. + +B. Cara Melestarikan Kebudayaan Daerah + Keberagaman budaya daerah agar tidak punah harus dilestarikan dan + + dipertahankan. Berikut cara melestarikan kebudayaan daerah. + 1. Mempelajari dan mengembangkan budaya daerah. + 2. Menonton festival tarian budaya daerah. + 3. Menggunakan pakaian adat ketika hari besar. + 4. Menggunakan bahasa daerah di lingkungan rumah. + 5. Mengadakan dan turut serta dalam kegiatan lomba atau pentas seni di + + daerah sekitar. + 6. Memasukkan dan mempelajari kebudayaan lokal dalam mata pelajaran + + muatan lokal di sekolah. + 7. Mengenalkan produk budaya ke kancah tradisional melalui jejaring sosial + + dengan menggugah foto atau video di media sosial. + 8. Mengekspor dan mempromosikan kebudayaan lokal melalui produk + + kesenian ke luar negeri. +B. MEDIA + + Video Pembelajaran Animasi + Link Youtube: https://youtu.be/cm0Kv7q9u5s?feature=shared + 120 + +C. INSTRUMEN PENILAIAN + +1. SOAL + +a. Pengetahuan + +Terlampir + +b. Keterampilan + +Anggota Kelompok: + +1. 3. + +2. 4. + +Bacalah petunjuk pengerjakan tugas proyek peta keberagaman bersama + +kelompokmu! + +1. Siapkan alat dan bahan berikut untuk mengerjakan tugas proyek! + + a) Gunting c) Pensil warna + + b) Lem d) Atlas + + 2. Potonglah gambar siswa, balon percakapan, dan gambar keberagaman + suatu daerah bersama kelompokmu! + + 3. Setelah digunting, urutkanlah gambar orang dan dialognya agar menjadi + komik kemudian tempelkan pada kertas yang telah disediakan! + + 4. Kemudian tempelkan pada kertas yang telah disediakan!. + 5. Jika sudah selesai, presentasikanlah hasil kerja kelompokmu di depan + + kelas! + +2. PEDOMAN PENILAIAN + +a. Penilaian Pengetahuan (Sumatif) + +Kelas : IV + +Pelajaran/BAB: IPAS/ 6. Indonesia Kaya Budaya + +Topik : B. Kekayaan Budaya Indonesia + +Bentuk Soal : Uraian + + Nomor Soal Jumlah + Skor +No Nama 1 2 + + ab c d e abc d e + +1. ARK +2. AIF +3. ER +4. IAPS +5. JRFP +6. KDS +7. RDM +8. SYC +9. TFS +10. VNF +11. VPRS + 121 + +12. ZZL +13. MAFH +14. AAD +15. FMA +16. FGCS + + RUBRIK SKOR PENILAIAN TES KEMAMPUAN + + BERPIKIR KRITIS SISWA + + Indikator Nomor Keterangan Skor + Kemampuan Soal +Berpikir Kritis + +Interpretation  Tidak menjawab 0 +(Interpretasi) 1.a  Menjawab tetapi tidak tepat 1 + 2. a  Menjawab tetapi kurang 2 + 3 + tepat +  Menjawab dengan tepat + +Analysis 1. b  Tidak menjawab 0 +(Analisis) 2. b  Menjawab tetapi salah 1 + 2 + semua 3 +  Hanya menyebutkan 1 +  Menyebutkan lebih dari 1 + +Evaluation  Tidak menjawab 0 +(Evaluasi) 1 + 1. c  Menjawab tetapi tidak tepat 2 + 2. c  Menjawab tetapi kurang 3 + + tepat + +  Menjawab dengan tepat + +Inference 1. d  Tidak menjawab 0 + +(Kesimpulan) 1. e  Menjawab tetapi tidak tepat 1 + + 2. d  Hanya menyebutkan 1 benar 2 + + 2. e  Menyebutkan 3 benar semua 3 + +Skor maksimal : 30 + +Penilaian : ℎ ℎ × 100 + ℎ + +Panduan Konversi Nilai: + +Konversi Nilai Predikat Klasifikasi + (skala 0-100) + A SB (Sangat Baik) + 90-100 B B (Baik) + 80-89 C C (Cukup) + 70-79 D K (Kurang) + 0-69 + 122 + +b. Penilaian Keterampilan (Formatif) + + LEMBAR PENILAIAN PENGAMATAN HASIL PROYEK + +N No Nama Siswa dapat Kriteria Siswa dapat Total + Mengurutkan menempelkan Skor + 1. ARK percakapan Siswa dapat Seluruh + 2. AIF dengan tepat menggunting gambar + 3. ER keragaman percakapan + 4. IAPS SB B C K + 5. JRFP budaya dan + 6. KDS keragaman + 7. RDM SB B C K + 8. SYC budaya + 9. TFS SB B C K + 10. VNF + 11. VPRS + 12. ZZL + 13. MAFH + 14. AAD + 15. FMA + 16. FGCS + + RUBRIK PENILAIAN PENGAMATAN + + Sangat Baik Cukup Perlu + Bimbingan +No. Kriteria Baik 3 2 + Dapat Kurang 1 + 4 mengurut- dapat Belum + kan gambar mengurut- mampu +1. Kesesuaian Dapat dan kan gambar mengurut- + percaka-pan dan percaka- kan gambar + mengurut- mengurut- dan percaka- + + kan gambar kan + + dan gambar + + percakapan dan + 123 + + percaka- dengan pan ggambar pan perlu + + pan benar, dan dengan bimbingan + + dengan jelas. benar dan guru atau + + benar, jelas. orang tua. + + jelas, dan + + tepat. + +2. Kemam-puan Dapat Dapat Kurang Belum + +menggun- menggun- menggun- dapat mampu + +ting ting ting menggun- menggunting + +keragaman keragaman keragaman ting keragaman + +budaya budaya budaya keragaman budaya + + dengan dengan dengan dengan + + benar, rapi benar. benar, jelas benar, jelas + + dan tepat. dan tepat. dan tepat. + +3. Kemam-puan Dapat Dapat Kurang Belum + +menempel- menempel- menempel dapat mampu + +kan gambar kan kan menempel menempel + +percakapan seluruh beberapa kan seluruh kan seluruh + +dan keberaga- gambar gambar gambar gambar + +man menjadi menjadi menjadi menjadi + +budayanya komik komik komik komik + + beserta beserta beserta beserta + + gambar gambar gambar gambar + + keberaga- keberaga- keberaga- keberaga- + + man man budaya budaya budaya + + budaya dengan dengan dengan tepat. + + dengan tepat. tepat. + + tepat dan + + jelas. + +Skor maksimal : 12 + + () = × 100 + + +Panduan Konversi Nilai: Predikat Klasifikasi + + Konversi Nilai A SB (Sangat Baik) + (skala 0-100) B B (Baik) + C C (Cukup) + 90-100 D K (Kurang) + 80-89 + 70-79 + 0-69 + 124 + +D. GLOSARIUM + + Budaya + Pikiran, akal, budi, hasil, adat istiadat, atau sesuatu yang sudah menjadi kebiasaan + yang suka diubah-ubah. + Capaian pembelajaran + Adalah kemampuan yang diperoleh melalui internalisasi pengetahuan, sikap, + keterampilan, kompetensi, dan akumulasi pengalaman belajar peserta didik. + Daerah + Wilayah (kekuasaan, pemerintahan, pengawasan, dan sebagainya). + Gotong royong + Kerja bersama untuk kepentingan bersama atau sebagai bentuk tolong menolong + yang dilakukan secara sukarela. + Indonesia + Negara dengan berbagai suku bangsa yang mendiami kepulauan. + Kearifan Lokal + Nilai-nilai luhur yang berlaku dalam tata kehidupan masyarakat untuk melindungi + dan mengolah lingkungan hidup secara lestari. + Keberagaman + Perbedaan-perbedaan yang ada dalam kehidupan bermasyarakat. + Kebudayaan + Keseluruhan hasil cipta, rasa, karsa dalam bentuk bahasa, seni, ekonomi, teknologi, + ekspresi beragama, cara kerja, dan sistem. + Metode pembelajaran + Merupakan cara yang dilakukan guru untuk mewujudkan suasana belajar dan proses + pembelajaran agar peserta didik mencapai kompetensi dasar atau seperangkat + indikator yang telah ditetapkan. + Model pembelajaran + Merupakan kerangka konseptual yang melukiskan prosedur yang sistematis dalam + mengorganisasikan pengalaman belajar untuk mencapai tujuan belajar. + Pelajar Pancasila + Perwujudan pelajar Indonesia sebagai pelajar sepanjang hayat yang memiliki + kompetensi global dan berperilaku sesuai dengan nilai-nilai Pancasila, dengan enam + ciri utama: beriman, bertakwa kepada Tuhan Yang Maha Esa, dan berakhlak mulia, + berkebinekaan global, bergotong royong, mandiri, bernalar kritis, dan kreatif. + Pengayaan + Adalah kegiatan yang diberikan kepada peserta didik kelompok cepat agar mereka + dapat mengembangkan potensinya secara optimal dengan memanfaatkan sisa waktu + yang dimilikinya. + Penilaian + Proses pengumpulan dan pengolahan informasi untuk mengukur pencapaian hasil + belajar peserta didik. + 125 + + Peserta didik + Anggota masyarakat yang berusaha mengembangkan potensi diri melalui proses + pembelajaran yang tersedia pada jalur, jenjang, dan jenis pendidikan tertentu. + Rumah Adat + Bangunan tempat tinggal yang menjadi ciri khas suatu daerah. + Refleksi + Aktifitas pikir dan rasa dalam rangka menilasi situasi diri atau situasi lingkungan + untuk menumbuhkan kesadaran yang lebih baik dalam mengaktualisasikan diri. + Suku bangsa + Kesatuan hidup atau sekelompok manusia yanga memiliki kesamaan sistem + interaksi, sistem norma, dan identitas yang sama yang menyatukan. + Tujuan pembelajaran + Merupakan gambaran proses dan hasil belajar yang diharapkan dicapai oleh peserta + didik sesuai dengan capaian pembelajaran. + Upacara Adat + Kegiatan sacral yang berhubungan dengan adat istiadat masyarakat + +E. DAFTAR PUSTAKA + +Amalia Fitri, dkk. 2022. Buku Panduan Guru Ilmu Pengetahuan Alam dan Sosial untuk + SD Kelas IV. Jakarta: Kementerian Pendidikan, Kebudayaan, Riset dan + Teknologi. + +Amalia Fitri, dkk. 2022. Buku Panduan Siswa Ilmu Pengetahuan Alam dan Sosial untuk + SD Kelas IV. Jakarta: Kementerian Pendidikan, Kebudayaan, Riset dan + Teknologi. + + Mengetahui, Madiun, 29 Mei 2027 + Guru Kelas 4A Mahasiswa + +DEWI NOVITA SARI, S.Pd. ALIFIA NAVRIELDA PUTRI +NIP. 19891117 202221 2 014 NIM. 2002101147 + Lampiran 2 Instrumen +A. Perencanaan + + 1) Validasi Modul Ajar Siklus I + + 126 + 127 + 128 + 129 + 130 + 131 + 132 +2) Validasi Modul Ajar Siklus I + 133 + 134 + 135 + 136 + 137 + 138 + +B. Pelaksanaan +1) Lembar Hasil Observasi Proses Pembelajaran Siklus I + +LEMBAR OBSERVASI PROSES PEMBELAJARAN IPAS DENGAN +MODEL PROJECT BASED LEARNING UNTUK MENINGKATKAN + + KEMAMPUAN BERPIKIR KRITIS SISWA + PTK SIKLUS I + +Nama Sekolah : SDN Patihan +Mata Pelajaran : IPAS +Kelas :4 + +Berilah tanda centang (√) pada salah satu kolom “Ya” atau “Tidak” berdasarkan + +observasi keterlaksanaan pembelajaran. + + Penilaian + +No Hal yang diamati Pengamatan Keterangan + + Ya Tidak + + Kegiatan Pendahuluan + + Guru memberikan salam dan secara + + acak memberikan kesempatan + + kepada salah satu siswa untuk Sudah + terlaksana +1. memimpin berdoa bersama sesuai √ + Sudah + dengan agama dan kepercayaanya terlaksana + + masing-masing sebelum Sudah + terlaksana + pembelajaran dilaksanakan. + Sudah + Guru bersama siswa menyanyikan terlaksana, +2. lagu nasional. √ namun hanya + beberapa siswa +3. Guru menyapa dan mengecek √ + kehadiran siswa. yang + menjawab + Guru bertanya jawab dengan siswa +4. terkait materi yang akan √ Sudah + terlaksana + disampaikan hari ini. + +5. Guru menyampaikan tujuan √ + pembelajaran. + + Kegiatan Inti + + PENENTUAN + PERTANYAAN/PERMASALA- + HAN MENDASAR + 139 + + Penilaian + +No Hal yang diamati Pengamatan Keterangan + + Ya Tidak + + Guru memberikan pertanyaan Sudah + terbuka “kalian lebih suka terlaksana + menarikan tarian tradisional daerah +6. atau tari modern?” dan guru juga √ Sudah + mempertanyakan “mengapa banyak terlaksana + orang yang lebih menyukai tarian namun hanya + modern?” sebagian siswa + mendengarkan + Guru menjelaskan sedikit mengenai +7. keberagaman budaya. Siswa √ Sudah + terlaksana + mendengarkan. + Sudah + Guru memberikan stimulus dengan terlaksana + +8. menayangkan video, siswa √ Sudah + mengamati video tersebut tentang terlaksana + namun hanya + keberagaman budaya. beberapa siswa + + Guru memberikan sedikit yang + mengemuka- +9. penjelasan mengenai keberagaman √ kan pendapat + budaya siswa menyimak penjelasan + + tersebut. + + Guru mengarahkan siswa untuk +10. mengemukakan pendapat tentang √ + + apa yang disampaikan oleh guru. + + MENDESAIN PERENCANAAN + PRODUK + + Guru membagi siswa menjadi Sudah +11. beberapa kelompok yang terdiri dari √ terlaksana + + 4 orang siswa. Sudah + Guru memberikan LKPD dan guru terlaksana +12. menjelaskan tugas proyek dan siswa √ + mendengarkan penjelasan tersebut. Sudah + Guru memberikan kesempatan terlaksana +13. untuk menanyakan hal yang belum √ + dipahami siswa, + MENYUSUN JADWAL + 140 + + Penilaian + +No Hal yang diamati Pengamatan Keterangan + + Ya Tidak Sudah + terlaksana + Guru menjelaskan cara kerja dan + Sudah +14. bahan apa saja yang dibutuhkan √ terlaksana + untuk menyelesaikan proyek peta + Sudah + keberagaman. terlaksana + + Guru meminta siswa dalam kegiatan + + pembelajaran dengan bekerjasama + +15. dalam kelompoknya. Siswa √ + + berdiskusi menyusun rencana + + pembuatan proyek. + +16. Guru dan siswa menyepakati waktu √ + penyelesaian. + + MEMONITORING SISWA DAN + KEMAJUAN PROYEK + + Guru memantau keaktifan siswa Sudah +17. selama melaksanakan proyek dan √ terlaksana + namun belum + realisasi kemajuan proyek. + optimal + Siswa diberi kesempatan untuk Sudah +18. bertanya atau berkonsultasi kepada √ terlaksana + + guru apabila mengalami kesulitan. Sudah + terlaksana + Guru meminta siswa melanjutkan + Sudah + kegiatan penyelesaian proyek yang terlaksana + +19. akan didiskusikan dan √ Sudah + terlaksana + menyelesaikan tugas sesuai arahan namun belum + + yang sudah dituangkan dalam optimal + + LKPD. Sudah + terlaksana + MENGUJI HASIL + Guru meminta siswa untuk +20. menyusun bahan laporan presentasi √ + kelompok. + + Guru memantau keterlibatan peserta +21. didik dan mengukur ketercapaian √ + + standar. + + EVALUASI PENGALAMAN + BELAJAR + Guru membimbing siswa tentang +22. bagaimana cara memaparkan hasil √ + proyek di depan kelas. + 141 + + Penilaian + +No Hal yang diamati Pengamatan Keterangan + + Ya Tidak + + Guru meminta siswa Sudah + terlaksana +23. mempresentasikan hasil kerja √ namun belum + + kelompok di depan kelas. optimal + Sudah + Guru memberikan kesempatan pada terlaksana + namun hanya +24. kelompok lain untuk menanggapi √ satu kelompok + dan memberikan masukan mengenai saja yang + memberikan + hasil kelompok yang presentasi. tanggapan + Sudah + Guru melakukan kegiatan ice terlaksana, +25. breaking untuk mengembalikan √ namun kurang + semangat + semangat belajar. Sudah + terlaksana +26. Guru memberikan penguatan hasil √ namun belum + presentasi yang telah dilakukan. optimal + + Guru memberikan apresiasi kepada Sudah + terlaksana + setiap kelompok dan penghargaan + Sudah +27. bagi kelompok belajar yang paling √ terlaksana + + aktif dan hasil diskusi yang paling Sudah + terlaksana + baik. namun belum + + Guru memberikan soal tes optimal + +28. kemampuan berpikir kritis kepada √ Sudah + siswa untuk dikerjakan secara terlaksana + + individu. Sudah + terlaksana + Kegiatan Penutup namun hanya + beberapa siswa + Guru bersama siswa melakukan yang mau + + refleksi pembelajaran mengenai +29. materi pembelajaran pada √ + + pertemuan ini. + + Guru meminta siswa untuk + +30. menyampaikan perasaannya √ + + selama mengikuti pelajaran. + + Guru memberikan kesempatan + + kepada peserta didik untuk + +31. menyampaikan kesimpulan yang √ + + didapat dari keberagaman budaya + + di Indonesia. + 142 + +No Hal yang diamati Penilaian Keterangan + Pengamatan + + Ya Tidak + + menyampaikan + kesimpulan + + Guru menutup pelajaran dan √ Sudah + secara bergantian memberikan terlaksana +32. kesempatan kepada siswa lain + untuk memimpin berdoa bersama + setelah selesai pembelajaran. + 143 + +2) Lembar Hasil Observasi Proses Pembelajaran Siklus II + + LEMBAR OBSERVASI PROSES PEMBELAJARAN IPAS DENGAN + MODEL PROJECT BASED LEARNING UNTUK MENINGKATKAN + + KEMAMPUAN BERPIKIR KRITIS SISWA + PTK SIKLUS II + +Nama Sekolah : SDN Patihan +Mata Pelajaran : IPAS +Kelas :4 + +Berilah tanda centang (√) pada salah satu kolom “Ya” atau “Tidak” berdasarkan + +observasi keterlaksanaan pembelajaran. + + Penilaian + +No. Hal yang diamati Pengamatan Keterangan + + Ya Tidak + + Kegiatan Pendahuluan + + Guru memberikan salam dan secara + + acak memberikan kesempatan kepada + +1. salah satu siswa untuk memimpin √ Sudah + berdoa bersama sesuai dengan agama terlaksana + + dan kepercayaanya masing-masing Sudah + terlaksana + sebelum pembelajaran dilaksanakan. + Sudah + Guru bersama siswa menyanyikan lagu √ terlaksana +2. nasional. + Sudah +3. Guru menyapa dan mengecek √ terlaksana + kehadiran siswa. + Sudah + Guru bertanya jawab dengan siswa terlaksana +4. terkait materi yang akan disampaikan √ + + hari ini. + +5. Guru menyampaikan tujuan √ + pembelajaran. + + Kegiatan Inti Sudah + terlaksana + PENENTUAN + PERTANYAAN/PERMASALA- + HAN MENDASAR + + Guru memberikan pertanyaan terbuka + “mengapa sekarang ketika peringatan + hari besar seperti hari Kartini, hari +6. pendidikan kita harus menggunakan √ + pakaian adat?” dan guru juga + mempertanyakan “apa pentingnya + melestarikan keberagaman budaya?” + 144 + + Penilaian + +No. Hal yang diamati Pengamatan Keterangan + + Ya Tidak Sudah + terlaksana + Guru menjelaskan sedikit mengenai +7. keberagaman budaya. Siswa √ Sudah + terlaksana + mendengarkan. + Guru memberikan stimulus dengan Sudah + menayangkan video, siswa mengamati terlaksana +8. video tersebut tentang cara √ + melestarikan dan pentingnya Sudah + keberagaman budaya. terlaksana + + Guru memberikan sedikit penjelasan Sudah +9. mengenai keberagaman budaya siswa √ terlaksana + + menyimak penjelasan tersebut. Sudah + terlaksana + Guru mengarahkan siswa untuk +10. mengemukakan pendapat tentang apa √ Sudah + terlaksana + yang disampaikan oleh guru. + Sudah + MENDESAIN PERENCANAAN terlaksana + PRODUK + Sudah + Guru membagi siswa menjadi beberapa terlaksana +11. kelompok yang terdiri dari 4 orang √ + Sudah + siswa. terlaksana + + Guru memberikan LKPD dan guru Sudah +12. menjelaskan tugas proyek dan siswa √ terlaksana + + mendengarkan penjelasan tersebut. + + Guru memberikan kesempatan untuk +13. menanyakan hal yang belum dipahami √ + + siswa, + + MENYUSUN JADWAL + + Guru menjelaskan cara kerja dan bahan + +14. apa saja yang dibutuhkan untuk √ + menyelesaikan proyek komik + + keberagaman. + + Guru meminta siswa dalam kegiatan + +15. pembelajaran dengan bekerjasama √ + dalam kelompoknya. Siswa berdiskusi + + menyusun rencana pembuatan proyek. + +16. Guru dan siswa menyepakati waktu √ + penyelesaian. + + MEMONITORING SISWA DAN + KEMAJUAN PROYEK + + Guru memantau keaktifan siswa selama +17. melaksanakan proyek dan realisasi √ + + kemajuan proyek. + 145 + + Penilaian + +No. Hal yang diamati Pengamatan Keterangan + + Ya Tidak Sudah + terlaksana + Siswa diberi kesempatan untuk +18. bertanya atau berkonsultasi kepada √ Sudah + terlaksana + guru apabila mengalami kesulitan. + Sudah + Guru meminta siswa melanjutkan terlaksana + kegiatan penyelesaian proyek yang +19. akan didiskusikan dan menyelesaikan √ Sudah + tugas sesuai arahan yang sudah terlaksana + dituangkan dalam LKPD. + MENGUJI HASIL Sudah + terlaksana +20. Guru meminta siswa untuk menyusun √ + bahan laporan presentasi kelompok. Sudah + terlaksana + Guru memantau keterlibatan peserta +21. didik dan mengukur ketercapaian √ Sudah + terlaksana + standar. + Sudah + EVALUASI PENGALAMAN terlaksana + BELAJAR + Sudah + Guru membimbing siswa tentang terlaksana +22. bagaimana cara memaparkan hasil √ + Sudah + proyek di depan kelas. terlaksana + + Guru meminta siswa Sudah + terlaksana +23. mempresentasikan hasil kerja √ + kelompok di depan kelas. + + Guru memberikan kesempatan pada + + kelompok lain untuk menanggapi dan +24. memberikan masukan mengenai hasil √ + + kelompok yang presentasi. + + Guru melakukan kegiatan ice breaking + +25. untuk mengembalikan semangat √ + belajar. + + Guru memberikan penguatan hasil + +26. presentasi yang telah dilakukan. √ + + Guru memberikan apresiasi kepada + setiap kelompok dan penghargaan bagi +27. kelompok belajar yang paling aktif dan √ + hasil diskusi yang paling baik. + + Guru memberikan soal tes kemampuan +28. berpikir kritis kepada siswa untuk √ + + dikerjakan secara individu. + 146 + +No. Hal yang diamati Penilaian Keterangan + Pengamatan + + Ya Tidak + + Kegiatan Penutup + + Guru bersama siswa melakukan + +29. refleksi pembelajaran mengenai √ Sudah + materi pembelajaran pada pertemuan terlaksana + + ini. + + Guru meminta siswa untuk √ Sudah +30. menyampaikan perasaannya selama terlaksana + + mengikuti pelajaran. √ Sudah + terlaksana + Guru memberikan kesempatan + kepada peserta didik untuk +31. menyampaikan kesimpulan yang + didapat dari keberagaman budaya di + Indonesia. + + Guru menutup pelajaran dan secara √ Sudah + bergantian memberikan kesempatan terlaksana +32. kepada siswa lain untuk memimpin + berdoa bersama setelah selesai + pembelajaran. + 147 + +C. Hasil + +1) Soal Tes Siklus I + + SOAL TES SIKLUS I + +Pelajaran/BAB: IPAS/ Indonesia Kaya Budaya Nama : + +Topik : B. Kekayaan Budaya Indonesia No. Abs : + +Hari, tanggal : Nilai : + +Jawablah pertanyaan-pertanyaan di bawah ini dengan benar! +1. Bacalah cerita di bawah ini untuk menjawab pertanyaan dari abjad a-e! + + Di suatu hari terdapat seorang anak SD bernama Eva sedang + menghampiri teman-temannya yang bermain di taman. Ia memakai baju + sabrina dengan rok selutut yang dilengkapi juga menggunakan sepatu sneakers. + Ketika berpergian, Eva sering melihat orang-orang memakai baju kekurangan + bahan dan brand-brand dari luar negeri. Ia pun tertarik untuk menggunakan + budaya luar tersebut sehingga sekarang dia langsung memakai dan meniru gaya + berpakaian budaya luar tanpa disaring atau pikir ulang. Ketika Eva sampai di + taman, teman-temannya yang melihat merasa gaya berpakaian Eva terlalu + dewasa dan kurang cocok dipakainya. + + Jawablah pertanyaan di bawah ini sesuai dengan bacaan di atas! + + a) Menurut Anda bagaimana penampilan Eva? + b) Dari cerita di atas apabila hal tersebut terus dilakukan, menurut Anda + + apakah yang akan terjadi? + c) Upaya apa yang dapat Anda lakukan agar Eva dapat menghindari + + pemakaian budaya luar negeri tersebut? Berikan contohnya! + d) Bagaimanakah tanggapan Anda mengenai masih adanya siswa yang + + menggunakan budaya daerah di Indonesia? + e) Apa saja pakaian daerah di Indonesia dan berasal dari mana sajakah + + asalnya? + +2. Bacalah percakapan di bawah ini untuk menjawab pertanyaan dari abjad a-e! + Michelle : “Eh Putri kamu tadi lagi ngapain sih?” + +Putri : “Aku baru aja selesai menari jaipong.” +Michelle : “Apaan tuh tari jaipong? Kok terlihat jadul.” +Putri : “Tari jaipong itu adalah tarian tradisional yang berasal dari + + jawa Barat. Ini gak jadul kok, malah terlihat indah gemulai.” + 148 + +Michelle “Tapi kok lebih bagusan tarian modern aku lhoh, terlihat +Putri keren dan energik.” +Michelle +Putri : “Iya, tapi tari tradisional juga memiliki arti lhoh.” + +Michelle : “Masak sih?” +Putri : “Iya tari jaipong ini menceritakan tentang sifat wanita Sunda + +Michelle yang memiliki berbagai kelebihan, seperti pantang +Putri menyerah, dan energik, berani, ramah, lincah, mandiri dan + bertanggung jawab, namun tetap santun.” +Michelle +Putri : “Oh, tapi tarian aku ini berasal dari luar negeri lhoh, keren + kan.” + + : “Iya tapi alangkah baiknya kalau kita juga melestarikan + budaya lokal sebagai orang Indonesia agar budaya tersebut + tidak punah.” + + : “Begitu ya?” + + : “Iya makannya kamu harus banyak cari pengetahuan tentang + budaya yang ada di Indonesia terlebih budaya daerah atau + tradisional.” + + : “Oke deh nanti aku akan belajar tentang budaya Indonesia + lebih banyak.” + + : “Oke semangat!” + +Jawablah pertanyaan di bawah ini sesuai dengan isi percakapan di atas! + +a) Menurut Anda, bagaimanakah sikap Michelle? +b) Dari cerita di atas apabila Michelle tidak mau mempelajari budaya daerah + + Indonesia, menurut Anda apakah yang akan terjadi? +c) Bagaimana cara Anda membujuk Michelle agar tertarik mempelajari + + budaya daerah Indonesia? +d) Bagaimanakah tanggapan Anda mengenai sikap Putri? +e) Apa saja tarian daerah yang ada di Indonesia dan dari mana asalnya? + 149 + + Kunci Jawaban +1. Jawaban abjad a-e sebagai berikut: + + a) Pakaian yang digunakan Eva tidak sopan dan kurang cocok dipakai untuk + anak usia SD karena terlalu dewasa. + + b) Anak usia SD lebih mengenal budaya luar negeri yang semakin + berkembang dan menjadi tidak mengenal budaya daerah. + + c) Upaya yang harus dilakukan Eva untuk menghindari pemakaian budaya + luar negeri: +  Memberikan contoh dengan cara mengajaknya berpakaian sopan sesuai + di Indonesia. +  Mengenalkan pakaian-pakaian adat dengan mengajak ke pameran + budaya atau menonton video keberagaman. +  Mengajak memakai pakaian adat ketika peringatan hari besar, seperti + hari Kartini. + + d) Bagus dan sopan karena mau melestarikan budaya daerah. + e) Pakaian daerah di Indonesia : + +  Kebaya = Jawa Timur +  Ule Balang = Aceh +  Koto Gadang = Sumatera Barat + +2. Jawaban abjad a-e sebagai berikut: + a) Michelle anak yang mau menang sendiri dan bangga akan budaya luar + negeri. + b) Menjadi tidak tahu mengenai bahasa daerah sehingga budaya daerah akan + punah dan budaya luar negeri makin berkembang. + c) Cara membujuk Michelle agar tertarik mempelajari budaya daerah + Indonesia: +  Memberikan contoh dengan mengajaknya menonton tarian daerah. +  Mengajar ke festival pameran budaya. +  Memberi pembelajaran tentang kebudayaan daerah. + d) Sikap Putri baik mau menghargai dan melestarikan budaya daerah. + e) Tarian daerah yang ada di Indonesia : +  Tari Remo = Jawa Timur +  Tari Topeng = Jawa Barat +  Tari Serimpi = Jawa Tengah + 150 +2) Validasi Soal Tes Siklus I + 151 + 152 + +3) Soal Tes Siklus II + + SOAL TES SIKLUS II + +Pelajaran/BAB: IPAS/ Indonesia Kaya Budaya Nama : + +Topik : B. Kekayaan Budaya Indonesia No. Abs : + +Hari, tanggal : Nilai : + +Jawablah pertanyaan-pertanyaan di bawah ini dengan benar! +1. Bacalah cerita di bawah ini untuk menjawab pertanyaan abjad a-e! + + Di suatu Hari SDN 1 Manisrejo mengadakan pameran festival budaya + Indonesia. Pameran ini berisikan berbagai macam keberagaman budaya daerah + di Indonesia yang mana setiap kelasnya dari pulau yang berbeda-beda. Setiap + anak memakai pakaian adat daerah sesuai provinsi yang telah ditentukan dan + memerkan berbagai macam alat musik tradisional, makanan khas daerah dan + gambar-gambar atau lukisan rumah adat. Namun di kelas 4A terdapat 5 siswa + yang tidak mau menggunakan pakaian adat daerah. Mereka hanya + menggunakan celana pensil, rok, dan baju seadanya. Ke lima anak tersebut + berjalan santai menuju tempat puncak acara. Mereka tidak mau mengunjungi + setiap bilik yang berisikan keberagaman budaya daerah. Mereka berpikir itu + adalah hal kuno yang tidak perlu dipamerkan di zaman yang serba modern + seperti sekarang. Padahal keberagaman budaya daerah penting untuk + dilestarikan agar kita sebagai generasi penerus bangsa tidak lupa akan budaya + daerah dan dapat memberikan penghormatan terhadap leluhur kita serta + sebagai penguat identitas lokal. + Jawablah pertanyaan di bawah ini sesuai dengan bacaan di atas! + a. Menurut Anda, bagaimanakah sikap ke lima anak yang tidak mau memakai + + pakaian adat tersebut? + b. Menurut Anda, apa yang akan terjadi apabila kita tidak bisa menghargai + + kebudayaan daerah? + c. Bagaimana cara Anda membujuk ke lima anak tersebut agar mau ikut serta + + melestarikan budaya daerah di Indonesia? + d. Bagaimanakah tanggapan Anda mengenai pentingnya melestarikan + + keberagaman budaya daerah? + e. Sebutkan 3 saja keberagaman budaya yang ada di provinsi Sumatera Barat! + +2. Bacalah percakapan di bawah ini untuk menjawab pertanyaan dari abjad a-e! + +Ibu : “Ndok arep nangdi?” + 153 + +Siti : “Kula badhe medhal teng toko buku Bu, kalihan rencang kula +Ibu Shinta.” +Siti +Siti : “Oalah yowes ati-ati ya Sit, muleh e aja sore-sore.” +Chika : “Nggih Bu.” +Siti +Chika “Ayo Chik.” +Siti : “Sit kamu ngomong apa tadi? Bahasa daerah ya?” + : “Iya Chik, aku kalau ngomong sama orang yang lebih tua +Chika +Siti memakai basa jawa. + : “Kenapa begitu? Kan pakai bahasa Indonesia tidak masalah.” +Chika : “Aku dari kecil sudah diajarkan seperti itu Chik, selain untuk +Siti + menghormati orang yang lebih tua, kita juga dapat +Chika mempertahankan bahasa daerah kita agar tidak hilang.” + : “Iya tapikan sekarang udah modern bahasanya juga udah gaul- + gaul tau.” + : “Alangkah baiknya kita sebagai generasi penerus bangsa mau + tetap melestarikan bahasa dan budaya daerah di Indonesia + Chik, kita tidak boleh lupa dengan peninggalan sejarah ini. + Kalau bukan kita yang melestarikan mau siapa lagi?” + : “Ya itu sih kamu aja Sit, aku enggak ah gak ngerti.” + : “Nah kalau gak ngerti ayo kita belajar bareng melestarikan + budaya daerah dari yang gmpang-gampang seperti + menggunakan bahasa daerah.” + : “Udahlah Sit, zamannya udah beda realistis aja saat ini + bagaimana.” + +Jawablah pertanyaan di bawah ini sesuai dengan isi percakapan di atas! + +a. Menurut Anda, bagaimanakah sikap Chika? +b. Menurut Anda, apa yang akan terjadi apabila kita tidak bisa + + mempertahankan kebudayaan daerah? +c. Bagaimana cara Anda membujuk Chika agar mau ikut serta melestarikan + + budaya daerah di Indonesia? +d. Bagaimanakah tanggapan Anda mengenai sikap Siti yang masih mau + + menggunakan bahasa daerah? +e. Sebutkan 3 saja keberagaman budaya yang ada di provinsi Jawa Tengah? + 154 + + Kunci Jawaban +1. Jawaban abjad a-e sebagai berikut: + + a) Sikap kelima anak tersebut egois, mau menang sendiri, dan kurang + menghargai kebudayaan daerah. + + b) Budaya asing yang masuk akan terus berkembang sedangkan budaya + daerah Indonesia semakin hilang. + + c) Cara membujuk ke lima anak tersebut agar mau ikut serta melestarikan + budaya daerah di Indonesia: +  Tetap mengajak ke pameran budaya atau menonton video + keberagaman budaya. +  Mengajak memakai pakaian adat ketika peringatan hari besar, seperti + hari Kartini. +  Memberi tahu pentingnya melestarikan budaya daerah. + + d) Melestarikan kebudayaan daerah penting karena dilestarikan agar kita + sebagai generasi penerus bangsa tidak lupa akan budaya daerah dan dapat + memberikan penghormatan terhadap leluhur kita serta sebagai penguat + identitas lokal. + + e) Keberagaman budaya yang ada di provinsi Sumatera Barat: +  Pakaian koto gadang +  Makanan rendang +  Tari piring + +2. Jawaban abjad a-e sebagai berikut: + a) Sikap Chika yaitu tidak peduli, tidak mau tahu dan tidak mengahargai + Bahasa daerah. + b) Budaya asing yang masuk akan terus berkembang sedangkan budaya + daerah Indonesia semakin hilang. + c) Cara membujuk Chika agar mau ikut serta melestarikan budaya daerah di + Indonesia: +  Memberikan contoh dengan mengajaknya menonton tarian daerah. +  Mengajar ke festival pameran budaya. +  Memberi pembelajaran tentang kebudayaan daerah. + d) Sikap Siti baik, sopan dan santu karena mau menghargai dan + melestarikan budaya daerah. + e) Keberagaman budaya yang ada di provinsi Jawa Tengah: +  Pakaian kebaya jangkep +  Makanan tempe mendoan +  Tari Serimpi + 155 +4) Validasi Soal Tes Siklus II + 156 + Lampiran 3 Data Penelitian +A. Daftar Nilai Siswa Pra siklus + + DAFTAR NILAI SISWA SEBELUM PENERAPAN MODEL + + PROJECT BASED LEARNING + +No. Nama Nilai Keterangan (KKM 75) + 63 Tidak Tuntas +1. ARK 57 Tidak Tuntas + 77 Tuntas +2. AIF 60 Tidak Tuntas + 63 Tidak Tuntas +3. ER 77 Tuntas + 77 Tuntas +4. IAPS 53 Tidak Tuntas + 57 Tidak Tuntas +5. JRFP 90 Tuntas + 60 Tidak Tuntas +6. KDS 57 Tidak Tuntas + 60 Tidak Tuntas +7. RDM 77 Tuntas + 63 Tidak Tuntas +8. SYC 77 Tuntas + 1068 +9. TFS 67 + 6 +10. VNF 37,5 + 10 +11. VPRS + 62,5% +12. ZZL 37,5 + +13. MAFH + +14. AAD + +15. FMA + +16. FGCS + + Jumlah Nilai + + Rata-Rata + + Siswa Tuntas + + Presentase Tuntas + + Siswa Tidak Tuntas + +Presentase Tidak Tuntas + + Ketuntasan Klasikal + + 157 + 158 + +B. Daftar Nilai Siswa Siklus I + +DATA HASIL TES KEMAPUAN BERPIKIR KRITIS SISWA SIKLUS I + +No Nama Nilai Keterangan (KKM 75) + 87 Tuntas +1. ARK 67 + 80 Tidak Tuntas +2. AIF 63 Tuntas + 67 +3. ER 80 Tidak Tuntas + 77 Tidak Tuntas +4. IAPS 70 + 80 Tuntas +5. JRFP 93 Tuntas + 60 Tidak Tuntas +6. KDS 80 Tuntas + 77 Tuntas +7. RDM 83 Tidak Tuntas + 67 Tuntas +8. SYC 90 Tuntas + 93 Tuntas +9. TFS 60 Tidak Tuntas + 76 Tuntas +10. VNF 10 + +11. VPRS 62,5% + 6 +12. ZZL + 37,5% +13. MAFH 62,5% + +14. AAD + +15. FMA + +16. FGCS + + Nilai Tertinggi + + Nilai Terendah + + Rata-Rata + + Siswa Tuntas + + Presentase Tuntas + + Siswa Tidak Tuntas + +Presentase Tidak Tuntas + + Ketuntasan Klasikal + 159 + +C. Daftar Nilai Siswa Siklus II + +DATA HASIL TES KEMAPUAN BERPIKIR KRITIS SISWA SIKLUS II + +No Nama Nilai Keterangan (KKM 75) + 90 Tuntas +1. ARK 67 + 83 Tidak Tuntas +2. AIF 80 Tuntas + 87 Tuntas +3. ER 93 Tuntas + 87 Tuntas +4. IAPS 73 Tuntas + 83 +5. JRFP 93 Tidak Tuntas + 80 Tuntas +6. KDS 87 Tuntas + 77 Tuntas +7. RDM 87 Tuntas + 77 Tuntas +8. SYC 93 Tuntas + 93 Tuntas +9. TFS 67 Tuntas + 82 +10. VNF 14 + +11. VPRS 87,5% + 2 +12. ZZL + 12,5% +13. MAFH 87,5% + +14. AAD + +15. FMA + +16. FGCS + + Nilai Tertinggi + + Nilai Terendah + + Rata-Rata + + Siswa Tuntas + + Presentase Tuntas + + Siswa Tidak Tuntas + +Presentase Tidak Tuntas + + Ketuntasan Klasikal + Lampiran 4 Dokumentasi +A. Dokumentasi Siklus I + + Kegiatan perencanaan pembelajaran siklus I + + Kegiatan pelaksanaan pembelajaran siklus I + 160 + 161 +Siswa Mengerjakan Soal Tes Siklus I + + Lembar Jawaban Siswa Siklus I + 162 +B. Dokumentasi Siklus II + + Kegiatan perencanaan pembelajaran siklus II + + Kegiatan Pelaksanaan Pembelajaran Siklus II + 163 +Siswa Mengerjakan Soal Tes Siklus II + + Lembar Jawaban Siswa Siklus II + Lampiran 5 Surat +A. Surat Izin Penelitian + + 164 + 165 +B. Surat Balasan + Lampiran 6 Lembar Persetujuan Judul Skripsi + 166 + Lampiran 7 Lembar Persetujuan Ujian Skripsi + 167 + Lampiran 8 Berita acara dan Validasi Pustaka + 168 + 169 + 170 + 171 + 172 + 173 + 174 + 175 + 176 + Lampiran 9 Daftar Riwayat Hidup + Riwayat Hidup + + Penulis bernama lengkap Alifia Navrielda Putri. Lahir di Kota Madiun +pada tanggal 14 November 2001. Penulis merupakan anak pertama dari 3 +bersaudara. Penulis beralamat di Jalan Indra Manis IV/18, Kec Taman, Kota +Madiun. Penulis memulai pendidikannnya di SDN 03 Manisrejo kemudian +pendidikan selanjutnya di SMPN 4 Madiun lalu ke jenjang SMAN 5 Madiun. Saat +ini penulis sedang menempuh pendidikan S1 jurusan Pendidikan Guru Sekolah +Dasar di Universitas PGRI Madiun angkatan 2020. Pengalaman organisasi yang +diikuti penulis adalah pramuka di Universitas PGRI Madiun. Penulis pernah +mengikuti Seminar Karya Ilmiah dasar sebagai pemakalah pada tahun 2024. Sekian +dari penulis semoga skripsi berjudul Penerapan Model Project Based Learning +untuk Meningkatkan Kemampuan Berpikir Kritis Siswa kelas 4 SDN Patihan +bermanfaat untuk pembaca. + + 177 + diff --git a/storage/app/books/mtk.pdf b/storage/app/books/mtk.pdf new file mode 100644 index 0000000..fa367bf --- /dev/null +++ b/storage/app/books/mtk.pdf @@ -0,0 +1,6691 @@ + MATEMATIKA MATEMATIKA DASAR + DASAR + Rahmawati Patta, Latri, Bahar Rahmawati Patta Latri Bahar + Matematika merupakan ilmu dasar yang sangat diperlukan untuk + landasan bagi teknologi dan pengetahuan modern. Apakah MATEMATIKA + matematika itu?. tentu tidak dapat dengan mudah dijawab dengan DASAR + satu kalimat begitu saja. Berbagai pendapat muncul tentang + pengertian matematika tersebut, dipandang dari pengetahuan dan + pengalaman masing-masing yang berbeda. Para pakar matematika + memberi definisi atau pengertian tentang matematika menurut sudut + pandang masing-masing. Ada yang mengatakan bahwa matematika + adalah bahasa simbol; matematika merupakan bahasa numerik; + matematika adalah bahasa yang dapat menghilangkan sifat kabur, + majemuk, dan emosional; matematika adalah metode berpikir logis; + matematika adalah sarana berpikir; matematika adalah logika pada + masa dewasa; matematika adalah ratunya ilmu dan sekaligus menjadi + pelayannya; matematika adalah sains mengenai kuantitas dan besaran; + matematika adalah sains yang bekerja menarik kesimpulan- + kesimpulan yang perlu; matematika adalah sains formal yang murni; + matematika adalah sains yang memanipulasi simbol; matematika + adalah ilmu tentang bilangan dan ruang; matematika adalah ilmu yang + memmpelajari hubungan pola, bentuk, dan struktur; matematika + adalah ilmu yang abstrak dan deduktif, matematika adalah aktivitas + manusia. Bagian yang dijabarkan dalam buku ini diantaranya : + Pemecahan Masalah Matematika, Penalaran Matematika, Logika, + Himpunan, Relasi Dan Fungsi, Persamaan Dan Pertidaksamaan, + Trigonometri + +BADAN PENERBIT UNM + +Alamat: Gedung Perpustakaan Lt.1 Kampus UNM Gunung Sari Baru +Jl. Raya Pendidikan 90222, Kota Makassar, Sulawesi Selatan +Telp/WA +62 852-5522-0015 +62 853-9750-1407 +62 822-3292-8654 +Email: badanpenerbit@unm.ac.id | badanpenerbitunm@gmail.com +website: badanpenerbit.unm.ac.id + MATEMATIKA + DASAR + + Rahmawati Patta + Latri + Bahar + +Reviewer: Erma Suryani Sahabuddin + Matematika Dasar + + Hak Cipta @ 2021 oleh Rahmawati Patta, Latri, Bahar + + Hak cipta dilindungi undang-undang + Cetakan pertama, Oktober 2021 + + Diterbitkan oleh Badan Penerbit UNM + Gedung Perpustakaan Lt. 1 Kampus UNM Gunungsari + + Jl. Raya Pendidikan 90222 + Tlp./Fax. (0411) 865677 / (0411) 861377 + + Email: badanpenerbit@unm.ac.id & + badanpenerbitunm@gmail.com + + Website: badanpenerbit.unm.ac.id + +Layouter & Desain Cover: Muhammad Rafli Pradana, S.Ds. + (Badan Penerbit UNM) + + ANGGOTA IKAPI No. 011/SSL/2010 + ANGGOTA APPTI No. 006.063.1.10.2018 + + Dilarang memperbanyak buku ini dalam bentuk + apapun tanpa izin tertulis dari penerbit + + v, 183 hlm; 23 cm + + ISBN 978-623-387-008-5 + KATA PENGANTAR + + Puji syukur dipanjatkan kepada Illahi Rabbi Sang +Penguasa Jagat Raya, yang menciptakan segalanya dan +mengatur kehidupan makhluknya yang begitu sistematis +sehingga apapun yang terjadi di semua Alam tidak ada yang +secara kebetulan. Marilah kita sejenak mengirimkan doa +kepada para nabi Allah yang menyampaikan kebenaran +Tauhid. Kemudian terkhusus buat Rasulullah Muhammad saw +marilah kita bersalawat kepadanya semoga kita termasuk +orang yang mendapatkan syafaat di kehidupan selanjutnya. + + ”Apakah matematika itu?” tidak dapat dengan mudah +dijawab dengan satu kalimat begitu saja. Berbagai pendapat +muncul tentang pengertian matematika tersebut, dipandang +dari pengetahuan dan pengalaman masing-masing yang +berbeda. Para pakar matematika memberi definisi atau +pengertian tentang matematika menurut sudut pandang +masing-masing. Ada yang mengatakan bahwa matematika +adalah bahasa simbol; matematika merupakan bahasa +numerik; matematika adalah bahasa yang dapat +menghilangkan sifat kabur, majemuk, dan emosional; +matematika adalah metode berpikir logis; matematika adalah +sarana berpikir; matematika adalah logika pada masa dewasa; +matematika adalah ratunya ilmu dan sekaligus menjadi +pelayannya; matematika adalah sains mengenai kuantitas dan +besaran; matematika adalah sains yang bekerja menarik +kesimpulan-kesimpulan yang perlu; matematika adalah sains +formal yang murni; matematika adalah sains yang + + ( i ) Dasar Matematika + memanipulasi simbol; matematika adalah ilmu tentang +bilangan dan ruang; matematika adalah ilmu yang +memmpelajari hubungan pola, bentuk, dan struktur; +matematika adalah ilmu yang abstrak dan deduktif, +matematika adalah aktivitas manusia. + + Mahasiswa yang sedang menuntuk ilmu pengetahuan +di perguruan tinggi harus mempelajari matematika, paling +tidak matematika dasar. Untuk membantu mahasiswa maka +kami berusaha menyusun bahan ajar ini, terutama digunakan +dalam mata kuliah pengantar dasar matematika pada +semester dua. + + Penyusun menyadari bahwa baik isi maupun cara +penyusunan buku ini masih jauh dari kesempurnaan. Oleh +karena itu, segala saran, tegur sapa, dan kritik yang +membangun sangat penyusun harapkan. Demikianlah, +mudah-mudahan buku ini bergunan dan dapat dimanfaatkan +sebaik-baiknya. + + Makassar, September 2020 + + Penulis + + ( ii ) Dasar Matematika + DAFTAR ISI + +KATA PENGANTAR (i) + +DAFTAR ISI ( ii ) + +BAB 1 PEMECAHAN MASALAH MATEMATIKA (1) + +A. Pengertian Masalah (2) + +B. Masalah Rutin dan Tidak Rutin (6) + +C. Klasifikasi Masalah Matematika (11) + +D. Pembelajaran Pemecahan Masalah Matematika (13) + +E. Langkah-langkah Pemecahan Masalah (15) + +F. Rangkuman (30) + +G. Latihan (31) + +BAB 2 PENALARAN MATEMATIKA (35) + +A. Penalaran Induktif (38) + +B. Penalaran Deduktif (39) + +C. Langkah-Langkah Dalam Penalaran + +Induktif & Deduktif (41) + +D. Rangkuman (44) + +E. Latihan (45) + +BAB 3 LOGIKA (47) + +A. Pernyataan (48) + +B. Kalimat Terbuka (48) + +C. Pernyataan (48) + +D. Ingkaran dari Pernyataan (50) + +E. Pernyataan Tunggal dan Majemuk (50) + +F. Tabel Kebenaran Pernyataan (51) + + ( iii ) Dasar Matematika + G. Operasi Logika (53) + +H. Konjungsi (54) + +I. Disjungsi (55) + +J. Implikasi (56) + +K. Biimplikasi (57) + +L. Bentuk-Bentuk Pernyataan (58) + +M. Kuantor (61) + +N. Negasi Pernyataan Berkuantor (63) + +O. Penarikan Kesimpulan (64) + +P. Penerapan Logika Matematika (71) + +Q. Rangkuman (72) + +R. Latihan (73) + +BAB 4 HIMPUNAN (77) + +A. Pengertian Himpunan (78) + +B. Notasi dan Anggota Himpunan (78) + +C. Cara Menyatakan Himpunan (79) + +D. Macam-Macam Himpunan (82) + +E. Sifat-Sifat Operasi Himpunan (85) + +F. Operasi Himpunan (86) + +G. Diagram Venn (91) + +H. Kardinilitas (91) + +I. Hubungan Antara Himpunan (92) + +J. Konsep Himpunan dalam Pemecahan Masalah (95) + +K. Rangkuman (98) + +L. Latihan (99) + +BAB 5 RELASI DAN FUNGSI (103) +A. Product Cartesius (105) +B. Relasi pada Himpunan (107) +C. Sifat-sifat pada Relasi (108) +D. Hubungan Relasi dengan Fungsi (114) +E. Macam-macam Fungsi (116) +F. Sifat-sifat Fungsi (121) +G. Fungsi Komposisi (124) +H. Fungsi Invers (126) + + ( iv ) Dasar Matematika + I. Invers Fungsi Komposisi (129) +J. Rangkuman (130) +K. Latihan (131) + +BAB 6 PERSAMAAN DAN PERTIDAKSAMAAN (135) +A. Persamaan Linier (136) +B. Persamaan Kuadrat (143) +C. Pertidaksamaan Linier (146) +D. Pertidakasamaan Kuadrat (149) +E. Aplikasi Persamaan dan Pertidaksamaan Liner (151) +F. Rangkuman (154) +G. Latihan (156) + +BAB 7 TRIGONOMETRI (161) + +A. Pengertian Trigonometri (162) + +B. Satuan Sudut (162) + +C. Perbandingan Trigonometri (163) + +D. Nilai trigonometri sudut istimewa (166) + +E. Perbandingan trigonometri di berbagai kuadran (167) + +F. Identitas Trigonometri (170) + +G. Aturan Sinus dan Cosinus (172) + +H. Luas Segitiga (175) + +I. Rangkuman (177) + +J. Latihan (179) + +DAFTAR PUSTAKA (181) + + ( v ) Dasar Matematika + BAB 1 + + PEMECAHAN MASALAH + MATEMATIKA + + PENDAHULUAN + Perkembangan Ilmu Pengetahuan dan Teknologi yang +semakin cepat menuntut setiap manusia untuk mampu +meyesuaikan diri guna mengikuti perubahan-perubahan yang +terjadi, serta mampu memecahkan masalah yang dihadapinya +secara cermat, tepat dan kreatif. Tujuan belajar matematika +yang tertecantum dalam kurikulum mata pelajaran +matematika di semua jenjang pendidikan, yaitu mengarah +kepada kemampuan siswa pada pemecahan masalah yang +dihidapi dalam kehidupan sehari-hari dengan menjadikan +siswa kreatif, dam inovatif. + Masalah merupakan bagian yang tak terpisahkan dari +kehidupan manusia. Setiap manusia hidup selalu berhadapan +dengan masalah. Yang berbeda adalah bagaimana mereka +menyikapi masalah itu. Ada yang menghindar dan ada yang +berusaha mencari pemecahan dari masalah itu. Orang yang +ingin selalu memecahkan masalah yang dihadapinya adalah +lebih baik dari pada orang yang selalu menghindar dari +masalah yang dihadapi, karena masalah itu tidak akan hilang +jika tidak diselesaikan. + + 1 | Pemecahan Masalah Matematika + A. PENGERTIAN MASALAH + + Suatu pertanyaan akan menjadi masalah, hanya jika +pertanyaan itu menunjukkan adanya suatu tantangan +(challenge) yang tidak dapat dipecahkan oleh suatu prosedur +rutin (routine procedure) yang sudah diketahui si pelaku, +seperti yang dinyatakan Cooney, et al. (1975: 242) berikut: “… +for a question to be a problem, it must present a challenge that +cannot be resolved by some routine procedure known to the +student.” + + Bell (1978) mengemukakan bahwa suatu situasi +dikatakan masalah bagi seseorang jika ia menyadari +keberadan situasi tersebut, mengakui bahwa situasi tersebut +memerlukan tindakan dan tidak dengan segera dapat +menemukan pemecahannya. + + Hudoyo (1990) lebih tertarik melihat masalah, dalam +kaitannya dengan prosedur yang digunakan seseorang untuk +menyelesaikannya berdasarkan kapasitas kemampuan yang +dimilikinya. Selanjutnya ditegaskan bahwa seseorang mungkin +dapat menyelesaikan suatu masalah dengan prosedur rutin, +namun orang lain dengan cara tidak rutin. + + Baroody (1993) menyatakan bahwa ”masalah” dalam +matematika adalah suatu soal yang di dalamnya tidak +terdapat prosedur rutin yang dengan cepat dapat digunakan +untuk menyelesaikan masalah dimaksud. Masalah dapat juga +berarti suatu tugas yang apabila kita membacanya, melihatnya +atau mendengarnya pada waktu tertentu, dan kita tidak +mampu untuk segera menyelesaikannya pada saat itu juga +(Gough dalam Coffey, Kolsch dan Mackinlay, 1995). + +Matematika Dasar | 2 + McGivney dan DeFranco (1995) memahami bahwa +setiap masalah dalam pembelajaran matematika +mengandung 3 unsur penting, yaitu : (1) informasi, (2) operasi +dan (3) tujuan. + + Menurut National Council of Teachers of Mathematics +(NCTM) (2000: 24) masalah mempunyai ciri: (1) nonroutine, (2) +long, (3) predicated on the high-level use of fact, concepts and +skills, (4) cast in context and (5) “focused on the students” abilities +to develop and use strategies to solve a problem. + + Menurut Charles (dalam Kaur Berinderjeet, 2008) +suatu masalah adalah tugas dimana : (1) seseorang ada +keinginan untuk menghadapi serta ada keinginan untuk +menemukan solusi, (2) seseorang tidak mempunyai prosedur +yang siap digunakan untuk menemukan solusi, dan (3) +seseorang harus berusaha untuk menemukan solusi. Dari tiga +komponen tugas pada diri seseorang tersebut mengindikasi- +kan pentingnya masalah. Pertama, suatu keinginan atau +kebutuhan pemecah masalah (solver) untuk menemukan +solusi. Kedua, solusi tersebut tidak bisa diperoleh secara +langsung atau tiba-tiba dengan hanya berdasar pada +pengetahuan. Ketiga, pemecah masalah (solver) harus +membuat suatu usaha nyata untuk tiba pada suatu solusinya. + + Berdasarkan beberapa pengertian tentang masalah +(problem) yang telah dikemukakan di atas, maka dapat +dikatakan bahwa suatu kondisi tertentu merupakan suatu +masalah bagi seseorang, tetapi belum tentu merupakan +masalah bagi orang lain. Dengan demikian, masalah +merupakan suatu kondisi yang relatif.. + + Suatu pertanyaan yang merupakan permasalahan bagi +siswa SD, mungkin bukan permasalahan bagi Anda sebagai + + 3 | Pemecahan Masalah Matematika + mahasiswa, sebab bagi siswa SD untuk menjawab pertanyaan +tersebut memerlukan proses penalaran yang rumit, +sedangkan bagi Anda untuk menjawab pertanyaan tersebut +memerlukan proses penalaran yang rutin. Sebaliknya, apabila +suatu pertanyaan merupakan permasalahan bagi Anda, +apakah pertanyaan tersebut merupakan permasalahan bagi +siswa SD? Tentu saja pertanyaan tersebut bagi siswa SD bukan +merupakan permasalahan, karena siswa SD memang belum +siap untuk mampu menjawab permasalahan Anda. Demikian +juga permasalahan yang dihadapi oleh ilmuwan, misalnya ahli +astronomi, tentunya bagi kita sebagai orang yang tidak +mempelajari permasalahan yang berkaitan dengan +keastronomian, bukan merupakan masalah. Masalah yang +sering dialami oleh sebagian besar siswa SD + +Contoh 1.1 +Berapakah jumlah dari 1 + 2 + 3 + . . . + 1000? + +Bagi siswa SD pertanyaan tersebut merupakan permasalahan, +karena siswa SD tidak mempunyai aturan/hukum tertentu +yang segera dapat dipergunakan untuk menemukan jawaban +pertanyaan tersebut. Hal ini berarti pertanyaan tersebut tidak +dapat dijawab dengan prosedur rutin, pertanyaan tersebut +meskipun dapat dimengerti, tetapi pertanyaan tersebut +merupakan tantangan untuk dijawab yang sifatnya individu +(tingkat berfikir siswa) dan pengetahuan yang telah dimiliki, +serta bergantung pada waktu. + +Contoh 1.2: +Menghitung suatu percobaan tentang melambungkan sebuah +dadu yang homogen oleh 25 siswa kelas VI secara bergantian, +frekuensi munculnya mata dadu 1 sebanyak 4 kali, mata dadu +2 sebanyak 3 kali, mata dadu 3 sebanyak 7 kali, mata dadu 4 + +Matematika Dasar | 4 + sebanyak 5 kali, mata dadu 5 sebanyak 4 kali, mata dadu 6 +sebanyak 2 kali, tentukan rataan dari data tersebut. + +Pemecahan masalah yang sering ditunjukkan oleh siswa + +berkaitan dengan kasus di atas adalah mereka menjumlahkan + +frekuensi dari data tersebut, kemudian membaginya dengan + +banyaknya peristiwa  4  3  7  5  4  2  25  4,16 . Hal +  6 6  + +ini adalah suatu masalah sebab walaupun siswa mampu + +memecahkan masalah tersebut dengan cepat, namun + +jawabannya tidak benar. Akan tetapi jika guru meluangkan + +waktu, walaupun hanya sebentar untuk menjelaskan hal + +tersebut, maka siswa pada umumnya akan mampu + +memecahkan masalah tersebut dengan baik dan benar. + +Contoh 1.3: + + Orang yang menghadapi permasalahan dalam +matematika, dapat digolongkan ke dalam empat tipe, yaitu: (1) +tipe pertama, adalah orang yang memiliki motivasi (keinginan +menyelesaikannya) kurang atau rendah dan memiliki +kompetensi (kemampuan) juga rendah, (2) tipe kedua, adalah +orang yang memiliki motivasi tinggi, akan tetapi +kompetensinya rendah, (3) tipe ketiga, adalah orang yang +memiliki motivasi rendah, akan tetapi ia sebenarnya memiliki + + 5 | Pemecahan Masalah Matematika + kompetensi tinggi, dan (4) tipe keempat, adalah orang yang +memiliki motivasi tinggi dan kompetensi yang tinggi pula. +Dari keempat tipe tersebut, tentunya tipe yang keempat +senantiasa diharapkan tidaklah mudah dilakukan, karena +perlu dibutuhkan ketelatenan, keuletan dan kesabaran. + +B. MASALAH RUTIN DAN MASALAH TIDAK RUTIN + + Suatu masalah biasanya memuat suatu situasi yang +mendorong seseorang untuk menyelesaikannya akan tetapi +tidak tahu secara langsung apa yang harus dikerjakan untuk +menyelesaikannya. + + Suatu soal dapat dipandang sebagai masalah, +merupakan hal yang sangat relatif. Suatu soal yang dianggap +sebagai masalah bagi seseorang, bagi orang lain mungkin +hanya merupakan hal yang rutin belaka. Dengan demikian, +guru perlu berhati-hati dalam menentukan soal yang akan +disajikan sebagai pemecahan masalah. Bagi sebagian besar +guru, untuk memperoleh atau menyusun soal yang benar- +benar bukan merupakan masalah yang rutin bagi siswa +termasuk pekerjaan yang sulit. Akan tetapi hal ini akan dapat +diatasi antara lain melalui pengalaman dalam menyajikan soal +yang bervariasi baik bentuk, tema masalah, tingkat kesulitan, +serta tuntutan kemampuan intelektual yang ingin dicapai atau +dikembangkan pada siswa. + + Untuk memudahkan dalam pemilihan soal, perlu +dilakukan pembedaan antara soal rutin dan soal tidak rutin. +Soal rutin biasanya mencakup aplikasi suatu prosedur +matematika yang sama atau mirip dengan hal yang baru +dipelajari. Sedangkan dalam masalah tidak rutin, untuk +sampai pada prosedur yang benar diperlukan pemikiran yang +lebih mendalam. Menurut hasil penelitian The National + +Matematika Dasar | 6 + Assessment di Amerika Serikat mengindikasikan bahwa siswa +SD pada umumnya menghadapi kesulitan dalam +mengahadapi soal tidak rutin yang memerlukan analisis dan +proses berfikir mendalam. + + Pada tingkat sekolah dasar, masalah matematika +dalam buku teks tertentu jarang menyajikan tentang +bagaimana untuk mengembangkan ketrampilan berfikir +matematika siswa. Para siswa harus diberikan masalah yang +menarik dan menantang sehingga mereka akan memperoleh +pengalaman dalam menganalisa informasi dan mengembang- +kan pandangan menjadi suatu hubungan matematis. Masalah +tidak rutin lebih kompleks daripada masalah rutin, sehingga +strategi untuk memecahkan masalah mungkin tidak bisa +muncul secara langsung, dan membutuhkan tingkat +kreativitas dan orisinalitas yang tinggi dari si pemecah +masalah (solver). Oleh karena itu tujuan terpenting dari +pembelajaran matematika seharusnya untuk membangun +kemampuan siswa kita dalam memecahkan masalah. +Meskipun sebagian guru percaya bahwa kemampuan +memecahkan masalah terbentuk secara otomatis dari +penguasaan keterampilan berhitung. Hal tersebut tidak +sepenuhnya benar. Pemecahan masalah perlu ditekankan +pada pembelajaran matematika sejak dini/ sejak awal. + + Siswa yang sedang belajar matematika dan terbiasa +dengan soal atau masalah yang tidak rutin, maka siswa +tersebut akan terlatih dengan menerapkan berbagai konsep +matematika dalam situasi baru, sehingga pada akhirnya +mereka akan mampu menggunakan berbagai konsep ilmu +yang telah mereka pelajari untuk memecahkan masalah +dalam kehidupan sehari-hari mereka. + + 7 | Pemecahan Masalah Matematika + Contoh 1.4: +Perhatikan beberapa soal berikut : + +1. 3194 6754 + 5346 8968 + 8877 7629 + + + ……… + + ……….. + +2. Pada hari Senin ada 5479 orang yang menonton film, + 3477 orang menonton pada hari Selasa dan 6399 orang + menonton pada hari Rabu. Berapa jumlah orang yang + menonton dalam tiga hari? + +3. Gunakan tiap angka 1, 2, 3, 4, 5, 6, 7, 8, 9 paling sedikit + satu kali untuk membentuk tiga buah bilangan empat- + angka yang jumlahnya 9636! + +4. Siswa kelas V SDN “Gatotkaca” akan pergi berkemah. Ada + 46 orang penumpang yang akan ikut, yaitu terdiri dari + siswa-siswi dan guru pembimbing. Alat transportasi yang + dapat di pilih ada 2, yaitu mobil Kijang dan Colt L-300. + +Kijang Colt L-300 + +Tempat duduk: 6 orang Tempat duduk : 8 orang + +a) Apabila menggunakan mobil Kijang, berapa buah mobil + Kijang yang dibutuhkan untuk pergi berkemah? + +b) Apabila menggunakan mobil Colt L-300, berapa buah + mobil Colt L-300 yang dibutuhkan untuk pergi berkemah? + +Matematika Dasar | 8 + c) Apabila tarip carter sebuah mobil Kijang adalah Rp. + 600.000,-, dan sebuah mobil Colt L-300 adalah Rp. + 750.000,- ; berapakah tarip termurahnya? + +Panitia memutuskan ke 46 penumpang supaya membawa +semua perlengkapannya yang dimasukkan ke dalam 14 kotak +(dus) yang ukurannya sama, maka rinciannya: + +Kijang Colt L-300 + +Tempat duduk : 4 orang Tempat duduk : 6 orang +Barang : 3 kotak (dus) Barang : 2 kotak (dus) + +d) Apabila panitia memutuskan untuk mencarter mobil Colt + L-300 saja, berapa buah mobil Colt L-300 yang mereka + perlukan? Catatan: demi keselamatan dalam perjalanan, + tidak ada dus yang diletakkan di atas jok mobil. + +e) Bagaimana seandainya panitia mencarter mobil Kijang + saja, apa perbedaannya? Apa persamaannya? + + 9 | Pemecahan Masalah Matematika + Soal no (1) dan (2) merupakan contoh masalah rutin +karena permasalahan yang terkandung didalamnya +merupakan permasalahan yang berkaitan dengan operasi +hitung, yaitu penjumlahan. Meskipun soal no (2) merupakan +soal cerita, namun bagi sebagian besar anak SD, memilih +operasi hitung yang sesuai dapat mengkaitkan dengan soal no +(1) tentang penjumlahan sehingga operasi yang digunakan +untuk menyelesaikan soal no (2) adalah penjumlahan. +Sedangkan untuk soal no (3) merupakan contoh masalah tidak +rutin karena untuk memperoleh jawaban yang cepat dan +benar, siswa dituntut melakukan penghitungan untuk +berbagai kemungkinan pasangan bilangan. + + Bagi mereka yang memiliki sense of number cukup +tinggi, mungkin bisa lebih efisien dalam proses pencarian +jawaban yang tepat. Sebagai contoh, seorang anak menyadari +bahwa jumlah dari tiga bilangan-bilangan dengan ujung-ujung +1, 3 dan 5, secara bersamaan. Untuk dapat menyelesaikan +soal ini dengan baik, seoang anak tidak cukup hanya memiiki +pengetahuan prasyarat. Sedangkan untuk soal no (4) a, b, c +dapat diselesaikan dengan pengerjaan sederhana atau +menggunakan algoritma perhitungan biasa. + + Oleh karena itu, dapat kita simpulkan bahwa soal no 4. +a, b, dan c termasuk masalah rutin, untuk soal no 4. d dan e +mempunyai tingkat kesulitan yang berbeda dibandingkan soal +no 4. a, b, c. Seorang siswa yang dihadapkan dengan soal no +4. d dan e ini, harus menentukan strategi yang tepat sebelum +memulai untuk memecahkan pertanyaan tersebut. Oleh +karena itu, soal no 4. d dan e merupakan masalah tidak rutin. + +Matematika Dasar | 10 + C. KLASIFIKASI MASALAH MATEMATIKA + + Masalah di dalam matematika dapat diklasifikasi +dalam dua jenis (Pusat Kurikulum, 2002 a, b, dan c), yaitu: + a. Penemuan (Problem to find), yaitu mencari, menentukan, + + atau mendapatkan nilai atau objek tertentu yang tidak + diketahui dari soal serta memenuhi kondisi atau syarat + yang sesuai dengan soal. + b. Pembuktian (Problem to prove), yaitu prosedur untuk + menentukan apakah suatu pernyataan benar atau tidak + benar. Soal membuktikan terdiri atas bagian hipotesis + dan kesimpulan. Untuk membuktikan kita harus + membuat atau memproses pernyataan yang logis dari + hipotesis menuju kesimpulan, sedangkan untuk + membuktikan bahwa suatu pernyataan tidak benar kita + harus memberikan contoh penyangkalnya sehingga + pernyataan tersebut menjadi tidak benar. + +Contoh 1.5: +Perhatikan beberapa contoh soal berikut: + +1. Apa langkah pertama yang harus dilakukan dalam + +mengerjakan 3 1 : 5 1 ? + 24 + + 1 1 +2. Tentukan hasilnya bila x 6 : 2 ? + 4 2 + +3. Manakah yang lebih luas, kebun yang berbentuk + persegipanjang dengan panjang 314 m dan lebar 12 m + atau kolam renang yang berbentuk lingkaran dengan jari- + jari lingkaran 12 m? + +11 | Pemecahan Masalah Matematika + 4. Ani lebih tua dari Budi, Budi lebih tua daripada Chandra, + Chandra lebih muda daripada Deni. Siapakah yang paling + muda di antara mereka? + +5. Diketahui sejumlah bangun geometri datar, yaitu persegi, + persegipanjang, segitiga, lingkaran, belahketupat, + jajargenjang, laying-layang, dan trapesium. Buatlah + hubungan di antara mereka dalam bentuk diagram peta + konsep! + +6. Dengan cara bagaimana kita menunjukkan 6 dibagi 3 + adalah 2? + +7. Jelaskan mengapa 2 5 x 3 5 - 5 = 25 ? + +8. Mengapa bilangan-bilangan ganjil dikalikan dengan + bilangan genap selalu menghasilkan bilangan genap? + +9. Mengapa setiap persegi adalah pesegi panjang? + +10. Mengapa sebuah relasi belum tentu merupakan fungsi? + +Dari soal-soal di atas soal no 1-5 merupakan masalah +penemuan, sedangkan soal no 6-10 merupakan masalah +pembuktian, mengapa? + + Pada soal no 1 siswa akan menentukan langkah + +pertama untuk mendapatkan nilai dari 31 :51 + 24 + +(masalah penemuan) + + Pada soal no 2 siswa akan mencari nilai dari 1 x6 : 2 1 + 4 2 + +(masalah penemuan) + + Pada soal no 3 siswa akan menentukan mana yang lebih + +luas dengan mencari luas kebun dan kolam renang + +Matematika Dasar | 12 + dengan ukuran masing-masing yang sudah di tentukan + (masalah penemuan) + +  Pada soal no 4 siswa akan menentukan kondisi yang + sesuai soal dengan yang diberikan (masalah penemuan) + +  Pada soal no 5 siswa akan mencari, menentukan, dan + mendapatkan hubungan bangun geometri datar yang + diberikan dalam diagram peta konsep (masalah + penemuan) + +  Pada soal no 6 siswa akan menunjukkan bahwa 6 dibagi + 3 adalah 2 merupakan pernyataan yang bernilai benar + (masalah pembuktian) + +  Pada soal no 7 siswa akan menunjukkan bahwa 2 5 x + 3 5 - 5 =25 adalah benar (masalah pembuktian). + +  Pada soal no 8, 9, 10 merupakan masalah pembuktian + diserahkan kepada Anda sebagai latihan. + +D. PEMBELAJARAN PEMECAHAN MASALAH MATEMATIKA + + Belajar matematika tidaklah bermakna jika tidak +dikaitkan dalam kehidupan sehari-hari. Karena dalam kegiatan +kehidupan sehari-hari sering membutuhkan bantuan ilmu +matematika, misalnya dalam jual-beli, bertani, dan lain-lain. +Karena memang matematika tumbuh dan berkembang dari +kehidupan sehari-hari manusia dengan segala aktivitasnya. +Misalnya saja dalam pekembangan bilangan, yang dimulai dari +bilangan asli, bilangan cacah, bilangan bulat, bilangan +rasional/irrasional, bilangan khayal, dan bilangan kompleks +muncul secara bertahap sesuai dengan kebutuhan manusia +terhadap bilangan. + + 13 | Pemecahan Masalah Matematika + Manusia primitif membilang dimulai dari 1, 2, 3, dan + +seterusnya (bilangan asli), tetapi setelah ditemukan angka 0 + +(nol), maka kegiatan membilang pada dasarnya dimulai dari + +tidak ada, yaitu: 0, 1, 2, 3, ...(bilangan cacah). Karena + +kehidupan manusia makin kompleks dan berkembang adanya + +hak milik, maka muncul bilangan bulat, seperi mempuanyai + +hutang sesuatu diartikan sebagai mempunyai jumlah yang + +negatif dan sebaliknya jika mempunyai sesuatu diartikan + +mempunyai jumlah yang potitif, dan antara mempunyai + +sesuatu dengan mempunyai hutang adalah tidak mempunyai + +sesuatu atau dilambangkan dengan bilangan nol. Setelah itu + +berkembang bilangan rasional dan bilangan pecah, karena + +suatu bilangan tidak selalu habis dibagi habis, seperti 1 dibagi + +1 2 +2, ditulis 2 dibagi 3, ditulis dan sebagainya. Di pihak lain +2 3 + + a + +ada bilangan yang tidak dapat dinyatakan dalam bentuk , + + b + +seperti 2, 3, 5 dan lain sebagainya. Gabungan bilangan + +rasional dan irrasional dinamakan bilangahn real (nyata). +Seterusnya muncul bilangan khayal, seperti bilangan dalam + +bentuk akar negatif (  1,  2,  4 dan sebagainya. + +Gabungan antara bilangan real dan khayal dinamakan +bilangan kompleks. + + Siswa sekolah dasar dimulai kelas satu sudah +sewajarnya dibekali dengan manfaat belajar matematika +dalam kehidupan sehari-hari, yaitu selalu mengaitkan materi +pembelajaran dengan kehidupan nyata yang terjadi dan yang +sering dialami siswa. + + Kemampuan kognitif siswa akan berkembang selaras +dengan kematangannya, dan akan berkembang dengan baik + +Matematika Dasar | 14 + dan cepat jika dalam belajarnya sering dihadapkan terhadap +permasalahan kehidupan sehari-hari. Kita sebagai guru harus +menyadari bahwa kemampuan manusia itu terbatas dan tidak +sama irama perkembangan mentalnya, maka dari itu sebagai +guru harus menyesuaikan pemberian materi pelajaran +dengan kemampuan-kemampuan siswa-siswanya, seperti +belajar dari hal-hal konkrit menuju abstrak, dari sederhana ke +kompleks, dan dari mudah ke sulit. + + Siswa diajak menyelesaikan pemecahan masalah dari +satu langkah ke penyelesaian masalah yang membutuhkan +banyak langkah yang disertai kemampuan memahami dan +menangkap lebih banyak vatiabel dan faktor dalam suatu +masalah. + + Tidak ada cara yang pasti bagai mana melatihkan +pemecahan masalah kepada siswa, namun ada petunjuk yang +dapat membantu guru dalam membelajarkan siswanya +kearah penggunaan pendekatan pemecahan masalah +matematika, agar siswa belajarnya terarah dan mendapat +hasil yang baik. + +E. LANGKAH-LANGKAH PEMECAHAN MASALAH + MATEMATIKA + + Polya (Upu, 2004) mengartikan pemecahan masalah +sebagai suatu usaha mencari jalan keluar dari suatu kesulitan +guna mencapai suatu tujuan yang tidak begitu mudah segera +dicapai. Sumarmo (Upu, 2004) menegaskan bahwa +pemecahan masalah dapat berupa menciptakan ide baru, +menemukan teknik atau produk baru. Bahkan di dalam +pembelajaran matematika, selain pemecahan masalah +mempunyai arti khusus, istilah tersebut juga mempunyai + + 15 | Pemecahan Masalah Matematika + interpreasi yang berbeda. Misalnya, menyelesaikan soal cerita +atau soal yang tidak rutin dan mengaplikasikan matematika +dalam kehidupan sehari-hari. + + Pemecahan adalah proses dalam memecahkan atau +menyelesaiakan (KBBI online 2012), kemudian pemecahan +masalah menurut Branca (Upu, 2004) menegaskan bahwa +terdapat tiga macam interpretasi mengenai pemecahan +masalah, yaitu: (1) pemecahan masalah sebagai tujuan yang +menekankan pada aspek mengapa matematika diajarkan. Hal +ini berarti bahwa pemecahan masalah bebas dari materi +khusus. Sasaran utama yang ingin dicapai adalah adalah +bagaimana cara memecahkan suatu masalah. (2) pemecahan +masalah sebagai proses diartikan sebagai kegiatan yang aktif. +Dalam hal ini penekanan utamanya terletak pada metode, +strategi atau prosedur yang digunakan oleh siswa dalam +menyelesaikan masalah hingga mereka menemukan jawaban. +(3) pemecahan masalah sebagai keterampilan menyangkut +dua hal, yaitu: (a) keterampilan umum yang harus dimiliki oleh +siswa untuk keperluan evaluasi. (b) keterampilan minimum +yangdiperlukan siswa agar dapat mengaplikasikannya dalam +kehidupan sehari-hari. + + Menurut Polya (Alimuddin, 2012), pemecahan masalah +matematika terdiri atas 4 (empat) langkah, yaitu: +1. Memahami masalah, meliputi: menemukan dengan tepat + + apa yang ditanyakan dan apa yang diketahui, menemukan + syarat-syarat apa yang sudah dipenuhi dan syarat-syarat + apa yang masih diperlukan, menuliskan soal dengan + kalimatnya sendiri, merumuskan sub-sub masalah, + +2. Merencanakan penyelesaian, meliputi: menuliskan atau + menyebutkan dengan tepat soal-soal yang pernah + dijumpai yang mirip dengan soal yang dihadapi, + +Matematika Dasar | 16 + menuliskan atau menyebutkan konsep-konsep, sifat- + sifat, prinsip-prinsip matematika yang terkait + dengan soal yang dihadapi, mengaitkan konsep- + konsep, sifat-sifat, prinsip-prinsip matematika dengan + masalah/soal yang dihadapi, merumuskan beberapa + strategi penyelesaian yang dapat digunakan dalam + menyelesaikan masalah yang dihadapi, + +3. Melakukan rencana penyelesaian, meliputi: memilih + strategi yang tepat dan mengimplementasikan strategi, + +4. Melihat kembali pekerjaan yang telah kita lakukan + meliputi: apakah jawaban sudah sesuai dengan + pertanyaan?, apakah jawaban sesuai kaedah + matematika?, apakah jawaban rasional ?. + + Sedangkan pemecahan masalah yang dimaksudkan +dalam penelitian (Bahar, 2013) terkait dengan masalah soal +cerita dengan segera dapat menemukan penyelesaiannya +melalui tahapan-tahapan sebagai berikut: +1. Memahami soal dengan menentukan apa yang diketahui + + dan apa yang ditanyakan. +2. Merencanakan penyelesaian dengan menyusun strategi + + yang dapat digunakan dalam menyelesaikan soal. +3. Mengimplementasikan penyelesaian dengan menetapkan + + atau memilih strategi yang sesuai dalam meyelesaiakan + soal dan melakukan perhitungan. +4. Verifikasi yaitu melihat kembali jawaban yang telah + lakukan apakah jawaban sudah sesuai dengan apa yang + ditanyakan. + + Sehingga beberapa keterampilan untuk meningkatkan +kemampuan memecahkan masalah antara lain adalah: (1) + + 17 | Pemecahan Masalah Matematika + memahami soal, (2) Merencanakan penyelesaian dengan +menyusun strategi, (3) Mengimplementasikan penyelesaian, +dan (4) Verifikasi. + +1) Memahami Soal + Guru memberi masalah dalam bentuk soal setiap hari, + baik dalam jam pelajaran matematika, maupan pada + mata pelajaran lain secara terpadu (karena matematika + banyak kaitannya dengan Bahasa, IPS, IPA, dan lain-lain), + dengan langkah-langkah sebagai berikut: + 1) menjelaskan kata atau ungkapan operasi hitung yang + sering digunakan, seperti sebagai berikut: + Penjumlahan: digabungkan, disatukan, dijadikan + satu wadah, dijumlahkan, dimasukan, dan + pengulangan suatu kegiatan. + + Contoh 1.6: + (1) Amin mempunyai 10 kelereng dan Andri mempunyai + + 8 kelereng, jika kelereng Amin dan Andri + digabungkan/disatukan/dijadikan satu wadah maka + jumlah kelereng mereka berjumlah ... + + (2) Kelereng Amin dalam gelas ada 5, lantas dimasukan + lagi sebanyak 4 kelereng, maka kelereng Amin dalam + gelas sekarang ada ... kelereng. + + (3) Pada hari senin Amin menyimpan uang dalam + celengan sebanyak Rp 2.000,00, pada hari selasa + sebanyak Rp 5.000,00, pada hari rabu sebanyak Rp + 3.000,00. Berapa rupiah banyak uang yang tersimpan + dalam celengan tersebut + +Matematika Dasar | 18 + Pengurangan: selisih/ beda, dikurangi/berkurang, + diambil, dipisahkan, dan dibagikan. +Contoh 1.7: +(1) Amin mempunyai uang sebesar Rp 5.000,00 + sedangkan Ani mempunyai Rp 7.000,00. Berapakah + selisih/beda uang Amin dan Ani? + +(2) Andri diberi uang jajan dalam satu minggu sebanyak + Rp 10.000,00 setalah hari ke empat uangnya + berkurang Rp 4.000,00. Berapakah sisa uang Andri + sekarang? + +(3) Pak Budi mempunyai anak ayam yang baru menetas + sebanyak 10 ekor, yang 5 ekor dipisahkan dari + induknya. Berapakah anak ayam yang ikut induknya? + +(4) Pak Budi mempunyai uang sebanyak Rp 50.000,00, + uang tersebut dibagikan kepada 2 oarng pakir miskin + sebanyak Rp 15.000,00. Berapakah rupiah sisa uang + Pak Budi sekarang? + + Perkalian: digandakan sebanyak ... kali, setiap ... + terdiri dari ..., kegiatan yang berulang-ulang (dalam + jumlah yang sama) + +Contoh 1.8: +(1) Pak Budi meminjam uang dari “Bank Keliling” + + sebanyak Rp 1.000.000,00 karena ia tak mampu + membayar dalam waktu satu tahun utangnya + digandakan sebanyak 3 kali. Berapa rupiah Pak Budi + harus membayar utangnya jika dalam satu tahun + tidak bisa membayar? + +(2) Kelurahan Munjuljaya terdiri dari 2.500 Kepala + Keluarga (KK), setiap harinya masing-masing KK + + 19 | Pemecahan Masalah Matematika + membuang sampah terdiri dari 1 kg. Berapa kg + sampah yang terkumpul dalam satu bulan? + (3) Kasir bank menghitung uang menggunakan jari- + jarinya, dalam satu kali gerakan jari-jarinya mampu + mengambil empat lembar uang. Jika dia + menggerakan jari-jarinya sebanyak 25 kali, maka + berapa lembar uang yang dia hitung? + + Pembagian: pengurangan yang berulang, dibagikan, + dipisah-pisah (dalam jumlah yang sama) + + Contoh 1:9: + (1) Amin mempunyai 100 kelereng, setiap hari + + diambilnya sebanyak 5 kelereng. Pada hari ke berapa + kelereng itu habis? + (2) Pak Budi membagikan uang zakat sebanyak Rp + 1.000.000,00 kepada 100 orang pakir miskin. Berapa + rupiah rata-rata kebagian setiap orangnya? + + (3) Pak Budi mempunyai ayam sebanyak 50 ekor, ayam + tersebut dipisahkan-pisahkan dalam 10 kandang. + Berapa ekor rata-rata isi setiap kandangnya? + + 2) menjelaskan hubungan antara penjumlahan dengan + pengurangan, perkalian dengan pembagian, + penjumlahan dengan perkalian, dan pengurangan + dengan pembagian. + + Contoh 1.10: +  Penjumlahan dengan pengurangan: + + Jika a + b = c , berlaku c – a = b atau c – b = a + +  Perkalian dengan pembagian: + +Matematika Dasar | 20 + Jika a x b = c , berlaku c : a = b atau c : b = a + + Penjumlahan dengan perkalian: + 5+5+5+5=4x5 + + Pengurangan dengan pembagian.: + 10 – 2 – 2 – 2 – 2 – 2 = 10: 2 + +3) melatih membaca pemahaman dari kalimat pendek + dan sederhana ke kalimat panjang dan kompleks. + Cobalah dengan menggunakan metode diskusi untuk + membahas soal yang diberikan dengan fokus isi + pokok kalimat. Apakah topik / tema yang dibicarakan, + informasi apa yang diberikan, apa yang ditanyakan, + dan sebagainya. + +a) Bertanya kepada siswa tentang isi kalimat yang + diberikan dalam contoh, tentang apa yang diketahui + atau data apa yang diberikan dan apa yang + ditanyakan atau apa yang akan dicari. + Dalam hal ini guru yang mengajukan pertanyaan + tentang isi kalimat yang dijadikan contoh. + +b) Pada tahap awal, pembuatan paragrap cukup terdiri + dari satu kalimat, dan jangan berbelit-belit sehingga + sulit dimengerti siswa. + +Contoh 1.11: +Kasir bank menghitung uang menggunakan jari-jarinya. +Dalam satu kali gerakan jari-jarinya mampu mengambil +empat lembar uang. Dia menggerakan jari-jarinya +sebanyak 25 kali. Berapa lembar uang yang dia hitung? + + 21 | Pemecahan Masalah Matematika + 2) Merencanakan penyelesaian dengan menyusun + strategi + + Seperti yang telah dibahas pada modul 1, pendekatan + atau strategi pemecahan masalah banyak sekali alternatif + yang harus kita pakai, hal tersebut didasarkan pada jenis + masalah atau soal. Starategi tersebut adalah: membuat + tabel, membuat gambar, menduga, mencoba, + memperbaiki, mencari pola, mengguanakan penalaran, + menggunakan variabel, membuat persamaan, + mengunakan algoritma, menggunakan sifat-sifat + bilangan, menggunakan rumus, menggunakan informasi + yang diketahui untuk mengembangkan informasi baru, + dan lain lain. + + Bagi siswa yang belum dapat berpikir abstraks + pendekatan dengan membuat gambar terlebih dahulu + akan sangat membantu. Hal tersebut dapat dilakukan + secara konkrit atau dengan gambaran obyek yang + dimaksud. Setelah itu berkembang kepada strategi- + strategi lain yang memungkinkan suatu masalah dapat + diselesaikan secara matematis, seperti membuat variabel, + membuat persamaan, menggunakan logika, dan lain-lain. + + Contoh 1.12: + + (1) Penjumlahan dan pengurangan + Pada mulanya Ani mempunyai 5 buku, kemudian + Ibunya memberi sejumlah buku sehingga buku Ani + sekarang menjadi 9 buku. Berapakah Ibu memberi + buku kepada Ani? + Jawab: + +Matematika Dasar | 22 + Lakukan secara konkrit atau dengan membuat +gambar, seperti berikut. + +Tanyakan kepada siswa ada berapa buku yang tidak +mempunyai pasangan seperti yang digambarkan di +atas dan buku yang tidak mempunyai pasangan +tersebut merupakan buku pemberian Ibu. Lantas +bimbing siswa kearah model matematika yang +terbentuk, seperti: 5 buku + .... buku = 9 buku atau 5 ++ ... = 9 +Dari gambar sudah didapat bahwa buku yang tidak +mempunyai pasangan sebanyak 4 buku, dan itu +adalah buku pemberian Ibu. Jadi kalimat matematika +yang terbentuk adalah: 5 + 4 = 9 +Jika strategi dengan pembuatan gambar telah +dikuasai, meningkatlah kepada pembuatan variabel, +boleh dengan “x, y, n, m, dll”.seperti berikut ini. +Diketahui: Ani mempunya 5 buku +Setelah diberi Ibu menjadi 9 buku +Ditanyakan: Berapakah buku pemberian Ibu? +Jawaban: +Misalkan buku pemberian Ibu = x, maka +5+ x=9 +5 + (-5) + x = 9 + (-5) + + 23 | Pemecahan Masalah Matematika + x=4 + Jadi, buku pemberian Ibu sebanyak 4 buku + (2) Perkalian dan Pembagian + Di kelas tiga ada 20 meja yang disusun secara + teratur, barisan terdepan ada 4 meja. Ada berapa + meja setiap baris ke belakang? + Jawab: + Membuat gambar + + Dalam membuat gambar lakukan membuat meja + barisan terdepan sebanyak 4 meja, lantas buatlah + gambar meja ke belakang sambil membilang sampai + 20 meja. Sehingga gambar akan seperti di atas. Meja + sebanyak 5 ke belakang merupakan jawaban dari + soal tersebut. + Model matematikanya adalah: 4 x ... = 20 atau + Misalkan setiap baris meja kebelakang = m, maka 4 x + m = 20 + Jika kedua ruas dibagi dengan 4, maka m = 5 + Jadi baris meja ke belakang ada 5 meja + +Matematika Dasar | 24 + (3) Operasi hitung campuran + Ibu belanja telur 4 kg dan terigu 3 kg, harga setiap + kilogram telur Rp 8.000,00 dan harga setiap kilogram + terigu Rp 4.000,00. Ibu membayar dengan uang Rp + 50.000,00. Berapakah sisa uang Ibu? + Jawab + Diketahui + (a) 4 kg @ Rp 8.000,00 + (b) 3 kg @ Rp 4.000,00 + (c) Ibu membayar Rp 50.000,00 + Ditanyakan berapa rupiah uang sisa (pengembalian)? + Model matematikanya: + 50.000 – [(4 x 8.000) + (3 x 4.000)] = ... + 50.000 – [ 32.000 + 12.000] = ... + 50.000 – 44.000 = 6.000 + Jadi sisa (pengembalian) uang Ibu adalah Rp. + 6.000,00 + +3) Mengimplementasikan penyelesaian + + Dalam menyelesaikan model matematika siswa dituntut + untuk terampil menggunakan pengetahuannya tentang + konsep-konsep dasar matematika beserta aturan-aturan + yang ia ketahui sewaktu mengerjakan latihan-latihan soal. + Baik dalam bentuk algoritma maupun secara aljabar + sederhana. Seperti hubungan penjumlahan dan + pengurangan, perkalian dan pembagian, pangkat dan + akar. + + 25 | Pemecahan Masalah Matematika + Dalam penyelesaian model matematika siswa telah +paham dan terampil, seperti hal-hal sebagai berikut: +(a) a + b = c, kalimat matematika ini dapat dibolak balik +sesuai dengan pola yang didapatkan dalam +menterjemahkan (mentransformasi) kedalam model +matematika, seperti menjadi c – a = b atau c – b = a + +(b) a x b = c, kalimat matematika ini dapat dibolak balik +sesuai dengan pola yang didapatkan dalam +menterjemahkan (mentransformasi) kedalam model +matematika, seperti menjadi c : a = b atau c : b = a + +(c) a2 = b, dapat diubah menjadi a = b atau b 2 = b + +(d) a  c  ad  bc atau a  c  ad  bc +b d bd b d bd + +(e) a  c  ad  bc + bd + +(f) dan lain-lain + +4) Verifikasi + + Sebelum ditafsirkan/diterjemahkan kedalam bentuk + kesimpulan, sebaiknya siswa dibiasakan untuk + memeriksa dulu, apakah jawaban hasil perhitungan itu + benar atau masih terdapat kekeliruan. Untuk ini + dibutuhkan ketelitian untuk mengecek ulang hasil + perhitung yang didapatkan. + + Menafsirkan solusi merupakan kemampuan berpikir + tingkat tinggi, karena hal tersebut merupakan penarikan + kesimpulan dari hal-hal yang telah dianalisis dengan + menggunakan berbagai srtategi dan menggunakan + berbagai opersi hitung. Menafsirkan solusi merupakan + +Matematika Dasar | 26 + menemukan jawaban dari permasalahan yang sedang +dibahas atau diuraikan. + +Contoh 1.13: +Ina disuruh Ibu membeli sebanyak 10 telur, di perjalanan +pulang telur yang dibeli tersenggol temannya, ketika +dihitung telur yang utuh tinggal 6 telur. Berapa butir telur +yang pecah? +Jawab +Diketahui : +Beli telur 10 +Sisa telur 6 +Ditanyakan: +Telur yang pecah +Jawab: +Alternatif kalimat: +(1) (Semua telur yang dibeli) - (Sisa telur yang utuh) = +(telur yang pecah) +(2) (Sisa telur yang utuh) + (telur yang pecah) = (Semua +telur yang dibeli) +(3) 10 – 6 = ... +(4) 6 + ... = 10 +Alternatif Pemecahan: +(1) Perlihatkan 10 benda (sebagai pemisalan telur) lantas + + ambil sebanyak 6, maka sisanya 4 benda +(2) Perlihatkan 10 jari lantas hitung mundur sebanyak 6 + + kali bertepatan dengan melipat jari, maka sisa jari + yang belum telipat sebanyak 4. + + 27 | Pemecahan Masalah Matematika + (3) Gambarlah 10 telur lantas pasangkan dengan + gambar 6 telur, maka 4 telus tidak mempunyai + pasangan + + (4) Enam ditambah berapa agar mnejadi sepuluh? + Hitung dimulai 6 sebanyak yang dibutuhkan sehingga + berhenti di 10, sambil mengacungkan jari. + + (5) Jika siswa telah memahami konsep penjumlahan dan + pengurangan, maka siswa langsung dibimbing ke + model matematika dan menyelesaikannya dengan + aturan-aturan tertentu. + Kesimpulan + Jadi telur yang pecah sebanyak 4 telur + + Contoh 1.14: + Suatu bak mandi mempunyai panjang dua kali lebarnya, + dan tingginya setengah dari lebarnya. Jika luas alas bak itu + 7.200 cm2 berakah liter isi bak air tersebut? + Jawab: + Diketahui: + Panjang bak 2 kali lebar + + 1 + + Tinggi bak lebar + + 2 + + Luas = 7.200 cm2 + Ditanyakan: isi bak dalam liter + Jawab: + Gambar: + + l + 2l + +Matematika Dasar | 28 + Mencari ukuran bak +2 l x l = 7200 +2 l2 = 7200 +l2 = 3600 + +l = 3600 + +l = 60 +Jadi lebar (l) = 60 cm +Karena lebar 60 cm, maka panjang (p) = 2 x 60 = 120 cm + +dan tingginya (t) adalah 1 x60  30 cm + 2 + +Rumus volum (isi) bak (yang berbentuk balok) adalah p x l +x t, yaitu: 120 cm x 60 cm x 30 cm = 216.000 cm3 +Karena yang ditanyakan adalah dalam bentuk satuan liter, +maka 216.000 cm3 = 216 dm3 = 216 liter +Jadi isi bak mandi tersebut adalah 216 liter. + +Dari proses penyelesaian soal di atas, dapat dirinci +langkah-langkah sebagai berikut: +(1) Memahami soal, seperti yang terlihat dalam + + menyederhanakan soal dalam bentuk yang diketahui + dan ditanyakan. +(2) Membuat gambar bak mandi yang mempunyai + panjang, lebar, dan tinggi. Dalam hal ini harus ingat + bahwa bentuk demikian adalah balok yang rumus + isinya adalah: p x l x t +(3) Mencari ukuran bak yang didahului dengan + menterjemahkan luas alas bak yang berbentu balok, + yaitu: panjang kali lebar dalam bentuk variabel l, + seperti: 2 l x l = 7200 +(4) Menjalankan operasi hitung, sehingga ditemukan + ukuran lebar yang dimaksud. + + 29 | Pemecahan Masalah Matematika + (5) Mengaitkan hasil operasi hitung dengan pernyataan + yang diketahui. Sepeti panjangnya dua kali lebarnya + dan tingginya setengah lebarnya. Sehingga + ditemukan ukuran panjang dan tinggi + + (6) Karena panjang, lebar, dan tinggi sudah diketahui + maka isi bak dapat diketahui dengan menjalankan + rumus isi (volumea) balok. + + (7) Volum bak sudah diketaui tetapi membutuhkan + transformasi dari bentuk cm3 ke liter melalui dm3. + + (8) Menyimpulkan isi bak air sebagai hasil proses + sebelumnya. + + Jelaslah, bahwa suatu proses penyelesaian masalah + sangatlah kompleks dan banyak hal-hal yang terkait, + sehingga membutuh daya nalar yang cukup tinggi. + +F. RANGKUMAN + + 1) Masalah dalam matematika terdiri dari masalah rutin + dan masalah tidak rutin + + 2) Klasifikasi masalah matematika terdiri dari dua yaitu: + a. Penemuan yaitu mencari, menentukan, atau + mendapatkan nilai atau objek tertentu yang tidak + diketahui dari suatu soal dan memenuhi kondisi + ataui syarat dari soal tersebut. + b. Pembuktian yaitu prosedur untuk menentukan + apakah suatu pernyataan benar atau tidak + + 3) Langkah-langkah dalam pemecahan masalah + matematika (menurut Polya) + a. Memahami masalah + b. Merencanakan penyelesaian + c. Melakukan rencana penyelesaian + d. Melihat kembali + +Matematika Dasar | 30 + G. LATIHAN + + 1. Dari beberapa pengertian masalah menurut + beberapa sumber yang telah disebutkan di atas, + menurut Anda apa sebenarnya yang dimaksud + dengan masalah? + + 2. Apa syarat suatu situasi disebut sebagai suatu + masalah? + + 3. Mengapa contoh (3) merupakan masalah bagi siswa + SD? + + 4. Berikan contoh soal yang termasuk masalah bagi + siswa SD! + + 5. Apa syarat suatu soal dapat dipandang sebagai + masalah rutin bagi siswa SD? + + 6. Apa syarat suatu soal dapat dipandang sebagai + masalah tidak rutin bagi siswa SD? + + 7. Berikan contoh masalah rutin dan masalah tidak + rutin bagi siswa SD! Jelaskan! + + 8. Apa yang dimaksud dengan masalah penemuan? + + 9. Apa yang dimaksud dengan masalah pembuktian? + + 10. Apa ciri-ciri suatu soal merupakan masalah + penemuan dan ciri-ciri suatu soal merupakan + masalah pembuktian? + + 11. Berikan contoh masalah penemuan dan masalah + pembuktian dalam matematika! Jelaskan! + + 12. Perhatikan ilustrasi-ilustrasi berikut dan tentukan + termasuk pada bilangan apa yang dimaksud? + a) Amin menghitung jumlah kambing peliharaannya + dimulai dari 2, 4, 6, 8, dan 10. + + 31 | Pemecahan Masalah Matematika + b) Ahmad membagikan 5 roti kepada 2 orang + temannya samaa banyak. + + c) Ani menghitung panjang sisi-sisi daerah segitiga + dengan menggunakan rumus: c2 = a2 + b2 + + d) Budi mempunyai meminjam uang di Bank Guna + Usaha sebanyak Rp. 10.000.000,00 + + 13. Pengetahuan apakah yang harus dimiliki oleh + seorang pemasang ubin lantai agar jumlah ubin yang + akan dipasangkan diketahui secara pasti? + + 14. Ayah telah mempunyai pagar sepanjang 40 m untuk + memagari kandang itik (berbentuk persegipanjang) di + belakang rumahnya ada tembok belakang dapat + dijadikan salah satu sisi persegi panjang. Berapakah + ukuran yang dapat dibuat agar ukuran luas persegi + panjang tersebut yang paling luas? + Dari soal tersebut di atas apa saja yang diketahui + yang menjurus kepada penyelesaian soal? + + 15. Hasil survei terhadap kelas enam yang terdiri dari 40 + siswa, 22 orang menyenangi pelajaran matematika, + 21 orang menyenangi pelajaran IPA, 20 orang + menyenangi pelajran IPS. 3 orang menyenangi + pelajaran Matematika dan IPA, 4 orang menyenangi + pelajaran IPA dan IPS, 6 orang menyenangi pelajaran + Matematika dan IPS, dan 5 orang yang menyenangi + ketiga pelajaran tersebut. Buatlah gambarnya! + + 16. Buatlah kalimat matematika dari pernyataan- + pernyataan berikut ini. + a) Bilangan yang berurutan jumlahnya 21. + b) Amin mendapat bunga bank sebesar Rp + 500.000,00 dari saldo simpanan sebesar Rp + +Matematika Dasar | 32 + 5.000.000,00. Berapa persen bunga yang diterima + Amin? +c) Harga 4 pensil dan 5 spidol sebesar Rp 35.000,00 +d) Lampu merah menyala setiap 5 detik, lampu + kuning menyala setiap 6 detik, lampu hijau + menyala setiap 8 detik, dan lampu biru menyala + setiap 12 detik. Jika ke empat lampu dinyalakan + secara bersamaan pada detik ke berapa lampu + merah dan lampu kuning menyala bersamaan + yang ke dua, ke tiga, dan ke empat. Pada detik ke + berapa lampu hijau dan lampu biru menyala + bersamaan yang ke dua, ke tiga, dan ke empat. + + 33 | Pemecahan Masalah Matematika + Matematika Dasar | 34 + BAB 2 + + PENALARAN DALAM + MATEMATIKA + + PENDAHULUAN + Dalam kehidupan ini, kita sering mengalami berbagai +peristiwa, baik itu peristiwa menyenangkan maupun peristiwa +tidak menyenangkan. Contoh peristiwa menyenangkan adalah +kita mendapat rezeki, sedangkan contoh peristiwa tidak +menyenangkan, adalah pada saat kita mendapat cobaan sakit. +Jika kita menghadapi peristiwa yang menyenangkan, kita tidak +boleh terlalu bergembira tetapi kita harus mensyukuri nikmat +Allah SWT, sebaliknya jika menghadapi peristiwa yang tidak +menyenangkan kita tidak boleh terlalu larut dalam kesedihan, +tetapi kita harus berpikir positif dan mengunakan akal dan +penalaran kita. Seringkali kita berpendapat dengan +melibatkan perasaan, prasangka, dan membuat kesimpulan- +kesimpulan yang tidak berdasar. Kita sebagai manusia diberi +kelebihan oleh Allah SWT dalam bentuk akal yang kita +gunakan untuk berpikir dan bernalar. + Penalaran dapat diartikan sebagai cara berpikir, +merupakan penjelasan dalam upaya menunjukkan hubungan +antara beberap hal yang berdasarkan pada sifat-sifat atau +hukum-hukum tertentu yang diakui kebernarnnya. Secara + + 35 | Penalaran dalam Matematika + singkat, penalaran sebagai proses penarikan kesimpulan +dalam sebuah argumen. Kemampuan materi matematika +seseorang tidak dapat dilepaskan dari kemampuan penalaran. +Artinya materi matematika dapat dengan mudah dipahami +dengan adanya kemampuan bernalar yang baik. Bagaimana +seharusnya kita menggunakan penalaran yang baik? Oleh +karena itu, marilah kita membahas mengenai penalaran +tersebut. Penalaran dalam matematika ada dua jenis, yaitu: +penalaran induktif dan penalaran deduktif. + +Aktivitas Kegiatan 1: +1. Gambarlah segitiga lancip, segitiga siku-siku, dan segitiga + + tumpul! +2. Dengan menggunakan busur derajat, hitunglah besar + + sudut masing-masing segitiga tersebut! +3. Berapa derajatkah jumlah ketiga sudut masing-masing + + segitiga tersebut? +4. Apakah yang dapat anda simpulkan dari kegiatan ini? + +Kegiatan 2: +Pertandingan sepakbola di wilayah timur Indonesia diikuti +oleh 15 kesebelasan. Sistem pertandingan menggunakan +sistem kompetisi penuh (setiap kesebelasan masing-masing +bertanding 2 kali dengan kesebelasan-kesebelasan lainnya, +yaitu satu kali bertanding di daerah sendiri dan satu kali +bertanding di daerah lawan). Berapa pertandingan yang akan +terjadi jika semua dilakukan? Jika n kesebelasan berapa +pertandingan yang dilakukan? + +Matematika Dasar | 36 + 1. Lengkapilah tabel berikut: + + Banyak Pertandingan Pola operasi hitung +kesebelasan yang terjadi + 1x0 + 1 0 2x1 + 2 2 3x2 + 3 … + 4 12 … + 5 … … + … … … + 15 … … + n … … + +2. Apakah yang dapat anda simpulkan dari kegiatan tersebut? + +Kegiatan 3: +Perhatikan gambar berikut: + +1 2 + + 3 + +Gambar ke-1 terdiri dari 1 persegi kecil +Gambar ke-2 terdiri dari 4 persegi kecil +Gambar ke-3 terdiri dari 9 persegi kecil + + a. Buatlah dua gambar berikutnya (yang ke-4 dan ke-5) + b. Berapa banyak persegi kecil pada gambar ke-n? + +Dari kegiatan 1, 2 dan 3 apa yang dapat anda simpulkan? +Bagaimana dengan permasalahan berikut ini? Apa yang dapat +kalian simpulkan? + + 37 | Penalaran dalam Matematika + Tentukan pola umum (generalisasi) yang mungkin berlaku +pada deret 1 + 3 + 5 + 7 + … + (2n  1), untuk setiap bilangan +asli n. Kemudian tentukan jumlah dari 1 + 3 + 5 + 7 + … + 199. + 1 = 1 = 12 = (1+1)2 + + 2 + + 1 + 3 = 4 = 22 = (1+3)2 + + 2 + + 1 + 3 + 5 = 9 = 32 = (1+5)2 + + 2 + + 1 + 3 + 5 + 7 = … = … = (1+⋯)2 + + 2 + + 1+3+5+7+9=…=…=… + + dan seterusnya. Dengan memperhatikan pola tersebut di + atas dapat diduga bahwa untuk sembarang bilangan asli + n berlaku : + 1 + 3 + 5 + 7 + ... + (2n – 1) = ... = n2 + Dengan menggunakan pola umum yang telah diperoleh + tentukan jumlah + 1 + 3 + 5 + 7 + ... + 199 + +A. PENALARAN INDUKTIF + + Kalau hujan turun dengan lebat, biasanya kita akan +membuat kesimpulan bahwa; sebentar lagi akan terjadi banjir. +Kesimpulan seperti ini merupakan suatu dugaan. Dugaan +tersebut diambil berdasar pada pengalaman sebab biasanya +kalau turun hujan, maka dimana-mana terdapat genangan air +karena tersumbatnya saluran. Contoh seperti ini merupakan +salah satu penalaran induktif. + + Penalaran induktif adalah proses berpikir untuk +menarik suatu kesimpulan yang berlaku umum berdasarkan +atas fakta-fakta yang bersifat khusus. Penalaran induktif +digunakan oleh beberapa cabang ilmu pengetahuan seperti +fisika, kimia, biologi, dan sebagainya untuk membangun suatu + +Matematika Dasar | 38 + teori baru. Sebagai contoh dalam ilmu fisika, dalam suatu +percobaan seorang peneliti berhasil menunjukkan bahwa +besi, seng, perak, dan aluminium apabila dipanaskan akan +memuai. Berdasarkan hasil percobaan tersebut, peneliti +tersebut mengamati bahwa besi, seng, perak dan aluminium +termasuk jenis logam. Oleh karena itu kemudian ia membuat +suatu generalisasi bahwa setiap logam apabila dipanaskan +memuai. + + Dengan demikian dapat disimpulkan bahwa berpikir +induktif adalah berpikir menggunakan kejadian atau +pengalaman yang sering dijumpai disimpulkan menjadi +kebenaran secara umum. + + BERPIKIR KRITIS + + n2 + n + 41 merupakan bilangan prima, untuk n + bilangan asli 1 sampai dengan 40. Apakah + diperoleh bilangan prima? Bagaimana untuk n = + 41? Apakah juga diperoleh bilangan prima? + +B. PENALARAN DEDUKTIF + Berlawanan dengan pemikiran induktif adalah berpikir + +deduktif. Penalaran deduktif yaitu proses berpikir +berdasarkan atas suatu pernyataan dasar yang berlaku umum +untuk menarik suatu kesimpulan yang bersifat khusus. +Penalaran deduktif digunakan dalam matematika. Aturan yang +berlaku secara umum tersebut, pada umumnya dibuktikan + + 39 | Penalaran dalam Matematika + terlebih dahulu kebenarannya dan setelah terbukti +kebenarannya baru diterapkan untuk kasus-kasus yang +bersifat khsusus. Sebagai contoh, diberikan aturan umum +bahwa sudut-sudut yang bertolak belakang adalah kongruen, +diketahui sudut A bertolak belakang dengan sudut B dan +ukuran sudut B adalah 60o, maka kesimpulannya ukuran +sudut A adalah 60o. + + Pada mulanya, matematika timbul karena adanya +pikiran-pikiran manusia yang berhubungan dengan ide, +proses dan penalaran. Oleh karena itu, walaupun matematika +menggunakan penalaran deduktif, namun para +matematikawan dapat menyusun atau menemukan bagian- +bagian matematika dengan menggunakan penalaran induktif. +Tetapi begitu pola umum atau generalisasi ditemukan maka +pola umum atau generalisasi tersebut harus dapat dibuktikan +kebenarannya secara deduktif. + + Penalaran deduktif berlangsung dari pernyataan yang +umum ke khusus. Proses untuk sistem penalaran dalam +matematika secara deduktif diawali dengan membuat suatu +konsep pangkal. Konsep pangkal sebagai sarana komunikasi +untuk menyusun pertanyaan-pertanyaan selanjutnya berupa +definisi, aksioma maupun teorema. + + Contoh 2.1: + Diketahui: Berdasarkan aksioma-aksioma + A1: pada R berlaku hukum komutatif perkalian + A2: pada R berlaku hukum distributive perkalian pada + penjumlahan + A3: a2 = a x a untuk setiap a ∈ R + Maka buktikan bahwa ∀, ∈ , ( + )2 = 2 + 2 + 2 + +Matematika Dasar | 40 + Bukti: karena A3 + (a + b)2 = (a + b)(a + b) karena A2 + (a + b)2 = (a + b) x a + (a + b) x b karena A1 + (a + b)2 = a x a + b x a + a x b + b x b karena A3 + (a + b)2 = a2 + 2ab + b2 + +C. LANGKAH-LANGKAH PENALARAN INDUKTIF & + DEDUKTIF + + Secara umum, langkah-langkah penalaran yang +digunakan dalam matematika sebagai berikut: + + 1. Mengamati pola-pola yang terjadi, + 2. Membuat dugaan (konjektur) tentang pola umum + + yang mugkin berlaku, + 3. Membuat generalisasi, + 4. Membuktikan generalisasi secara deduktif. + + Contoh 2.2: + + Tentukan pola umum (generalisasi) yang mungkin berlaku + + pada deret 1 + 2 + 3 + 4 + … + n, untuk setiap bilangan asli + + n. Kemudian tentukan jumlah dari 1 + 2 + 3 + 4 + … + 200. + + Pembahasan: + +1 = 1 = 1. 2 = 11  1 . + + 2 2 + +1+2 = 3 = 2. 3 = 22  1 . + + 2 2 + +1+2+3 = 6 = 3. 4 = 33  1 + + 2 2 + +. + +1+2+3+4= 10 = 4. 5 = 44 1 + + 2 2 + +. + + 41 | Penalaran dalam Matematika + 1 + 2 + 3 + 4 + 5 = 15 = 5. 6 = 55  1 . + 2 + 2 + +dan seterusnya. Dengan memperhatikan pola tersebut di + +atas dapat diduga (digeneralisasikan) bahwa untuk + +sembarang bilangan asli n berlaku : + +1+2+3+…+n = nn 1 . + + 2 + +Dengan memperhatikan hasil generalisasi tersebut di atas + +diperoleh: 200200 1 20.100. +1 + 2 + 3 + … + 200 = = + 2 + + Dalam matematika, generalisasi pada contoh 1 tidak +dibenarkan dan perlu dibuktikan secara deduktif. Namun +untuk pembelajaran di Sekolah Dasar pembuktian secara +deduktif tidak perlu dilakukan, karena pada umumnya tahap +berpikir siswa Sekolah Dasar masih dalam tahap berpikir +induktif (tahap berpikir operasi konkret). + +Contoh 2.3: +Secara induktif, tentukan generalisasi yang mungkin +berlaku apabila sembarang dua buah bilangan ganjil +dikalikan, dan kemudian secara dedutif buktikan bahwa +generalisasi tersebut benar secara matematika. + +Pembahasan: +Untuk menyelidiki pola umum yang mungkin terjadi pada +perkalian sembarang dua buah bilangan ganjil, +perhatikan tabel 1 berikut: + + 1 3 5 7 + +1 1 3 5 7 + +3 3 9 15 21 + +Matematika Dasar | 42 + 5 5 15 25 35 + +7 7 21 35 49 + +Dengan memperhatikan tabel 1, terlihat bahwa polanya +adalah bilangan ganjil apabila dikalikan dengan bilangan +ganjil hasilnya juga bilangan ganjil. Oleh karena itu dapat +diduga (digeneralisasikan) bahwa bilangan ganjil apabila +dikalikan dengan bilangan ganjil hasilnya adalah bilangan +ganjil. + +Seperti telah dikemukakan sebelumnya bahwa dalam +matematika, generalisasi tersebut tidak dibenarkan dan +perlu dibuktikan secara deduktif. Untuk membuktikan +secara deduktif, perlu pengertian bilangan genap dan +bilangan ganjil sebagai berikut : + +Definisi 1 +(1). Bilangan bulat m dikatakan bilangan genap + + apabila terdapat bilangan bulat k sehingga + berlaku m = 2k. +(2). Bilangan bulat m dikatakan bilangan ganjil + apabila terdapat bilangan bulat k sehingga + berlaku m = 2k + 1. + +Bukti generalisasi Contoh 2.3. +Ambil sembarang dua buah bilangan ganjil m dan n. Akan +dibuktikan bahwa m × n bilangan ganjil. Karena m +bilangan ganjil maka terdapat bilangan bulat k sehingga +m = 2k + 1, dan juga karena n bilangan ganjil maka +terdapat bilangan bulat p sehingga n = 2p + 1. Selanjutnya +diperoleh : + + 43 | Penalaran dalam Matematika + m × n = (2k + 1) × (2p + 1) = 4kp + 2k + 2p + 1 = 2(2kp + k + + p) + 1 = 2r + 1, dengan r = 2kp + k + p. + Karena 2, k dan p masing-masing bilangan bulat maka r = + 2kp + k + p juga bilangan bulat, sebab penjumlahan dan + perkalian pada bilangan bulat bersifat tertutup. + Jadi terdapat bilangan bulat r sehingga m × n = 2r + 1. + Dengan kata lain m × n merupakan bilangan ganjil. + + Matematika merupakan bidang ilmu yang dalam + melakukan penalaran bukan berdasarkan induktif, tetapi + bersifat deduktif sebab penurunan suatu teorema tidak + didasarkan pada observasi umum tetapi berdasarkan + definisi, aksioma, dan teorema-teorema yang telah ada + sebelumnya. Satu hal yang perlu diperhatikan bahwa pola + induktif hanya digunakan sebagai pendekatan + pembelajaran matematika untuk tingkat SD. Namun + seiring dengan perkembangan berdasarkan teori Jean + Piaget, pola berpikir anak akan secara perlahan terbentuk + secara abstrak, tidak tergantung lagi terhadap benda- + benda kongrit dalam mengembangkan konsepnya. + +D. RANGKUMAN + +1. Penalaran induktif adalah proses berpikir untuk menarik + kesimpulan yang bersifat umum melalui pernyataan- + pernyataan yang bersifat khusus. + +2. Penalaran deduktif merupakan proses berpikir untuk + menarik kesimpulan yang berlangsung dari hal yang + umum ke hal yang khusus. + +3. Langkah-langkah penalaran yang umum yaitu mengamati + pola, membuat dugaan, melakukan generalisasi dan + membuktikan dengan deduktif. + +Matematika Dasar | 44 + E. LATIHAN + +1. Diskusikan dengan teman Anda untuk menentukan + contoh penggunaan penalaran induktif dan deduktif + dalam kehidupan sehari-hari. + +2. Diskusikan dengan teman Anda, penalaran mana yang + cocok untuk diterapkan pada pembelajaran matematika + di Sekolah Dasar, penalaran induktif atau deduktif? + +3. Diskusikan dengan teman Anda untuk menentukan + contoh penggunaan penalaran induktif dalam + pembelajaran matematika di Sekolah Dasar. + +4. Secara induktif, tentukan pola umum (generalisasi) yang + mungkin berlaku pada deret 2 + 4 + 6 + 8 + … + 2n, untuk + setiap bilangan asli n. Kemudian tentukan jumlah dari 2 + + 4 + 6 + 8 + … + 200. + +5. Secara induktif, tentukan pola umum (generalisasi) yang + +mungkin berlaku pada deret + + 1  1  1  1  , untuk setiap +1.2 2.3 3.4 + nn 1 + +bilangan asli n. Kemudian tentukan jumlah dari + +1  1  1  1 . +1.2 2.3 3.4 50.51 + +6. Untuk soal 3 + 8 dengan 8 + 3 bagi siswa kelas I SD + manakah soal yang dianggap lebih mudah? Berikan + alasannya. + +7. Buktikan bahwa bilangan ganjil ditambah bilangan ganjil + adalah bilangan genap! + + 45 | Penalaran dalam Matematika + Matematika Dasar | 46 + BAB 3 + + LOGIKA MATEMATIKA + + PENDAHULUAN + Logika adalah dasar dan alat berpikir yang logis dalam +matematika dan pelajaran-pelajaran lainnya, sehingga dapat +membantu dan memberikan bekal tambahan untuk +mempelajari bidang yang lain. Dalam Logika dipelajari +metode-metode dan prinsip-prinsip yang dapat dipakai untuk +membedakan cara berpikir benar (correct) atau tidak benar +(incorrect), sehingga dapat membantu menyatakan ide-ide +tepat dan tidak mempunyai arti ganda. Jadi, dalam ilmu logika +hanya mempelajari atau memperhatikan kebenaran dan +kesalahan dari penalaran, dan penarikan kesimpulan dari +sebuah pernyataan atau lebih. + Secara teoritis belajar logika adalah tidak hanya +belajar bagaimana menalar dengan benar, melainkan juga +mengenal bentuk-bentuk penarikan kesimpulan yang absah. +Simbol-simbol dalam logika, seperti juga dalam bidang +matematika lainnya merupakan sarana yang penting untuk +melakukan penalaran. + + 47 | Logika Matematika + A. PERNYATAAN +Aktivitas: +Perhatikan kalimat-kalimat berikut: +1. Sebuah segiempat mempunyai empat sisi +2. Ibukota provinsi Jawa Tengah adalah Semarang +3. Apakah Ratih berada di rumahmu? +4. Alangkah indahnya lukisan ini! +5. Makassar adalah ibukota provinsi Sulawesi Tenggara +6. Tutuplah pintu itu! +7. Semoga anda lekas sembuh + +Dari kalimat-kalimat diatas: + a. Sebutkan jenis kalimat-kalimat tersebut! + b. Kalimat mana saja yang merupakan pernyataan + c. Bagaimana ciri-ciri kalimat yang merupakan + pernyataan. + +B. KALIMAT TERBUKA + Kalimat terbuka adalah kalimat yang belum dapat + +ditentukan nilai kebenaraanya. Ciri dasar kalimat terbuka +adalah adanya peubah atau variabel. + + Contoh 3.1: + a. 2x - 5 = 9 + b. 3 + n adalah bilangan prima + c. Kota A adalah ibukota provinsi Sulawesi Selatan + +C. PERNYATAAN + + Pernyataan adalah suatu kalimat yang mempunyai +nilai logika (kebenaran) benar saja atau salah saja dan tidak +duanya. Istilah-istilah lain dari pernyataan adalah kalimat + +Dasar Matematika | 48 + matematika tertutup, kalimat tertutup, kalimat deklaratif, +statement atau proposisi. + + Setiap pernyataan adalah sebuah kalimat, tetapi suatu +kalimat belum tentu s u at u pernyataan. Hanyalah kalimat- +kalimat yang bersifat “menerangkan sesuatu” (kalimat +deklaratif) yang dapat digolongkan sebagai pernyataan. +Akan tetapi, tidak semua kalimat yang menerangkan sesuatu +dapat digolongkan sebagai pernyataan. + +Contoh 3.2: +Suatu pernyataan dan nilai kebenarannya. +1. Bangun datar segiempat memiliki empat titik sudut. + + (benar) +2. 2 adalah bilangan prima (benar) +3. 5 – 7 = 2 (salah) +4. Segitiga sama sisi memiliki tiga sudut yang sama + + besar. (benar) + +Contoh 3.3: variabel yang +Bukan pernyataan +1. Bukalah pintu itu! + +2. x lebih besar dari 3 (xadalah + menunjukkan bilangan). + +3. Apakah ariefat sudah makan? + +Suatu pernyataan dinotasikan dengan huruf kecil seperti p, q, +r dsb. +Misalnya: + + P: Semua bilangan prima adalah ganjil + q: Jakarta ibukota Indonesia + +Ada 2 dasar untuk menentukan nilai kebenaran suatun +pernyataan yaitu : + +49 | Logika Matematika + a. Dasar empiris: jka nilai kebenaran ditentukan dengan + pengamatan pada saat tertentu. + + Contoh 3.4: + * Rambut adik panjang + * Besok pagi cuaca cerah +b. Dasar tidak empiris: jka nilai kebenaran ditentukan + menurut kaidah atau hukum tertentu. Jadi nilai mutlak + tidak terikat oleh waktu dan tempat. + + Contoh 3.5: + * Jumlah sudut dalam segitiga adalah 1800 + * Gunung Latimojong terletak di Kabupaten Enrekang + +D. INGKARAN DARI PERNYATAAN + + Ingkaran atau negasi dari suatu pernyataan adalah +pernyataan yang mengingkari pernyataan semula. Ingkaran +dari pernyataan p dinotasikan ~ p dibaca “ bukan p” atau +“tidak p”. + + Contoh 3.6: + a. p : Ibu pergi ke pasar + + ~ p : Ibu tidak pergi ke pasar + b. q : 2 + 7 < 10 + + ~ q : 2 + 7  10 + + c. r : 7 – 3 = 4 + + ~r :7–3 4 + +E. PERNYATAAN TUNGGAL DAN MAJEMUK + + Suatu kalimat selain dibedakan atas pernyataan dan +bukan pernyataan, kalimat juga dibedakan pula atas +pernyataan tunggal dan pernyataan majemuk. Pernyataan +tunggal atau pernyataan sederhana adalah pernyataan yang + +Dasar Matematika | 50 + tidak memuat pernyataan lain atau sebagai bagiannya, +sedangkan pernyataan majemuk dapat merupakan kalimat +baru yang diperoleh dengan cara menggabungkan beberapa +pernyataan tunggal. + + Dua pernyataan tunggal atau lebih dapat digabungkan +menjadi sebuah kalimat baru yang merupakan pernyataan +majemuk, sedangkan tiap pernyataan bagian dari pernyataan +majemuk disebut komponen-komponen pernyataan +majemuk. Komponen-komponen dari pernyataan majemuk +itu tidak selamanya harus pernyataan tunggal, tetapi mungkin +saja pernyataan majemuk. Namun yang terpenting adalah +bagaimana menggabungkan pernyataan-pernyataan tunggal +menjadi pernyataan majemuk. + + Untuk menggabungkan pernyataan-pernyataan +tunggal menjadi pernyataan majemuk dapat dipakai kata +gabung atau kata perangkai yang disebut operasi-operasi +logika matematika. + + Contoh 3.7: + 1. Merah putih adalah bendera negara RI + 2. 2 adalah bilangan prima yang genap + 3. Jika suatu bilangan habis dibagi dua maka bilangan itu + + genap + +F. TABEL KEBENARAN PERNYATAAN + + Tabel kebenaran adalah suatu tabel yang memuat nilai +kebenaran pernyataan-pernyataan tunggal atau pernyataan- +pernyataan majemuk. Untuk melengkapi tabel kebenaran +pernyataan, harus diketahui dulu berapa banyak pernyataan +yang termuat yang berlainan dalam tabel tersebut. Langkah + + 51 | Logika Matematika + ini diperlukan agar tidak ada kemungkinan komposisi nilai +kebenaran yang mungkin tidak tertuliskan. + +Contoh 3.8: +Jika terdapat dua pernyataan berlainan, maka +kemungkinan-nya adalah: +1. Pernyataan pertama benar, pernyataan kedua benar +2. Pernyataan pertama benar, pernyataan kedua salah +3. Pernyataan pertama salah, pernyataan kedua benar +4. Pernyataan pertama salah, pernyataan kedua salah +Berarti ada empat komposisi pernyataan jika terdiri dari +dua pernyataan yang berlainan. Dalam bentuk tabel +kebenaran sebagai berikut: + + p q + + B B + + B S + + S B + + S S + + Jika diperhatikan, ternyata dua pernyataan +mempunyai 4 kemungkinan komposisi. Jadi, banyaknya +komposisi itu tergantung pada banyaknya pernyataan yang +akan digabungkan. Secara umum berlaku jika banyaknya +pernyataan ada n, maka banyaknya komposisi adalah 2n. +Contoh 3.9: +Jika ada 3 pernyataan yang akan digabungkan maka +banyaknya pernyataan yang dapat dibuat adalah 23 = 8. Dalam +bentuk tabel kebenaran: + +p q s + +B B B + +B B S + +B S B + +B S S + +Dasar Matematika | 52 + S B B + +S B S + +S S B + +S S S + +G. OPERASI LOGIKA + + Suatu pernyataan hanyalah bisa benar saja atau salah +saja. Kebenaran atau kesalahan dari suatu pernyataan disebut +nilai kebenaran dari pernyataan itu. Untuk pernyataan yang +mempunyai nilai benar diberi tanda huruf kapital B, +sedangkan untuk pernyataan yang mempunyai nilai salah +diberi tanda huruf kapital S. Telah diuraikan sebelumnya +bahwa pernyataan terdiri dari pernyataan tunggal dan +pernyataan majemuk. Pernyataan majemuk adalah +pernyataan yang terdiri dari gabungan beberapa pernyataan +tunggal. Untuk lebih memahami bentuk pernyataan majemuk +perhatikan beberapa contoh berikut: +1. Hari ini terjadi hujan atau panas +2. 13 adalah bilangan prima dan bilangan ganjil +3. Jika malam nanti cerah maka saya akan datang ke + + rumahmu +4. Suatu segitiga adalah sama sisi jika dan hanya jika ketiga + + sudutnya sama besar. +5. Ibu membeli baju dan sepatu untuk adik + + Untuk menggabungkan pernyataan-pernyataan +tunggal menjadi pernyataan majemuk dapat dipakai kata +gabung atau kata perangkai yang disebut operasi-operasi +logika matematika. Adapun operasi-operasi yang dapat +membentuk pernyataan majemuk adalah: + 1. Negasi/ingkaran, dengan kata perangkai tidaklah benar, + + simbol “ ~ “ + 2. Konjungsi, dengan kata perangkai dan, simbol “  “ + + 53 | Logika Matematika + 3. Disjungsi, dengan kata perangkai atau, simbol “  “ +4. Implikasi, dengan kata perangkai Jika …, maka …., simbol “ + + “ +5. Biimplikasi, dengan kata perangkai ...jika dan hanya jika, + + simbol “  “ + +H. KONJUNGSI + + Suatu pernyataan majemuk yang dibentuk dengan +cara menggabungkan dua pernyataan tunggal dengan +memakai kata perangkai ”dan” disebut konjungsi. Operasi +konjungsi dilambangkan dengan “  “ + + Definisi: Sebuah konjungsi bernilai benar jika komponen- + komponennya bernilai benar, dan bernilai salah jika salah + satu dari komponennya bernilai salah +Definisi diatas dapat ditulis dalam tabel kebenaran sbb: + + p q pq + + B B B + + B S S + + S B S + + S S S + +Contoh 3.10: + +p : diagonal-diagonal persegi saling berpotongan + + tengak lurus. + +q : diagonal persegi sama panjang + +pq : diagonal-diagonal persegi saling berpotongan + + tengak lurus dan diagonal persegi sama + + panjang + +pernyataan p  q bernilai benar sebab p bernilai benar + +dan q bernilai benar. + +Dasar Matematika | 54 + I. DISJUNGSI + + Suatu pernyataan majemuk yang dibentuk dengan +cara menggabungkan dua pernyataan tunggal dengan +memakai kata perangkai atau disebut disjungsi. Operasi +disjungsi dilambangkan dengan “  “ + + Definisi: Sebuah disjungsi inklusif bernilai benar jika paling + sedikit salah satu komponennya bernilai benar, sedangkan + disjungsi eksklusif bernilai benar jika paling sedikit + komponennya bernilai benar tetapi tidak kedua-duanya. + +Definisi diatas dapat ditulis dalam tabel kebenaran sbb: + +Disjungsi Inklusif: + +p q pq + +B B B + +B S B + +S B B + +S S S + +Disjungsi Eksklusif: + +p q p q + +B B S + B +B S B + S +S B + +S S + + 55 | Logika Matematika + Contoh 3.11: +Disjungsi inklusif : seseorang yang boleh melamar CPNS +adalah warga Negara Indonesia lulus SMA atau yang +sederajat. +Disjungsi eksklusif : saya berada dirumah atau disekolah + +J. IMPLIKASI + + Suatu pernyataan majemuk yang dibentuk dengan +cara menggabungkan dua pernyataan tunggal dengan +memakai kata perangkai ”Jika Maka” disebut implikasi +disimbolkan dengan “  “ + + Definisi: Sebuah pernyataan implikasi hanya salah jika + antesedennya benar dan konsekwennya salah, dalam + kemungkinan lainnya implikasi bernilai benar. + +Pernyataan majemuk “jika p maka q” yang dibentuk dari +pernyataan p dan q disebut implikasi dan dituliskan p  q. +Pernyataan p  q dapat dibaca: + +  Jika p, maka q. +  p mengimplikasi q . +  q hanya jika q . +  q jika p. +  q asal saja p +  p adalah syarat cukup untuk q . +  q adalah syarat perlu untuk p . + +Definisi tersebut dapat ditulis dalam tabel kebenaran sbb: + +P q pq + +B B B + +B S S + +S B B + +S S B + +Dasar Matematika | 56 + Contoh 3.12: + +p : 11 adalah bilangan prima + +q : Jumlah sudut-sudut dalam segitiga 1800 + +p  q : jika 11 adalah bilangan prima maka jumlah + + sudut-sudut dalam segitiga 1800 + +K. BIIMPLIKASI + + Suatu pernyataan majemuk yang dibentuk dengan +cara menggabungkan dua pernyataan tunggal dengan +memakai kata perangkai … jika dan hanya jika... disebut +biimplikasi. Operasi biimplikasi dilambangkan dengan “  “ + + Definisi: Sebuah pernyataan biimplikasi bernilai benar jika + komponen-komponennya mempunyai nilai kebenaran sama, + dan jika komponen-komponennya mempunyai nilai + kebenaran tidak sama maka biimplikasi bernilai salah. + +Definisi diatas dapat ditulis dalam tabel kebenaran sbb: + + p q pq + + B B B + + B S S + + S B S + + S S B + +Contoh 3.13: + +p : Segitiga ABC adalah segitiga sama sisi + +q : Ketiga sisi segitiga ABC sama panjang + +p  q : Segitiga ABC adalah segitiga sama sisi jika dan + + hanya jika ketiga sisi segitiga ABC sama + + panjang + + 57 | Logika Matematika + L. BENTUK-BENTUK PERNYATAAN + +1. Tautologi, Kontradiksi, dan Kontegensi + a. Tautologi + Jika nilai kebenaran pernyataan majemuk adalah + benar dalam segala hal, tanpa memandang nilai + kebenaran komponen-komponennya. Dalam tabel + kebenaran, suatu tautologi selalu bernilai benar (B) + pada setiap barisnya. + +b. Kontradiksi + Jka suatu pernyatan majemuk dengan nilai + kebenaran pernyataannya salah dalam segala hal, + tanpa memandang komponen-komponennya. Dalam + tabel kebenaran, suatu kontradiksi selalu bernilai + salah (S) pada setiap barisnya. + +c. Kontigensi + Suatu pernyataan majemuk tidak harus mempunyai + nilai kebenaran selalu benar atau selali salah untuk + segala hal. Bisa jadi pernyataan majemuk itu + mempunyai nilai kebenaran benar pada suatu situasi + dan mempunyai nilai kebenaran salah pada situasi + yang lain. Secara umum, sebuah pernyataan + majemuk dinamakan kontigensi, jika nilai + kebenarannya merupakan kumpulan nilai benar dan + salah diluar tautologi dan kontradiksi. + +Contoh 3.14: +Selidiki pernyataan di bawah ini apakah suatu tautologi, + +kontradiksi atau kontingensi! (~p  q)  (q p) + +p q ~p ~p  q q p ( ~p  q)(q  p) + +BB S S B B + +Dasar Matematika | 58 + BS S S B B + +SB B B S B + +SS B S B B + +Karena pada tabel kebenaran di atas benar semua, maka +pernyataan di atas suatu tautologi + +2. Implikasi Logis dan Ekuivalen Logis + Suatu bentuk pernyataan implikasi yang merupakan + tautologi disebut implikasi logis. + + Contoh 3.15: + + Selidikilah apakah bentuk pernyataan majemuk [( p  + q)p] p merupakan implikasi logis atau bukan. + +p q p q (p q )  p [( p q)p] p + +BB B B B + +BS S S B + +SB B S B + +SS B S B + +Dua atau lebih pernyataan majemuk yang mempunyai nilai +kebenaran sama disebut ekwivalen logis dengan notasi “  “ +atau “  “ + +Contoh 3.16: p q +Selidikilah apakah bentuk pernyataan majemuk +ekivalen logis dengan + +(p q)  (q  p) + +p q p q p q q p (p q)  (q  p) + +BB B B B B + + 59 | Logika Matematika + BS S S B S + +SB S B S S + +SS B B B B + +Karena p q mempunyai nilai kebenaran sama dengan (p  +q)(q  p), maka kedua pernyataan majemuk di atas disebut + +ekwivalen logis. + +Jadi, p q  (p q)(q  p) + +3. Konvers, Invers dan Kontraposisi + +  Jika suatu bentuk implikasi p q diubah menjadi q  + + p disebut konvers + +  Jika suatu bentuk implikasi p q diubah menjadi ~p + ~q disebut invers + +  Jika suatu bentuk implikasi p q diubah menjadi ~q + ~p disebut kontraposisi + +Adapun skema konvers, invers dan kontraposisi dapat + +dilihat sbb: + + konvers + +p q qp + +invers kontaposisi invers + +~p ~q ~q ~p + + Konvers + +Contoh 3.17: +Carilah konvers, invers dan kontraposisi dari pernyataan: + + “ Jika binatang itu bertubuh besar maka binatang itu + disebut gajah “ + +Dasar Matematika | 60 + Konvers : Jika binatang itu disebut gajah maka binatang + Itu bertubuh besar + + Invers : Jika binatang itu tidak bertubuh besar maka + binatang itu bukan gajah + + Kontraposisi : Jika binatang itu bukan gajah maka binatang + itu tidak bertubuh besar + + Silahkan anda mencoba soal berikut untuk lebih + memahami konvers, invers dan kontraposisi: + Buatlah konvers, invers dan kontraposisi dari pernyataan + berikut dan tentukan nilai kebenarannya. + 1. Jika dua buah garis saling tegak lurus maka kedua + + garis itu membentuk sudut siku-siku + + 2 + + 2. Jika x = 3 maka x = 9 + +M. KUANTOR + + Suatu Kuantor adalah suatu ucapan yang apabila +dibubuhkan pada suatu kalimat terbuka akan mengubah +kalimat terbuka tersebut menjadi suatu kalimat tertutup atau +pernyataan. + +Kuantor dibedakan atas: +1. Kuantor Universal / Umum ( Universal Quantifier ), + + notasinya : “  ” + + Misalkan p(x) adalah suatu kalimat terbuka, dengan x + anggota himpunan semesta pembicaraan S + + Pernyataan : (x  S) p(x) atau (x) p(x) + + Dibaca “untuk setiap x, berlaku p(x)” + Penggunaaan kata “untuk setiap” pada + kuantor universal senilai dengan kata + “untuk semua”, untuk tiap-tiap”, dan + “untuk seluruhnya” + + 61 | Logika Matematika + Contoh 3.18: + + 1. Tuliskan kalimat “untuk setiap n anggota himpunan + bilangan asli N, berlaku n anggota himpunan + bilangan real R” dengan notasi matematika + + 2. Jika semesta pembicaraannya bilangan real R, + + tentukan nilai kebenaran dari (x)(x  3  6) + + Jawab: + + 1. (n) n  N  n  R + 2. (x)(x  3  6) bernilai salah. Karena ada nilai x + + yang tidak memenuhi, misalnya x = 4. Akibatnya, 4 + + 3 < 6 (bernilai salah). Dengan demikian tidak berlaku + + untuk setiap x  R + +2. Kuantor Khusus ( Kuantor ( Eksistensial Quantifier ), + + notasinya : “  “ + + Misalkan p(x) adalah suatu kalimat terbuka pada suatu + himpunan semesta pembicaraan S + + Pernyataan (x  S ) p(x) atau (x) p(x) + + Dibaca “terdapat x sehingga p(x)” + Kata “terdapat” senilai dengan kata “ada”, + “beberapa”, “untuk suatu”, dan “untuk paling + sedikit satu” + + Contoh 3.19: + Tentukan nilai kebenaran dari kalimat berkuantor + eksistensial berikut jika x dan y adalah anggota himpunan + bilangan real R. + + a. (x)(x2  6x  8  0) + b. (x)(y)(x2  2 y  3) + +Dasar Matematika | 62 + Jawab: benar. Misalnya + benar. Misalnya +a. (x)(x2  6x  8  0) bernilai + + diambil x = 2 atau x = 4 + +b. (x)(y)(x2  2 y  3) bernilai + + diambil x =1 dan y = 1 + +N. NEGASI PERNYATAAN BERKUANTOR + + Negasi pernyataan “Semua manusia akan mati” adalah +“Tidak benar bahwa semua manusia akan mati” atau “Beberapa +manusia tidak akan mati”. Negasi pernyataan “Beberapa +manusia memakai baju putih” adalah “Tidak benar bahwa +beberapa manusia memakai baju putih” atau “ Semua manusia +tidak memakai baju putih”. + +Dengan demikian, jika dituliskan secara simbolik adalah: +  x p(x) negasinya x ~ p(x) + x p(x) negasinya x ~ p(x) +  x y p(x,y) negasinya x y ~ p(x,y) + x y p(x,y) negasinya x y ~ p(x,y) + + Contoh 3.20: + 1. Negasi dari pernyataan: “ Semua mahasiswa tidak + + mengerjakan tugas “ adalah “ Ada mahasiswa yang + mengerjakan tugas “ + Jika diberikan notasi, maka pernyataan di atas + menjadi: + + x, M(x)  T( x) , negasinya  x, M(x)  T(x) + +2. Tentukan negasi dari kalimat berkuantor + + (x)(y)(x2  y 2  25) + +Jadi negasinya adalah (x)(y) ~ (x2  y 2  25) + +atau + + (x)(y)(x2  y 2  25) + + 63 | Logika Matematika + O. PENARIKAN KESIMPULAN + +1. Argumen + Argumen merupakan kumpulan pernyataan-pernyataan + yang dikelompokkan dalam dua bagian yaitu premis dan + konklusi. Premis tersusun atas pernyataan-pernyataan + yang digunakan sebagai data untuk menghasilkan + pernyataan baru berupa konklusi atau kesimpulan. + + Contoh 3.21: + 1) Jika bilangan dan logika diperlukan maka semua + + mahasiswa belajar matematika + 2) Bilangan dan logika diperlukan + + ∴ semua manusia belajar matematika + + Pernyataan (1) dan (2) merupakan premis, sedangkan ∴ + merupakan kesimpulan dari argument tersebut. + + Contoh 3.22: + Jika kita makan nasi satu piring maka perut kita kenyang, + dan jika kita minum air jeruk satu gelas maka badan kita + segar. Jadi kita makan nasi satu piring dan minum air + jeruk satu gelas maka perut kita kenyang dan badan kita + segar. + + Tentukan premis dan konklusi dari argument tersebut. + Suatu argumen dikatakan valid apabila untuk sembarang + pernyataan-pernyataan yang ada dalam premis benar + maka kesimpulannya juga benar. Sebaliknya, meskipun + semua premis benar tetapi ada kesimpulan yang salah + maka argument tersebut dikatakan tidak valid. Dengan + kata lain, penarikan kesimpulan dikatakan valid jika + kebenaran konjungsi pernyataan-pernyataan yang ada + pada premis mengakibatkan secara logic kebenaran + konklusi. + +Dasar Matematika | 64 + Bukti Keabsahan Argumen +Bukti keabsahan argumen dapat melalui: + + 1. Tabel Kebenaran + 2. Aturan Penyimpulan + +Untuk argumen sederhana atau argumen yang premis- +premisnya hanya sedikit bukti keabsahan argumen dapat +menggunakan tabel kebenaran, namun untuk argumen yang +premis-premisnya kompleks harus menggunakan aturan- +aturan yang ada pada logika diantaranya aturan penyimpulan. + +Tabel Kebenaran +Contoh 3.23: + +Buktikan keabsahan argumen + +a. 1. p q + + 2. ~ q / ~p + +b. 1. a b + 2. c d + + 3. ( ~b~d )  ( ~a~b )/ ~a ~c (latihan) + +Bukti: +menggunakan tabel kebenaran + +p q ~p ~q p q [(p q)  ~q] [(p q)  ~q] +  ~p +BB S S B S + B +BS S B S S B + B +SB B S B S B + +S S B B B B + + Karena dari tabel kebenaran di atas menunjukkan +tautologi, maka argumen sah atau valid + + 65 | Logika Matematika + Aturan Penyimpulan + +1. Modus Ponens (MP) + + p q + + p /q + +2. Modus Tolens (MT) + + p q + + ~q / ~p + +3. Hypothetical Syllogisme (HS) + + p q + q r / p r + +4. Disjunctive Syllogisme (DS) + pq + ~p /  q + +5. Constructive Dillema (CD) + + (p q )  ( r s ) + + pr / q v s + +6. Destructive Dillema (DD) + + (p q)  (r s) + + ~q~s / ~p~r + +7. Conjunction (Conj) + p + q / p  q + +8. Simplification (Simpl) + pq + p + +9. Addition ( Add) + p + pq + +Dasar Matematika | 66 + Aturan Penggantian +1. De Morgan + + a. ~( p  q )  ~ p ~q + b. ~( pq )  ~p ~q + +2. Komutatif + a. ( p  q )  ( q  p ) + b. ( p V q )  ( q V p ) + +3. Asosiatif + a. ( pq )  r  p ( qr ) + b. ( p  q )  r  p  ( q  r ) + +4. Distributif + a. ( pq )  r  ( p  r )  ( q  r ) + b. ( p  q ) r  ( pr )  ( qr ) + +5. Dobel Negasi + ~(~ p )  p + +6. Implikasi + + p q  ~pq + +7. Material Equivalen + + a. p  q  ( p q )  ( q p ) + + b. p  q  ( p  q )  ( ~ p  ~ q ) + +8. Eksportasi + + p  ( qr )  ( p  q ) r + +9. Transposisi + + p q  ~q  ~p + +10. Tautologi + a. ( pp )  p + b. ( p  p )  p + + 67 | Logika Matematika + Namun, dari aturan penyimpulan dan aturan penganti +yang sering digunakan dalam penarikan kesimpulan adalah +modus ponens, modus tollens, dan modus silogisme. +(1) Modus Ponens + + Modus ponens merupakan salah satu bentuk aturan + penyimpulan yang bentuk argumennya: + + p q + + p /q + jika dinyatakan dalam implikasi maka argumen tersebut + adalah + [( ⇒ ) ∧ ] ⇒ yang nilai kebenarannya merupakan + tautologi. + + Contoh 3.24: + 1) Jika lampunya terang, maka Aldi dapat membaca + + dengan jelas + Lampunya terang + Karena itu, Aldi dapat membaca dengan jelas + 2) Jika lampunya terang, maka Aldi dapat membaca + dengan jelas + Aldi dapat membaca dengan jelas + Karena itu, lampunya terang + 3) Jika lampunya terang, maka Aldi dapat membaca + dengan jelas + Lampunya tidak terang + Karena itu, Aldi tidak dapat membaca dengan jelas + + Dari ketiga argumen tersebut, selidiki yang mana + merupakan argumen yang valid (sah)! + +(2) Modus Tollens + Modus tollens juga merupakan salah satu bentuk dari + aturan penyimpulan yang bentuk argumennya + + p q + +Dasar Matematika | 68 + ~q / ~p + jika dinyatakan dalam bentuk implikasi maka argumen + tersebut adalah + [( ⇒ ) ∧ ¬] ⇒ ¬ yang nilai kebenarannya dalam + bentuk tautologi. + + Contoh 3.25: + 1) Jika membayar pajak tidak terlambat maka tidak + + akan kena denda + Kena denda + Berarti membayar pajak + 2) Jika membayar pajak tidak terlambat maka tidak + kena denda + Membayar pajak terlambat + Karena itu, kena denda + + Dari kedua argumen tersebut, selidiki yang mana + merupakan argumen yang valid. + +(3) Modus Silogisme + Silogisme merupakan sebuah konsep pengambilan + kesimpulan dengan menggunakan aturan rantai yaitu: + + p q + q r / p r + + bentuk implikasi dari silogisme adalah [( ⇒ ) ∧ ( ⇒ + ] ⇒ ( ⇒ ) yang merupakan tautologi. + + Contoh 3.26 + 1) Jika hari ini ibu ke pasar, maka ibu beli ikan + + ⇒ + Jika ibu beli ikan, maka ibu memasak ikan + + ⇒ + Jika ibu memasak ikan, maka ibu tidak membuat kue + + ⇒ + + 69 | Logika Matematika + Hari ini ibu ke pasar + + + Karena itu, ibu tidak membuat kue + ∴ + + Penyelesaian: + Misalkan: + (1) ⇒ + (2) ⇒ + (3) ⇒ + (4) + (5) ∴ + Dari (1) dan (2) diperoleh dengan modus silogisme + yaitu ⇒ + Dari ⇒ dengan (3) dengan modus silogisme + diperoleh ⇒ + Dari ⇒ dengan (4) dengan modus ponens diperoleh + + Jadi argumen tersebut adalah valid. + 2) Jika hari ini ibu ke pasar, maka ibu membeli ikan + + Jika ibu membeli ikan, maka ibu memasak ikan + Jika ibu memasak ikan, maka ibu tidak membuat kue + Ibu membuat kue + Karena itu, hari ini ibu tidak ke pasar. + 3) Jika hari ini ibu ke pasar, maka ibu membeli ikan + Jika ibu membeli ikan, maka ibu memasak ikan + Jika ibu memasak ikan, maka ibu tidak membuat kue + Ibu tidak membuat kue + Karena itu, hari ini ibu ke pasar + Selidiki keabsahaan argumen (2) dan (3)! + +Dasar Matematika | 70 + P. PENERAPAN LOGIKA MATEMATIKA + Logika matematika dengan nilai kebenarannya tidak + +hanya berguna untuk menetapkan besar atau salahnya +pernyataan, tetapi secara pratis banyak aplikasi dalam +kehidupan sehari-hari. Salah bentuk penerapan logika +matematika dalam rangkaian listrik. + + Secara umum rangkaian listrik yang sering kita jumpai +dalam peralatan elektronik dibedakan menjadi dua yaitu +rangkaian seri dan paralel. Pada rangkaian seri lampu akan +menyala hanya apabila misalkan saklar p dan saklar q dalam +posisi menyala (on), jika tidak lampu akan mati. Perhatikan +ilustrasi berikut: + +Rangkaian listrik seri merupakan konsep dari konjugsi ( ∧ ). +Bagaimana dengan rangkaian paralel? + + Tuliskan simbol logika dari rangkaian listrik berikut: + + 71 | Logika Matematika + Q. RANGKUMAN +1. Pernyataan adalah kalimat matematika yang sudah jelas, + + sudah pasti benarnya atau salahnya dan tidak + mempunyai dua arti. Oleh karena itu, nilai kebenaran dari + pernyataan diberi benar (B) atau (S). +2. Pernyataan terdiri dari dua yaitu pernyataan tunggal dan + pernyataan majemuk. Pernyataan majemuk adalah + pernyataan yang mengandung pernyataan lain sebagai + komponennya. Jadi, terdiri dari beberapa pernyataan. +3. Operasi logika terdiri dari konjungsi, disjungsi, implikasi + dan biimplikasi. +4. Bentuk-bentuk pernyataan terdiri dari tautologi, + kontradiksi, kontigensi, konvers, invers, kontraposisi +5. Argumen merupkan kumpulan dari pernyataan- + pernytaaan yang terdiri dari premis dan konklusi. +6. Untuk membuktikan keabsahan argumen, dalam + melakukan penarikan kesimpulan yaitu dengan + menggunakan tabel kebenaran dan aturan penyimpulan. +7. Penarikan kesimpulan yang sering digunakan adalah + modus ponens, modus tollens, dan modus silogisme. + +Dasar Matematika | 72 + R. LATIHAN + +1. Nyatakan kalimat-kalimat berikut merupakan kalimat + terbuka atau pernyataan. jika pernyataan nyatakan nilai + kebenaranya : x + 2 = x – 2 dan 2(x + 1)+ 3 = 2x +5 + +2. Tuliskan negasi dari pernyataan 2 bilangan prima + dan 2 +3 sama dengan 5 + +3. Tentukan nilai kebenaran dari 3 bilangan prima atau + 5 bilangan genap dengan disjungsi + +4. Tentukan nilai kebenaran dari 6 bilangan prima dan + 3 bilangan ganjil dengan konjungsi + +5. Tentukan nilai kebenaran jika 2 + 3 = 5, maka 4 + 5 = 7 + dengan implikasi + +6. Tentukan nilai kebenaran 2 + 2 = 4 3 + 4 = 8 + +7. Tentukan konvers, invers, dan kontraposisi dari setiap + pernyataan implikasi berikut : + a. Jika harga BBM naik, maka harga kebutuhan sehari- + hari naik + b. Jika Carli siswa yang pandai, maka ia lulus tes + c. Jika harga turun, maka permintaan naik + + d. Jika n 2 ganjil maka n ganjil + +8. Selidiki apakah pernyataan-pernyataan di bawah ini suatu + + tautologi, kontradiksi atau kontingensi! ( p v q )  ( ~ p  + + r) + + a. [( p q )  ( q p )]  ( p  q ) + b. ( p  q )  ( p  ~q ) + c. ( p  q ) p + d. ( p q )  [ ( ~ q  r )  ( r  p ) ] + e. ( pq )  ( ~p  q ) + + 73 | Logika Matematika + f. ( p  q)  q + g. q  ( p ~ q) + +9. Selidiki apakah pernyataan di bawah ini implikasi logis, + ekwivalen logis atau tidak kedua-duanya + + a. [( p  q ) r]  [( p ~q ) v r] + b. [( p q ) r]  ( pq ) + c. [p  ( q r )]  [( p  q ) r] + d. [( p q ) v r ]  [( p  ~ q )  r] + e. [ ~ ( p  q )]  ( p  q ) + +10. Buktikan keabsahan argumen di bawah ini! + + a. j k + b. ( k l ) ~( m  n ) + c. (~m  ~n)  ( o  p ) + d. (o  p)  (q  r) / ( l  k )  (r  q) + +11. Buatlah notasi untuk pernyataan berkuantor di bawah ini! + 1) Semua pedagang asongan adalah pejalan kaki ( A(x), + K(x) ) + 2) Ada mahasiswa yang tidak mengerjakan tugas ( M(x), + T(x) ) + 3) Beberapa mahasiswa lomba Porseni ( M(x), L(x) ) + +12. Jika p(x) kalimat terbuka: x + 3 > 5 maka nyatakan + kedalam bentuk simbol pernyataan kuantor universal dan + kuantir eksistensial + +13. Jika x  bilangan bulat, maka tentukan nilai kebenaran + dari pernyataan-pernyataan di bawah ini! + + 1) (  x) (  y ) ( x + 2y = 7 ) + 2) (  x) (  y) (x + 2y = x) + 3) (  x) (  y) ( x > y ) + 4) (  x) (  y) ( x.y = 1 ) + +Dasar Matematika | 74 + 14. Ubahlah kalimat di bawah ini ke dalam notasi logika! + a. Tidak semua bunga mawar berwarna merah (B(x), + M(x)) + b. Semua mahasiswa baru harus mendaftar ulang (M(x), + U(x)) + c. Ada bilangan prima yang genap (P(x), G(x)) + d. Beberapa tamu yang datang pejabat negara (T(x), P(x)) + e. Tidak semua penumpang memiliki karcis (P(x), K(x)) + +15. Gambarkan rangkaian listrik untuk pernyataan- + pernyataan berikut: + . ( ∧ ) ∨ + b. ( ∨ ) ∧ + c. ( ∨ ( ∧ )) ∨ (( ∨ ) ∧ ( ∨ )) + + 75 | Logika Matematika + Dasar Matematika | 76 + BAB 4 + + HIMPUNAN + + PENDAHULUAN + Himpunan merupakan objek dasar dari semua objek +yang dipelajari dalam matematika selain fungsi. Pada saat +sesorang belajar matematika, mulai tingkat dasar sampai +tingkat lanjut, selalu berhadapan dengan himpunan. Sebagai +contoh, jika seorang siswa belajar tentang operasi +penjumlahan bilangan bulat maka akan mempelajari tentang +himpunan bilangan bulat dimana semua prosesnya dilakukan +dalam ruang lingkup himpunan bilangan bulat. + George Cantor (1845 – 1918) adalah seorang ahli +Matematika bangsa Jerman yang pertama kali +mengembangkan teori himpunan. Pada permulaannya +konsep mengenai himpunan bertahun-tahun tidak diterima, +tetapi baru tahun 1920 pendapatnya itu dipertimbangkan oleh +para ahli matematika pada waktu itu. + Teori himpunan pertama kali diperkenalkan di sekolah +pada tahun 1960-an setelah era Sputnik. Pada tahun 1970-an +banyak orang merasa bahwa symbol-simbol yang ada pada +teori himpunan ini mengakibatkan kebingungan pada anak- +anak maupun orang dewasa, khususnya bagi mereka yang +baru mengenal symbol-simbol itu. + + 77 | Himpunan + A. PENGERTIAN HIMPUNAN + + Tidak semua konsep dalam matematika dapat +didefinisikan secara tepat. Dalam matematika, himpunan +merupakan pengertian pangkal (tidak didefinisikan, undefined +term). Untuk memahaminya, himpunan sering diartikan +sebagai kumpulan objek-objek (abstrak atau konkret) yang +didefinisikan dengan jelas (well defined), jadi keanggotaannya +harus jelas. Didefinisikan dengan jelas, berarti himpunan +dapat mengklasifikasikan objek kedalam anggota atau bukan +anggota himpunan itu. + + Contoh 4.1: Yang termasuk himpunan: +  Kumpulan hewan-hewan berkaki dua. +  Kumpulan huruf vokal +  Kumpulan nama-nama mahasiswa UNM yang berusia + + di bawah 20 tahun + + Contoh 4.2: Yang bukan merupakan himpunan: +  Kumpulan mobil yang bagus +  Kumpulan lukisan yang indah +  Kumpulan mahasiswi PGSD UNM yang cantik. + +B. NOTASI DAN ANGGOTA HIMPUNAN + + Himpunan biasanya dinyatakan dengan huruf kapital +A, B, C, D, dan seterusnya. Untuk menyatakan suatu himpunan +digunakan simbol “{….}”. Sementara untuk melambangkan +anggota (elemen) himpunan biasanya menggunakan huruf +kecil a, b, c, d, dan seterusnya. Perlu diperhatikan bahwa +penulisan anggota (elemen) dalam suatu himpunan hanya +sekali saja Jadi tidak boleh kita menuliskan himpunan sebagai +{1,a,b,8,a}. Demikian pula kita tidak boleh menyatakan + +Dasar Matematika | 78 + himpunan sebagai {bunga, kambing, sapi, kerbau, sapi, +tumbuhan}. Untuk menyatakan anggota (elemen) suatu + +himpunan digunakan lambang “” (baca: anggota / elemen) + +sedangkan untuk menyatakan bukan anggota suatu + +himpunan digunakan lambang “ ” (baca: bukan anggota + +/elemen). + + Contoh 4.3: +  Himpunan huruf vocal. V ={a, i, u, e, o} +  Himpunan bilangan asli. N = { 1, 2, 3,... } +  Himpunan bilangan bulat. Z = { ..., -2, -1, 0, 1, 2, ... } + +C. CARA MENYATAKAN HIMPUNAN + + Suatu himpunan dapat dinyatakan dengan tiga cara +sebagai berikut: +1. Dengan kata-kata. + + Dengan cara kata-kata artinya menyebutkan semua + syarat/sifat keanggotaannya. + + Contoh 4.4: +  N adalah himpunan bilangan asli yang dimulai dari 5 + + sampai 15 + Dituliskan dengan cara, N = {bilangan asli dari 5 + sampai 15} +  P adalah himpunan bilangan prima antara 10 dan 40, + Ditulikan dengan cara, P = {bilangan prima antara 10 + dan 20}. + +2. Dengan Cara mendaftar anggota-anggotanya + Dengan cara menyebutkan anggota-anggotanya, yaitu + menuliskan semua angotanya dengan menggunakan + kurung kurawal, dan anggota-anggotanya dipisahkan + dengan tanda koma. Pada contoh (1.4) tersebut dapat + + 79 | Himpunan + dituliskan dengan cara mendaftar semua anggota- +anggotannya, dapat kita lihat sebagai berikut + N = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} + P = {11, 13, 17, 19} + +3. Dengan notasi pembentuk himpunan. + Dengan notasi pembentuk himpunan Sama seperti + menyatakan himpunan dengan kata-kata dan cara + mendaftar semua anggota-anggotannya, pada cara ini + disebutkan semua syarat/sifat keanggotannya. Namun, + anggota himpunan dinyatakan dengan suatu peubah. + Peubah yang biasa digunakan adalah x atau y. Adapun + beberapa penulisan dengan cara notasi namun + mempunyai makna yang sama. Kita kembali melihat + contoh (1.4) dan penjelasan penulisan himpunan dengan + cara mendaftar anggota-anggotanya pada bagian 2 akan + ditulikan dengan notasi pembentukan himpunan, dapat + kita lihat sebagai berikut: + +  N = {x | 5  x  15 , x bilangan asli} atau ditulikan + dengan notasi N  {x 5  x  15, x  N}, + + N  {x 4  x  15, x  N} , N  {x 5  x  16, x  N} + + , N  {x 4  x  16, x  N} + +  P = {x | 10  x  20 , x bilangan prima} atau dituliskan + dengan notasi P  {x 5  x  16, x  P} + +Dasar Matematika | 80 + Lab Mini +Kegiatan 1: +Dengan memperhatikan benda-benda yang terdapat di dalam +ruangan maka kalian dapat menentukan beberapa kumpulan +benda. +1. Daftarlah kumpulan benda: + + a. Benda-benda yang ada dalam ruangan + b. Benda-benda yang ada dalam ruangan yang terbuat + + dari kayu + c. Nama-nama teman dalam ruangan yang berkacamata + d. Merek-merek HP temanmu yang paling mahal + e. Nama-nama temanmu yang pandai +2. Dari kumpulan-kumpulan yang kalian daftar, tentukan + yang mana himpunan dan bukan himpunan. Berikan + alasanmu! + +Kegiatan 2: +1. Perhatikan angka-angka dan symbol-simbol yang + + terdapat di kalkulator. Apakah angka-angka dan symbol- + simbol tersebut mewakili suatu himpunan tertentu? + Berikan pendapatmu! +2. Diketahui Himpunan A adalah tujuh bilangan asli + pertama. Nyatakanlah himpunan A dengan cara: + a. Mendaftar semua anggota-angootanya + b. Menggunakan notasi himpunan + c. Mengunakan kata-kata + + 81 | Himpunan + D. MACAM-MACAM HIMPUNAN + +1. Himpunan kosong + Himpunan Kosong adalah himpunan yang tidak + mempunyai anggota atau biasa dikenal dengan + himpunan hampa, yang dinotasikan dengan { } atau  + (dinyatakan himpunan kosong). Secara teoritis, himpunan + kosong adalah himpunan bagian dari setiap himpunan. + +Contoh 4.5: + + A adalah himpunan manusia di bumi yang tingginya + +lebih dari 25 meter. Karena tidak ada manusia di bumi + +yang tingginya lebih dari 25 meter maka A = { } + + N = {x│x adalah bilangan asli kurang dari 1} + + P = { orang Indonesia yang pernah ke bulan }, maka P = + + + +Catatan: Perhatikan bahwa { 0 } tidak sama dengan { } + +atau { 0 } ≠ { }. + +{ 0 } bukan himpunan kosong, sebab mempunyai + +anggota, yaitu 0. + +{ } tidak mempunyai anggota, maka disebut + +himpunan kosong. + +2. Himpunan Semesta + Himpunan semesta adalah himpunan yang memuat + semua anggota himpunan yang dibicarakan. Himpunn + semesta disebut juga semesta pembicara atau himpunan + universal. Lambang himpunan semesta adalah S atau U. + +Dasar Matematika | 82 + Contoh 4.6: + S adalah himpunan huruf latin + + S = {a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z} + V adalah himpunan huruf vokal V = {a,i,u,e,o} + +Untuk memperjelas kedudukan sebuah himpunan dalam +himpunan semesta atau untuk menggambarkan relasi +antar himpunan, kita dapat menggunakan diagram Venn. +Berikut contoh diagram Venn yang mempresentasikan +kedudukan himpunan V (himpunan huruf vokal) dalam +himpunan semesta S (himpunan huruf latin). + +Sc df j + + yk s np + q + rt +vb z + hg x + m + l V + + w ai + + ue o + + Gambar 1 + +3. Himpunan Berhingga dan Himpunan Tak Berhingga + Himpunan dikatakan berhingga jika ia mempunyai + anggota-anggota yang banyaknya berhingga. Sedangkan + himpunan dikatakan tak berhingga jika himpunan + tersebut mempunyai anggota-anggota yang banyaknya + tak berhingga. + + Contoh 4.7: + +  R = {x x  himpunan bilangan-bilangan cacah} + + Berarti anggotanya {0, 1, 3, …..}, jadi R disebut + himpunan tak berhingga + + 83 | Himpunan +  M = {x x  himpunan bilangan-bilangan cacah kurang + + dari 5} + Berarti anggotanya {0, 1, 3, 4}, jadi M disebut + himpunan berhingga + + Perhatikan angka-angka dan symbol-simbol yang + terdapat di kalkulator. Apakah angka-angka dan + symbol-simbol tersebut mewakili suatu himpunan + tertentu? Berikan pendapatmu! + +Aktivitas: +Kegiatan 1: + +Perhatikan angka-angka dan symbol-simbol yang terdapat di +kalkulator. Apakah angka-angka dan symbol-simbol tersebut +mewakili suatu himpunan tertentu? Berikan pendapatmu! +1. Daftarlah 5 himpunan kosong yang dapat dibentuk yang + + berada di sekitarmu +2. Tuliskan himpunan yang kalian daftar menggunakan + + notasi himpunan. + +Kegiatan 2: +Jika diketahui: P = {pensil, buku} + + Q = Himpunan bilangan prima yang kurang dari + 6 + R = { x | 5 < x < 8, x ∈ bilangan cacah} +1. Tentukan masing-masing 2 himpunan semesta yang + mungkin dari himpunan P +2. Tentukan masing-masing 2 himpunan semesta yang + mungkin dari himpunan Q +3. Tentukan masing-masing 2 himpunan semesta yang + mungkin dari himpunan R + +Dasar Matematika | 84 + E. SIFAT-SIFAT OPERASI HIMPUNAN +1. Komutatif + + Diberikan himpunan A dan B. + + Maka berlaku AB = BA dan juga AB = BA + +2. Asosiatif + Diberikan himpunan A, B dan C. + + Maka berlaku (AB)C = A(BC) dan juga + (AB)C= A(BC). + +3. Idempoten + + Diberikan suatu himpunan A. Maka berlaku AA=A + dan juga AA=A + +4. Identitas + Diberikan suatu himpunan A dalam semesta S. + + Maka AS=A dan juga AS=A + +5. Distributif + + Diberikan himpunan A,B dan C. Maka A(BC) = + (AB)(AC) dan juga A(BC)=(AB)(AC) + +6. Komplementer + Diberikan suatu himpunan A dalam semesta S. Maka + + AAc = S dan AAc =  + +7. Dalil De Morgan + Diberikan himpunan A dan B. + + Maka (AB)c = Ac  Bc dan (AB)c = Ac  Bc + + 85 | Himpunan + F. OPERASI HIMPUNAN +1. Irisan (intersection) + +  Notasi : A  B = { x  x  A dan x  B } + Contoh 4.8: + (i) Jika A = {2, 4, 6, 8, 10} dan B = {4, 10, 14, 18}, + + maka A  B = {4, 10} + (ii) Jika A = { 3, 5, 9 } dan B = { -2, 6 }, maka A  B = . + + Artinya: A // B +2. Gabungan (union) + +  Notasi : A  B = { x  x  A atau x  B } + + Contoh 4.9: + (i) Jika A = { 2, 5, 8 } dan B = { 7, 5, 22 }, maka A  B = {2, + + 5, 7, 8, 22 } + (ii) (ii) A   = A + +Dasar Matematika | 86 + 3. Komplemen (complement) + + A  Notasi : = { x  x  U, x  A } + + Contoh 4.10: + Misalkan U = { 1, 2, 3, ..., 9 }, + + A (i) Jika A = {1, 3, 7, 9}, maka = {2, 4, 6, 8} + A (ii) Jika A = { x | x/2  P, x < 9 }, maka = { 1, 3, 5, 7, 9 } + + Contoh 4.11: + Misalkan: + A = himpunan semua mobil buatan dalam negeri + B = himpunan semua mobil impor + C = himpunan semua mobil yang dibuat sebelum + + tahun 1990 + D = himpunan semua mobil yang nilai jualnya + + kurang dari Rp 100 juta + E = himpunan semua mobil milik mahasiswa + + universitas tertentu + (i) “mobil mahasiswa di universitas ini produksi dalam + + negeri atau diimpor dari luar negeri”  (E  A)  (E  + B) atau E  (A  B) + (ii) “semua mobil produksi dalam negeri yang dibuat + sebelum tahun 1990 yang nilai jualnya kurang dari + Rp 100 juta”  A  C  D + + 87 | Himpunan + (iii) “semua mobil impor buatan setelah tahun 1990 + mempunyai nilai jual lebih dari Rp 100 juta”  + + CDB + +4. Selisih (difference) + + B  Notasi : A – B = { x  x  A dan x  B } = A  + + Contoh 4.12: + (i) Jika A = { 1, 2, 3, ..., 10 } dan B = { 2, 4, 6, 8, 10 }, maka + + A – B = { 1, 3, 5, 7, 9 } dan B – A =  + (ii) {1, 3, 5} – {1, 2, 3} = {5}, tetapi {1, 2, 3} – {1, 3, 5} = {2} + +5. Beda Setangkup (Symmetric Difference) +  Notasi: A  B = (A  B) – (A  B) = (A – B)  (B – A) + Contoh 4.13: + Jika A = { 2, 4, 6 } dan B = { 2, 3, 5 }, maka A  B = { 3, 4, 5, + 6} Contoh 4.14: + Misalkan : + U = himpunan mahasiswa + P = himpunan mahasiswa yang nilai ujian UTS di atas 80 + Q = himpunan mahasiswa yang nilain ujian UAS di atas 80\ + Seorang mahasiswa mendapat nilai A jika nilai UTS dan + nilai UAS keduanya di atas 80, mendapat nilai B jika salah + +Dasar Matematika | 88 + satu ujian di atas 80, dan mendapat nilai C jika kedua + ujian di bawah 80. +  “Semua mahasiswa yang mendapat nilai A” : P  Q +  “Semua mahasiswa yang mendapat nilai B” : P  Q +  “Semua mahasiswa yang mendapat nilai C” : U – (P  + + Q) + Teorema. Beda setangkup memenuhi sifat-sifat berikut: + (a) A  B = B  A (hukum komutatif) + (b) (A  B )  C = A  (B  C ) (hukum asosiatif) + +6. Perkalian Kartesian (cartesian product) +  Notasi: A  B = {(a, b)  a  A dan b  B } + Contoh 4.13: + 1) Misalkan C = { 1, 2, 3 }, dan D = { a, b }, maka C  D = { + (1, a), (1, b), (2, a), (2, b), (3, a), (3, b) } + 2) Misalkan A = B = himpunan semua bilangan riil, maka + A  B = himpunan semua titik di bidang datar + Catatan: + 1) Jika A dan B merupakan himpunan berhingga, maka: + AB=A . B. + 2) Pasangan berurutan (a, b) berbeda dengan (b, a), + dengan kata lain (a, b)  (b, a). + 3) Perkalian kartesian tidak komutatif, yaitu A  B  B  A + dengan syarat A atau B tidak kosong. + Pada Contoh 20(i) di atas, D  C = {(a, 1), (a, 2), (a, 3), + (b, 1), (b, 2), (b, 3) }  C  D. + 4) Jika A =  atau B = , maka A  B = B  A =  + + 89 | Himpunan + Contoh 4.14: + Misalkan: + A = himpunan makanan = { s = soto, g = gado-gado, n = + + nasi goreng, m = mie rebus } + B = himpunan minuman = { c = coca-cola, t = teh, d = es + + dawet } + Berapa banyak kombinasi makanan dan minuman yang + dapat disusun dari kedua himpunan di atas? + Jawab: + A  B = AB = 4  3 = 12 kombinasi dan minuman, + yaitu {(s, c), (s, t), (s, d), (g, c), (g, t), (g, d), (n, c), (n, t), (n, d), + (m, c), (m, t), (m, d)}. + Contoh 4.15: + Daftarkan semua anggota himpunan berikut: + (a) P() (b)   P() c) {} P() (d) P(P({3})) + Jawab: + (a) P() = {} + (b)   P() =  (ket: jika A =  atau B =  maka A  B = + + ) + (c) {} P() = {} {} = {(,)) + (d) P(P({3})) = P({ , {3} }) = {, {}, {{3}}, {, {3}} } + +Dasar Matematika | 90 + G. DIAGRAM VENN + +Contoh 4.16: +Misalkan U = {1, 2, …, 7, 8}, A = {1, 2, 3, 5} dan B = {2, 5, 6, +8}. +Diagram Venn: + +U AB 7 + + 12 8 + + 3 5 6 4 + +H. KARDINALITAS + + Kardinalitas Himpunan adalah bilangan yang +menyatakan banyaknya anggota dari suatu himpunan dan +dinotasikan dengan n(A)". + +  Jumlah elemen di dalam A disebut kardinal dari + himpunan A. + +  Notasi: n(A) atau A  + + Contoh 4.17: + 1. B = { x | x merupakan bilangan prima yang lebih kecil + + dari 20 }, atau B = {2, 3, 5, 7, 11, 13, 17, 19} maka B + =8 + 2. T = {kucing, a, Amir, 10, paku}, maka T = 5 + 3. A = {a, {a}, {{a}} }, maka A = 3 + + 91 | Himpunan + I. HUBUNGAN ANTAR HIMPUNAN +1. Himpunan Bagian (Subset) + + a) Himpunan A dikatakan himpunan bagian dari + himpunan B jika dan hanya jika setiap elemen A + merupakan elemen dari B. + + b) Dalam hal ini, B dikatakan superset dari A. + c) Notasi: A  B + d) Diagram Venn: + + U + + B + A + + Contoh 4.18: + 1. { 1, 2, 3}  {1, 2, 3, 4, 5} + 2. {1, 2, 3}  {1, 2, 3} + 3. N  Z  R  C + 4. Jika A = { (x, y) | x + y < 4, x , y  0 } dan B = { (x, y) | + + 2x + y < 4, x  0 dan y  0 }, maka B  A. + Teorema. Untuk sembarang himpunan A berlaku hal-hal + sebagai berikut: + (a) A adalah himpunan bagian dari A itu sendiri (yaitu, A  + + A). + (b) Himpunan kosong merupakan himpunan bagian dari + + A (   A). + (c) Jika A  B dan B  C, maka A  C + (e)   A dan A  A, maka  dan A disebut himpunan + bagian tak sebenarnya (improper subset) dari himpunan A. + +Dasar Matematika | 92 + Contoh 4.19: + A = {1, 2, 3}, maka {1, 2, 3} dan  adalah improper subset + dari A. + e) A  B berbeda dengan A  B + (i) A  B : A adalah himpunan bagian dari B tetapi A  B. + A adalah himpunan bagian sebenarnya (proper subset) + dari B. + + Contoh 4.20: + {1} dan {2, 3} adalah proper subset dari {1, 2, 3} + (ii) A  B : digunakan untuk menyatakan bahwa A adalah + + himpunan bagian (subset) dari B yang memungkinkan + A = B. + +2. Himpunan yang Sama +  A = B jika dan hanya jika setiap elemen A merupakan + elemen B dan sebaliknya setiap elemen B merupakan + elemen A. +  A = B jika A adalah himpunan bagian dari B dan B + adalah himpunan bagian dari A. Jika tidak demikian, + maka A  B. +  Notasi : A = B  A  B dan B  A + + Contoh 4.21: + (i) Jika A = { 0, 1 } dan B = { x | x (x – 1) = 0 }, maka A = B + (ii) Jika A = { 3, 5, 8, 5 } dan B = {5, 3, 8 }, maka A = B + (iii) Jika A = { 3, 5, 8, 5 } dan B = {3, 8}, maka A  B + + Untuk tiga buah himpunan, A, B, dan C berlaku aksioma + berikut: + (a) A = A, B = B, dan C = C + (b) jika A = B, maka B = A + (c) jika A = B dan B = C, maka A = C + + 93 | Himpunan + 3. Himpunan yang Ekivalen +  Himpunan A dikatakan ekivalen dengan himpunan B + jika dan hanya jika kardinal dari kedua himpunan + tersebut sama. +  Notasi : A ~ B  A = B + + Contoh 4.22: + Misalkan A = { 1, 3, 5, 7 } dan B = { a, b, c, d }, maka A ~ B + sebab A = B = 4 + +4. Himpunan Saling Lepas + Dua himpunan A dan B dikatakan saling lepas (disjoint) + jika keduanya tidak memiliki elemen yang sama. +  Notasi : A // B +  Diagram Venn: + + U + +A B + + Contoh 4.23: + Jika A = { x | x  P, x < 8 } dan B = { 10, 20, 30, ... }, maka A + // B. + +5. Himpunan Kuasa +  Himpunan kuasa (power set) dari himpunan A adalah + suatu himpunan yang elemennya merupakan semua + himpunan bagian dari A, termasuk himpunan kosong + dan himpunan A sendiri. +  Notasi : P(A) atau 2A +  Jika A = m, maka P(A) = 2m. + +Dasar Matematika | 94 + Contoh 4.24: +Jika A = { 1, 2 }, maka P(A) = { , { 1 }, { 2 }, { 1, 2 }} + +Contoh 4.25: +Himpunan kuasa dari himpunan kosong adalah P() = +{}, dan himpunan kuasa dari himpunan {} adalah +P({}) = {, {}}. + +J. KONSEP HIMPUNAN DALAM PEMECAHAN MASALAH + + Jika kalian amati masalah dalam kehidupan sehari-hari +maka banyak di antaranya dapat diselesaikan dengan konsep +himpunan. Agar dapat menyelesaikannya, kalian harus +memahami kembali mengenai konsep diagram Venn. Kalian +harus dapat menyatakan permasalahan tersebut dalam suatu +diagram Venn. Perhatikan contoh berikut: + +Contoh 4.26: +Perhatikan diagram Venn dibawah ini! + +S K T + + 6 29 + +8 + +S = himpunan siswa kelas VII A +K = himpunan siswa yang suka minum es teh +T = himpunan siswa yang suka minum jus +Setiap angka menunjukkan banyaknya siswa dalam +masing-masing kesukaannya. + + 95 | Himpunan + Tentukanlah: + a. Berapa banyak siswa yang suka minum keduanya? + b. Berapa banyak siswa yang suka minum es teh? + c. Berapa banyak siswa yang tidak suka minum + + keduanya? + d. Berapa banyak siswa kelas VII A tersebut? + + Jawab: + + a. n(K  T) = 2 + + b. n(K) = 6 + + c. n(K  T)c = 8 + d. n(S) = n(K – T) + n(T – K) + n(K  T) + n(K  T)c = 4 + 7 + 2 + + + 8 = 21 + + Contoh 4.27: + Dalam suatu kelas yang terdiri atas 40 siswa, diketahui 24 + siswa gemar bermain tenis, 23 siswa gemar sepak bola, + dan 11 siswa gemar keduaduanya. Gambarlah diagram + Venn dari keterangan tersebut, kemudian tentukan + banyaknya siswa: + a. yang hanya gemar bermain tenis; + b. yang hanya gemar bermain sepak bola; + c. yang tidak gemar kedua-duanya. + + Jawab: + Dalam menentukan banyaknya anggota masing-masing + himpunan pada diagram Venn, tentukan terlebih dahulu + banyaknya anggota yang gemar bermain tenis dan sepak + bola, yaitu 11 siswa. Diagram Venn-nya seperti gambar + berikut + +Dasar Matematika | 96 + a. Banyak siswa yang hanya gemar tenis = 24 – 11 = 13 + siswa + +b. Banyak siswa yang hanya gemar sepak bola = 23 – 11 + = 12 siswa + +c. Banyak siswa yang tidak gemar kedua-duanya = 40– + 13–11–12 = 4 siswa + + 97 | Himpunan + K. RANGKUMAN +1. Himpunan sering diartikan sebagai kumpulan objek + + (abstrak atau konkret) yang didefinisikan dengan jelas + (well defined), jadi keaggotaannya harus jelas. +2. Cara menyatakan himpunan dengan tiga cara yaitu: + dengan kata-kata, dengan mendaftrakan anggota- + anggotanya dan dengan notasi himpunan. +3. Macam-macam himpunan: + a. Himpunan kosong + b. Himpunan semesta + c. Himpunan berhingga dan tak berhingga +4. Operasi himpunan terdiri dari: + a. Irisan + b. Gabungan + c. Komplemen + d. Selisih + e. Beda setangkup + f. Perkalian cartesius +5. Hubungan antar himpunan terdiri dari: + a. Himpunan bagian + b. Himpunan yang sama + c. Himpunan ekivalen + d. Himpunan saling lepas + +Dasar Matematika | 98 + L. LATIHAN + +1. Tuliskan dengan menggunakan notasi himpunan + +a. x bukan elemen A c. A memuat B + +b. A dimuat oleh B d. A tidak memuat B + +2. Nyatakan dalam bentuk daftar himpunan berikut: + + a. A  x x2  4 c. B  x x  4  5 + +b. B  x x positif , x, negatif  + +3. Nyatakan pernyataan berikut dengan 3 cara dalam + menyatakan himpunan, lalu tentukan banyaknya masing- + masing himpunan tersebut: + a. himpunan bilangan prima yang kurang dari 20 + b. himpunan bilangan ganjil antara 10 sampai 30 + +4. Selidikilah apakah himpunan berikut kosong atau bukan! + a. himpunan bilangan prima genap + b. himpunan bilangan genap yang habis dibagi 7 + c. himpunan nama bilangan yang lamanya 32 hari tiap + bulan + + d. A = { x x  2  6, x bilangan asli} + +5. Diberikan A = {1, 2, 3, 4}, B ={2, 4, 6, 8}, dan C ={3, 4, 5, 7}. + +Tentukanlah: + +a. A  B c. B  C e. A  (B  C) + +b. A  C d.(A  B)  C + +6. Jika M  {x x  10, x bilangan bulat positif } + N  {y y  10, y bilangan bulat positif } + + 99 | Himpunan + Maka tentukanlah kardinalitas himpunan M dan N serta + apa perbedaan kardinalitas himpunan M dan himpunan + N + +7. Dari 53 bayi di PUSKESMAS, 30 bayi minum susu kaleng, + 13 bayi minum susu ASI, dan 10 bayi minum keduanya. + Berapa jumlah bayi yang hanya minum ASI? + +8. Dari 46 siswa yang gemar bahasa inggris ada 26 siswa, + gemar bahasa arab ada 32 siswa dan 14 siswa gemar + keduanya. Tentukan banyaknya siswa yang tidak gemar + keduanya! + +9. Dari sekelompok siswa yang suka tennis meja ada 26 + siswa, yang gemar bulu tangkis ada 27 siswa, yang gemar + keduanya ada 9 siswa dan yang tidak gemar keduanya + ada 4 siswa. Tentukan banyaknya siswa dalam kelompok + tersebut! + +10. Dari 500 yang ikut ujian masuk perguruan tinggi, ternyata + 329 mengikuti ujian matematika, 186 mengikuti ujian + fisika, 83 mengikuti ujian matematika dan fisika. Tentukan + jumlah siswa yang tidak mengikuti ujian matematika + maupun fisika ! + +11. Suatu himpunan bilangan asli terdiri atas 10 bilangan + yang hasbis dibagi 6, 15 bilangan yang habis dibagi 2, 10 + bilangan yang habis dibagi 3 dan satu bilangan yang tidak + habis dibagi 2 ataupun 3. Tentukan banyaknya unsur + bilangan tersebut! + +12. Jika hasil penelitian yang dilakukan terhadap 250 orang + penduduk suatu desa menyatakan bahwa. Ada 60 orang + +Dasar Matematika | 100 + pemilik sawah dan 110 orang penggarap sawah. +Disamping itu ada pula 100 orang yang bukan pemilik +maupun penggarap sawah. Maka tentukan banyaknya +orang sebagai pemilik dan penggarap sawah ! + +13. Perhatikan himpunan A, B, dan C dalam diagram Venn + berikut! + +S A C + + 7 9-x 8 + + x + 8-x 7-x + + 9 + + B + +Diberikan S = A  B  C, dan n(S) = 34, hitunglah: + +a. nilai x + +b. n(A  B  C) + + 101 | Himpunan + Dasar Matematika | 102 + BAB 5 + + RELASI DAN FUNGSI + + PENDAHULUAN + + Dalam kehidupan sehari-hari, anda tentunya sering +mendengar kata “relasi”. Relasi memiliki arti hubungan. +Misalkan teman kantor, sering kita sebut relasi atau rekan +kerja. Relasi “bersaudara dengan” (Dian bersaudara dengan +Dani, Vita bersaudara dengan Vino, dan sebagainya). Relasi +“teman” (Fahrul dengan Taufik, Wirda dengan Asmi, Jumriati +dengan Wiana, dan sebagainya). Contoh lain relasi “gemar” +(Asri gemar sepak bola, Hendra gemar Bola Volly, dan +sebagainya). Dalam matematika, relasi diartikan sebagai +hubungan antara dua himpunan. + + Telah diuraikan pada unit 3, bahwa himpunan +merupakan objek dasar dari semua objek yang dipelajari +dalam matematika. Fungsi juga merupakan objek dasar dalam +pembelajaran matematika. Apa perlunya kita mempelajari +fungsi? Fungsi memiliki banyak aplikasi dalam kehidupan +sehari-hari. Di bidang ekonomi, misalnya, mengekspresikan +kajiannya tentang analisis permintaan dan penawaran suatu +produk. Melalui grafik fungsi dapat dilihat perkembangan +fluktuasi permintaan dan penawaran dari waktu ke waktu. Di +bidang kedokteran, kondisi kesehatan jantung seseorang +dapat dipantau melalui grafik fungsi jumlah detak jantung +terhadap satuan waktu. Bidang lain yang banyak + + 103 | Relasi dan Fungsi + memanfaatkan fungsi adalah teknologi informasi dalam +mengenskripsi data. Hal ini menunjukkan funsi diperlukan +untuk melakukan deskripsi dan analisis dalam sebuah bidang +kajian. + + Sebelum masuk pada bahasan fungsi, maka terlebih +dahulu harus dipahami konsep-konsep yang mendasari +pembentukan konsep fungsi yakni perkalian himpunan dan +relasi. Jadi, fungsi merupakan bentuk khusus dari relasi. +Aktivitas +Kegiatan 1: +Gambar berikut merupakan hubungan antara kelompok siswa +dengan kelompok band favoritnya: + +Dari gambar tersebut, tanpa ada penjelasan yang lebih +terperinci apa kalian temukan? Diskusikan! +Kegiatan 2: +Dalam rangka memperingati HUT RI ke-71 di Kota Makassar, +SMA Negeri 9 Makassar akan mengirimkan siswanya untuk +mengikut pertandingan antar SMA untuk pertandingan tenis +lapangan, sepakbola, bola volley, bulu tangkis, tenis meja, dan + +104 | Matematika Dasar + catur. Terdapat 6 orang siswa (Ansar, Amri, Jaya, Arman, +Harun, dan Fahrul) yang akan mengikuti pertandingan +tersebut. Pasangkanlah siswa dengan pertandingan yang akan +diikuti dengan ketentuan berikut: +1. Ansar ikut pertandingan tenis meja dan bola volley, Amri + + ikut pertandingan badminton, Jaya ikut pertandingan + catur, Arman ikut pertandingan bola volley, Harun ikut + pertandingan tenis meja dan Fahrul ikut pertandingan + tenis meja. +2. Arman ikut pertandingan bola volley, Jaya ikut + pertandingan catur, Amri ikut pertandingan badminton, + Harun dan Fahrul ikut pertandingan bola volley. +3. Keenam siswa ikut pertandingan sepakbola +4. Tono akan mengikuti seluruh pertandingan + +A. PRODUCT CARTESIUS + + Product Cartesius dari himpunan A dan B adalah +himpunan yang elemennya semua pasangan berurutan +(ordered pairs) yang terbentuk dari komponen pertama +himpunan A dan komponen kedua himpunan B. Penulisan: A +x B = { (a, b) l a  A dan b  B } + + Contoh 5.1: + 1. Tentukan Product Cartesius dari himpunan A = {1, 2, + + 3}, dan B = {a, b} + Jawab : + Product Cartesius dari himpunan A dan B : + A x B = {(1, a), (1, b), (2, a), (2, b), (3, a), (3, b)} + + 2. Dua buah uang logam Rp. 500,- dilempar bersama- + sama, tentukan kemungkinan angka dan gambar + yang akan muncul pada kedua uang logam tersebut . + + 105 | Relasi dan Fungsi + Jawab : pada + misalkan : + a = logam pertulisan angka Rp. 500,- + g = logam yang bergambar garuda + A = {a, g} + B = {a, g} + angka dan gambar yang muncul + +pelemparan kedua uang logam : +A x B = {(a, a), (a, g), (g, a), (g, g)} + +3. Dua buah dadu dilempar bersama-sama, tentukan + kemungkinan angka-angka yang akan muncul pada + kedua dadu tersebut . + Jawab : + Kedua dadu masing-masing mempunyai angka 1, 2, 3, + 4, 5, dan 6 + A = {1, 2, 3, 4, 5, 6} + B = {1, 2, 3, 4, 5, 6} + angka-angka yang akan muncul pada kedua dadu + A x B = {(1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), + (2, 1), (2, 2), (2, 3), (2, 4), (2, 5), (2, 6), + (3, 1), (3, 2), (3, 3), (3, 4), (3, 5), (3, 6), + (4, 1), (4, 2), (4, 3), (4, 4), (4, 5), (4, 6), + (5, 1), (5, 2), (5, 3), (5, 4), (5, 5), (5, 6), + (6, 1), (6, 2), (6, 3), (6, 4), (6, 5), (6, 6)} + +4. Sebuah uang logam dan sebuah dadu dilempar + bersamaan, tentukan kemungkinan angka atau + gambar pada uang logam dan angka pada dadu + tersebut. + Jawab : + Uang logam mempunyai dua sisi yaitu angka Rp. 500,- + (a) dan gambar garuda (g) + +106 | Matematika Dasar + A = {a, g} + Dadu mempunyai enam angka yaitu 1, 2, 3, 4, 5 dan 6 + B = {1, 2, 3, 4, 5, 6} + Angka atau gambar pada uang logam dan angka pada + dadu yang mungkin terjadi : + A x B = {(a, 1), (a, 2), (a, 3), (a, 4), (a, 5), (a, 6), + (g, 1), (g, 2), (g, 3), (g, 4), (g, 5), (g, 6)} + + 5. Dari kota A ke kota B ada 3 jalan yang berbeda, dari + kota B ke kota C ada 4 jalan yang berbeda. Tentukan + semua jalan yang dapat dilalui dari kota A ke kota C. + Jawab : + Dari kota A ke kota B ada 3 jalan yang berbeda + misalnya p1, p2, p3 + P = {p1, p2, p3} + Dari kota B ke kota C ada 4 jalan yang berbeda + misalnya q1, q2, q3, q4 + Q = {q1, q2, q3, q4} + Semua jalan yang dapat dilalui dari kota A ke + kota C : + P x Q = {(p1, q1), (p1, q2), (p1, q3), (p1, q4), + (p2, q1), (p2, q2), (p2, q3), (p2, q4), + (p3, q1), (p3, q2), (p3, q3), (p3, q4)} + +B. RELASI PADA HIMPUNAN + Jika P x Q adalah Product Cartesius himpunan P dan + +Q, maka relasi R dari himpunan P ke Q adalah sembarang +himpunan bagian dari Product Cartesius P x Q. + +Pada relasi R = {(x, y) I x  P  y  Q}, maka: + +  Himpunan P disebut domain. +  Himpunan Q disebut kodomain. + + 107 | Relasi dan Fungsi +  Himpunan bagian dari Q yang bersifat x R y disebut + range. + + Contoh 5.2: + 1. Relasi himpunan P = {1, 2, 3} dan Q = {p, q} + + ditentukan relasi oleh R1 , R2, R3 berikut ini : + a) R1 = {(1, p), (1, q), (2, p), (2, q), (3, p)} + b) R2 = {(1, p), (1, q), (2, p), (2, q)} + c) R3 = {(1, p), (2, p), (3, p)} + Gambarkan relasi himpunan R1, R2 dan R3 serta + tentukan domain, kodomain, dan range + Jawab: + +C. SIFAT-SIFAT RELASI + a. Refleksif + Relasi R pada himpunan A disebut refleksif jika (x, x)  R + untuk setiap x  A. + Contoh 5.3: + Himpunan A = {1, 2, 3, 4, 5}, dan relasi R didefinisikan + pada himpunan A. manakah yang bersifat reflektif pada + relasi berikut ini: + 1) R = {(1, 1), (1, 3), (1, 5), (2, 1), (2, 2), (3, 3), (4, 2), (4, 3), (4, + 4), (5, 5)} + +108 | Matematika Dasar + 2) R = {(1, 1), (1, 5), (2, 2), (2, 3), (3, 3), (4, 3), (5, 2), (5, 5)} + Jawab : + 1) Relasi R bersifat refleksif karena terdapat unsur relasi + + (x, x)  R, + yaitu (1, 1), (2, 2), (3, 3), (4, 4) dan (5, 5) + 2) Relasi R tidak bersifat refleksif karena (4, 4)  R. + +b. Simetris + Relasi R pada himpunan A disebut simetris jika untuk + semua x, y  A, jika (x, y)  R, maka (y, x)  R. Relasi R + disebut tak simetris (anti simetris) jika x, y  A, jika (x, y) +  R dan x  y , maka (y, x)  R. + + Contoh 5.4: + Himpunan A {1, 2, 3, 4, 5} dan relasi R didefinisikan pada + himpunan A. + Manakah relasi yang bersifat simetris pada relasi berikut + ini : + 1) R = {(1, 1), (1, 2), (2, 1), (2, 2), (2, 4), (3, 5), (4, 2), (4. 4), + + (5, 3) (5, 5)} + 2) R = {(1, 1), (2, 3), (2, 4), (3, 5), (4, 2), (5, 3), (5, 5)} + Jawab: + 1) Relasi R bersifat simetris karena (x, y)  R dan (y, x)  + + R, yaitu : + (1, 2)  R dan (2, 1)  R + (2, 4)  R dan (4, 2)  R + (3, 5)  R dan (5, 3)  R + 2) Relasi R bersifat tidak simetris karena (3, 2)  R + + 109 | Relasi dan Fungsi + c. Transitif + Relasi R pada himpunan A disebut transitif + (menghantar), jika (x, y)  R dan (y, z)  R, maka (x, z)  + R, untuk x, y, z  A. + + Contoh 5.5: + Manakah relasi yang bersifat transitif pada relasi berikut + ini : + 1) Diketahui A = { 1, 2, 3 }. + + Pada A didefinisikan relasi R = { (1,1) , (1,2) , (2,2) , + (2,1) , (3,3) } Relasi R tersebut bersifat transitif. + 2) Relasi R = { (1,1) , (1,2) , (2,2) , (2,3) , (3,3) , (3,2) } yang + didefinisikan pada himpunan A = {1, 2, 3 } tidak + bersifat transitif, karena terdapat (1,2)  R dan (2,3) +  R, tetapi (1,3)  R . + +d. Antisimetris jika untuk + Relasi R dikatakan bersifat antisimetris + setiap (x,y)  R dan (y,x)  R berlaku x = y. + +Contoh 5.6: +Manakah relasi yang bersifat antisimetris pada relasi +berikut ini : +1) Pada himpunan B = { 2, 4, 5 } didefinisikan relasi R = + + { (x,y)  x kelipatan y , x,y  B }. Dengan demikian R = + {(2,2),(4,4),(5,5),(4,2)}. Relasi R tersebut bersifat + antisimetris. +2) Diketahui A = { 1, 2, 3 }. + Pada A didefinisikan relasi R = { (1,1) , (1,2) , (2,2) , + (2,1) , (3,3) } + Relasi R tersebut tidak bersifat antisimetris karena + terdapat (1,2)R dan (2,1)  R5, tetapi 1  2. + +110 | Matematika Dasar + e. Relasi Ekivalen + Relasi R disebut sebagai sebuah relasi ekivalen jika + relasi tersebut bersifat refleksif, simetris dan transitif. + + Contoh 5.7: + 1) Diketahui A = { 1, 2, 3 }. + + Pada A didefinisikan relasi R = { (1,1) , (1,2) , (2,2) , (2,1) + , (3,3) } + Relasi R tersebut bersifat refleksif, simetris dan + transitif. Oleh karena itu relasi R merupakan relasi + ekivalen. + 2) Diketahui B = { 2, 4, 5 }. + Pada B didefinisikan relasi R = { (x,y)  x kelipatan y , + x,y  B }. + R = { (2,2) , (4,4) , (5,5) , (4,2) } + Relasi R tersebut tidak bersifat simetris, oleh karena itu + relasi tersebut bukan relasi ekivalen. + +f. Relasi Pengurutan Sebagian + Relasi R disebut sebagai sebuah relasi pengurutan + sebagian (partial ordering), jika relasi tersebut bersifat + refleksif, transitif dan antisimetris. + + Contoh 5.8: + 1) Diketahui A = { 1, 2, 3 }. + + Pada A didefinisikan relasi R = { (1,1) , (1,2) , (2,2) , (2,1) + , (3,3) } + Relasi R tersebut bersifat refleksif dan transitif, tetapi + tidak bersifat antisimetris. Oleh karena itu relasi + tersebut bukan merupakan relasi pengurutan + sebagian. + 2) Diketahui B = { 2, 4, 5 }. + + 111 | Relasi dan Fungsi + Pada B didefinisikan relasi R = { (x,y)  x kelipatan y , x,y +  B }. + R = { (2,2) , (4,4) , (5,5) , (4,2) } + Relasi R tersebut bersifat refleksif, antisimetris dan + transitif. Oleh karena itu relasi tersebut merupakan relasi + pengurutan sebagian. + +Aktivitas. +Kegiatan 1: + +Lima orang siswa yaitu: Wirda, Asmi, Irma, Selvi, dan Ria +merupakan sahabat yang selalu bersama-sama dalam setiap +kegiatan sekolah. Bapak Amri adalah guru matematika yang +senang persahabatan yang mereka bina karena mereka selalu +memiliki nilai paling bagus. Suatu hari bapak Amri ingin +mengetahui data-data tentang mereka. Hal ini diperlukan +sebagai bahan motivasi untuk teman-teman mereka. Data- +data yang diinginkan berupa: berapa jam rata-rata waktu +belajar mereka dalam satu hari. +1. Jika kelima sahabat itu dibuat dalam satu himpunan + + misalnya himpunan A dan lama waktu belajar dalam satu + hari adalah anggota himpunan B = {1, 2, 3, 4, 5, 6, 7, 8}. + a. Nyatakanlah sebuah relasi yang mungkin menurut + + anda yang menggambarkan lama waktu belajar lima + sahabat itu + b. Apakah semua anggota himpunan A pasti memiliki + pasangan dengan anggota himpunan B? berikan + penjelasanmu. + c. Apakah ada dua kemungkinan bahwa anggota + himpunan A berpasangan dengan 2 atau lebih + anggota himpunan B? berikan penjelasanmu. + +112 | Matematika Dasar + d. Apakah ada dua kemungkinan bahwa anggota + himpunan A memiliki pasangan yang sama dengan + salah satu anggota himpunan B? berikan + penjelasanmu! + +2. Jika kelima sahabat itu dibuat dalam satu himpunan + misalnya himpunan C dan data tentang banyaknya + saudara mereka ada dianggota himpunan D yang + anggoyanya D = {1, 2, 3, 4}. + a. Nyatakanlah sebuah relasi yang mungkin menurut + anda yang menggambarkan banyak saudara kelima + sahabat itu. + b. Untuk semua relasi yang mungkin, apakah semua + anggota himpunan C memiliki pasangan dengan + anggota himpunan D? berikan penjelasanmu. + c. Apakah ada kemungkinan bahwa anggota himpunan + C berpasangan dengan 2 atau lebih anggota + himpunan D? berikan penjelasanmu. + d. Apakah ada kemungkianan bahwa anggota + himpunan C memiliki pasangan yang sama dengan + salah satu anggota himpunan D? berikan + penjelasanmu! + +Kegiatan 2: +Perhatikanlah relasi-relasi yang ditunjukan pada gambar +berikut: + + 113 | Relasi dan Fungsi + v + +Dari gambar tersebut uraiakan fakta-fakta apa saja yang kalian +peroleh? Apakah semuanya termasuk fungsi? Yang mana saja +merupakan fungsi? Berikan penjelasanmu? +D. Hubungan Relasi dengan Fungsi + + Relasi dari himpunan P ke himpunan Q disebut fungsi +atau pemetaan, jika dan hanya jika tiap unsur pada himpunan +P berpasangan tepat hanya dengan sebuah unsur pada +himpunan Q. + + Jika x  P dan y  Q sehingga pasangan-terurut (x, y)  + +f, maka y disebut peta atau bayangan dari x oleh fungsi f. +Adapun bagian-bagian dari fungsi adalah Domain, Kodomain, +dan Range. + + 1) Domain (daerah asal) fungsi f adalah himpunan P (Df) + 2) Kodomain (daerah kawan) fungsi f adalah himpunan Q + + (Kf) + +114 | Matematika Dasar + 3) Range (daerah hasil) fungsi f adalah himpunan semua + peta P di Q (Rf) + +Contoh 5.9: + +1. Diketahui f : A  R dan f dinyatakan oleh f (x) = x + 2 + Jika daerah asal A ditetapkan A = {xI 1  x  5, x R}, + + a. Carilah f(1), f(2), f(3), f(4) dan f(5) + b. Gambarkan grafik fungsi y = f(x) = x + 1 dalam + + bidang Cartesius + c. Carilah daerah hasil dari fungsi f + Jawab : + a) f(x) = x + 2 + + f(1) = 1 + 2 = 3 + f(2) = 2 + 2 = 4 + f(3) = 3 + 2 = 5 + f(4) = 4 + 2 = 6 + f(5) = 5 + 2 = 7 + b) Grafik fungsi y = f(x) = x + 2 + + c) Daerah hasil + + Rf = {y I 3  y  7, y  R} + + 115 | Relasi dan Fungsi + 2. Tentukan daerah asal alami (natural domain) dari tiap + +fungsi berikut ini : + + 4 +a) f(x) = + + x 1 + +b) F(x) = 9  x2 + +c) G(x) = 5 + + x2  5x  6 + +Jawab : + +a) f(x) = 4 ; supaya f(x) bernilai real maka x – 1  + x 1 + + 0 atau x  1 + Jadi, Df = {x I x  R dan x  1} + +b) F(x) = 9  x 2 ; supaya F(x) bernilai real maka + 9 – x2  0 + x2 – 9  0 + (x + 3)(x – 3)  0 – 3  x  3 + Jadi, DF = {x I – 3  x  3; x  R} + +c) G(x) = 5 ; supaya G(x) bernilai real + + x2  5x  6 + +maka + +X2 – 5x + 6 > 0 + +(x – 2)(x – 3) > 0 + +x < 2 atau x > 3 + +Jadi, DG = {xI x < 2 atau x > 3; x  R} + +E. MACAM-MACAM FUNGSI + + Ada beberapa fungsi yang mempunyai ciri spesifik di +antaranya: fungsi konstan, fungsi identitas, fungsi genap, +fungsi ganjil, fungsi modulus, dan fungsi tangga. + +116 | Matematika Dasar + 1) Fungsi Konstan + Untuk semua unsur dalam himpunan A berkaitan + hanya dengan sebuah unsur dalam himpunan B. + + Fungsi konstan ditulis f : x  k, k = konstanta, x  R. + + Grafik fungsi konstan merupakan garis yang sejajar + dengan sumbu X . + +Contoh 4.10: +Buat diagram panah dan grafik pada bidang Cartesius +untuk fungsi y = 5. +( 2  x  2 dan x  bilangan bulat) + +Jawab : Grafik pada bidang Cartesius +Diagram panah + + X Y Y + + 5 y=5 + +-2 + +-1 + 5 + +0 + +1 X + +2 -2 -1 0 1 2 + +2) Fungsi Identitas + Semua unsur dalam himpunan A berkaitan dengan + + dirinya sendiri. Grafik fungsi identitas y = x untuk x  + + R + +Contoh 5.11: +Buat diagram panah dan grafik pada bidang Cartesius +untuk fungsi y = 5, (x  3 dan x  bilangan cacah) + + 117 | Relasi dan Fungsi + Jawab : Grafik pada bidang Cartesius +Diagram panah Y + y=x +A B + +0 0 + +1 1 3 + +2 2 2 + + 1 + +3 3 X + + 0 123 + + 3) Fungsi Genap dan Fungsi Ganjil + + Fungsi f : x  y = f(x) disebut fungsi genap jika f(- x) = + + + f(x) + Grafik fungsi genap selalu simetri terhadap sumbu Y + + Fungsi f : x  y = f(x) disebut fungsi ganjil jika f(- x) = - + + f(x) + + Grafik fungsi ganjil selalu simetri terhadap titik asal O + Jika suatu fungsi y = f(x) tidak memenuhi keduanya + maka disebut fungsi tak genap dan tak ganjil + + Contoh 5.12: + Manakah yang merupakan fungsi genap atau fungsi ganjil + ? + a) f(x) = x2 + b) f(x) = x3 + c) f(x) = x3 + 1 + + Jawab : + a) f(x) = x2 + + f(– x) = (– x)2 + = x2 + +118 | Matematika Dasar + f(– x) = + f(x) + f(x) = x2 fungsi genap + +b) f(x) = x3 + f(– x) = (– x)3 + = – x3 + – f(x) = – x3 + f(– x) = – f(x) + f(x) = x3 fungsi ganjil + c) f(x) = x3 + 1 + f(– x) = (– x)3 + 1 + = – x3 + 1 + – f(x) = – (x3 + 1) + = – x3 – 1 + + f(– x)  + f(x) dan f(– x)  – f(x) + + maka f(x) = x3 – 1 bukan fungsi genap dan bukan fungsi + ganjil. + +4) Fungsi Modulus + Modulus atau nilai mutlak dari sebuah bilangan real x + +x, jika x > 0 + | x | = 0, jika x = 0 + -x , jika x < 0 + + 119 | Relasi dan Fungsi + Contoh 5.13: + +Diketahui fungsi f:x  I x I dengan x  R + +Carilah f(– 3) , f(– 2), f(–1), f(0), f(1), f(2) dan f(3) + +Jawab : +f(x) = I x I +f(– 3) = l – 3 l = 3 +f(– 2) = I – 2 I = 2 +f(–1) = I –1 I = 1 +f(0) = I 0 I = 0 +f(1) = I 1 I = 1 +f(2) = I 2 I = 2 +f(3) = l 3 l = 3 + +5) Fungsi Tangga + Fungsi Tangga atau Fungsi Nilai Bulat Terbesar dalam + perhitungan matematika sering dilakukan pembulatan + +Contoh 5.14: + +0,2; 0,3; 0,78 dan seterusnya untuk semua x  R dan 0  + +x < 1 dibulatkan ke bawah menjadi 0 + +1,1; 1,2; 1,57 dan seterusnya yang kurang x  R dan 1  x + +< 2 dibulatkan ke bawah menjadi 1. + +Suatu nilai bulat terbesar yang kurang dari x + +dilambangkan dengan [[ x ]]. + +– 2  x < –1  [[ x ]] = – 2 + +–1  x < 0  [[ x ]] = –1 +0  x<1  [[ x ]] = 0 +1  x<2  [[ x ]] = 1 + +2  x<3  [[ x ]] = 2 + +Fungsi f: x  [[ x ]] disebut fungsi nilai bulat terbesar + +Grafik fungsi y = f(x) = [[ x ]] untuk x  R + +120 | Matematika Dasar + Grafiknya menyerupai tangga maka f(x) = [[ x ]] sering +disebut fungsi tangga + +F. SIFAT-SIFAT FUNGSI + 1) Fungsi Surjektif + +  Fungsi f : A  B disebut fungsi surjektif atau fungsi + + onto atau fungsi kepada jika dan hanya jika daerah + fungsi f sama dengan himpunan B atau Rf = B + +  Fungsi f : A  B disebut fungsi into atau fungsi ke + + dalam jika dan hanya jika daerah hasil fungsi f + merupakan himpunan bagian murni dari himpunan + + B atau Rf atau Rf  B. + + Contoh 5.15: + Himpunan A = {1, 2, 3, 4, 5} dan B = {a, b, c, d} + +Fungsi f adalah fungsi onto Fungsi f adalah fungsi into +Rf = {a, b, c, d} Rf = {a, b, c} +Rf = B + Rf  B + + 121 | Relasi dan Fungsi + 2) Fungsi Injektif + + Fungsi f : A B disebut fungsi injektif atau fungsi + satu-satu jika dan hanya jika untuk tiap a1, a2  A dan + a1  a2 berlaku f(a1)  f(a2) + + Contoh 5.16: + Himpunan P = {1, 2, 3} dan Q = {p, q, r}. + + Fungsi f adalah fungsi injektif Fungsi f bukan fungsi injektif + Untuk mengetahui fungsi injektif atau bukan, dapat + dilihat melalui grafik + 1) Gambarlah grafik fungsi y = f(x) pada bidang + + Cartesius + 2) Ambillah nilai-nilai x1, x2 anggota daerah asal dan x1 + +  x2 + a) Jika f(x1)  f(x2) maka f merupakan fungsi injektif + + b) Jika f(x1) = f(x2) maka f bukan fungsi injektif + +122 | Matematika Dasar + Contoh 5.17: + +1. Manakah yang merupakan fungsi injektif di bawah + +ini: + +a) y = f(x) = x2, x  R b) y = f(x) = x3, x  R + +Jawab : + + a b + +bukan fungsi injektif fungsi injektif + +Fungsi Bijektif + +Fungsi f: A  B disebut sebagai fungsi bijektif jika + +dan hanya jika fungsi f sekaligus merupakan fungsi +surjektif dan fungsi injektif. + + Contoh 5.18: Fungsi f : A  B + + Fungsi f : A  B A = {0, 1, 2} dan B = {a, b, c, d} + +A = {0, 1, 2} dan B = {a, b, c} + +fungsi f bijektif fungsi f bukan bijektif + 123 | Relasi dan Fungsi + G. FUNGSI KOMPOSISI + Operasi komposisi dilambangkan dengan o (dibaca + komposisi) + Fungsi baru dapat dibentuk dengan operasi komposisi + a. (f o g) (x), dibaca: f komposisi g(x) atau f (g x) + b. (g o f) (x), dibaca, g komposisi f(x) atau g (f x) + + Fungsi g : A  B + Tiap x  A dipetakan ke y  B + Sehingga g : x y ditentukan dengan rumus : y = g(x) + + Fungsi f : B C. + Tiap y  B dipetakan ke z  C, sehingga f : y z + + ditentukan dengan rumus : z = f (y) + + Fungsi h : A  C. + Tiap x  A dipetakan ke z  C, sehingga h : x z + + ditentukan dengan rumus: z = h (x) + Fungsi h disebut komposisi dari fungsi f dan fungsi g. + Komposisi fungsi f dan g ditulis dengan notasi h = f o g + atau h(x) = (f o g) (x) + +124 | Matematika Dasar + Contoh 5.19: + +1. Fungsi f : R R dan g : R R ditentukan f(x) = 4x – 1 + + dan g(x) = 2x. + Tentukan : + a) (f o g) (x) + b) (g o f) (x) + Jawab : + a) f(x) = 4x – 1 + + f(g(x)) = 4.g(x) – 1 + (f o g)(x) = 4(2x) – 1 + + = 8x – 1 + b) g(x) = 2x + + g(f(x)) = 2.f(x) + (g o f) (x) = 2(4x –1) + + = 8x – 2 + +2. Fungsi-fungsi f dan g dinyatakan dengan pasangan- + terurut + f = {(-1, 4), (1, 6), (2, 3), (8, 5)} + g = {(3, 8), (4, 1), (5, –1), (6, 2)} + +Tentukan : d) (f o g) (1) +a) (f o g) e) (g o f) (1) +b) (g o f) f) (g o f) (4) +c) (f o g) (4) +Jawab : + + 125 | Relasi dan Fungsi + H. FUNGSI INVERS + + Suatu fungsi f : A  B mempunyai fungsi invers f –1 : B +A jika dan hanya jika f merupakan fungsi bijektif atau + +himpunan A dan B mempunyai korespondensi satu-satu. + +Jika fungsi f : A  B pasangan terurut f : {(a, b) I a  A dan b +B} +Maka invers fungsi f adalah f –1 : B A adalah f –1 = {(b, a)I b +B dan aA} + + Contoh 5.20: + 1. A = {– 2, –1, 0, 1} dan B = {1, 3, 4}. + + Fungsi : A  B ditentukan oleh f = {(– 2, 1), (–1, 1), (0, + + 3), (1, 4)} + Carilah invers fungsi f, kemudian selidikilah apakah + invers fungsi f itu merupakan fungsi + Jawab : + + f -1: B  A ditentukan oleh f -1 = {(1, – 2), (1, –1), (3, 0), + + (4, 1)} + +126 | Matematika Dasar + Dari gambar terlihat f –1 adalah relasi biasa (bukan + fungsi) sebab terdapat dua pasangan terurut yang + mempunyai ordinat sama yaitu (1, – 2) dan (1, –1) +2. A = {0, 2, 4} dan B = {1, 3, 5, 7}. + + Fungsi : A  B ditentukan oleh g = {(0, 1), (2, 3), (4,5)} + + Carilah invers fungsi g, kemudian selidikilah apakah + invers fungsi g itu merupakan fungsi + Jawab : + + g –1 : B  A ditentukan oleh g –1 = {(1, 0), (3, 2), (5, 4)} + + Dari gambar terlihat g –1 adalah relasi biasa (bukan + fungsi) sebab ada sebuah anggota di B yang tidak + dipetakan ke A, yaitu 7 + + 127 | Relasi dan Fungsi + 3. A = {–1, 0, 1, 2} dan B = {1, 2, 3, 5}. + + Fungsi h: A  B ditentukan oleh h = {(–1, 1), (0, 2), (1, + + 3), (2, 5)}. + Carilah invers fungsi h, kemudian selidikilah apakah + invers fungsi h itu merupakan fungsi. + Jawab : + + h –1 : B  A ditentukan oleh h –1 = {(1, –1), (2, 0), (3, 1), + + (5, 2)} + + Dari gambar tampak bahwa h –1 merupakan suatu + fungsi. + Jadi, h –1 adalah fungsi invers. + + 4. Carilah fungsi inversnya + a) f(x) = x + 1 + b) f(x) = x2 – 1 + Jawab : + a) y = x + 1 + x =y–1 + + x = f –1(y) + + f –1(y) = y – 1 + +128 | Matematika Dasar + f –1(x) = x – 1 +b) y = x2 – 1 + + x2 = y + 1 + + x = y 1 + x = f –1(y) + + f –1(y) = y  1 + f –1(x) = x  1 + +I. INVERS FUNGSI KOMPOSISI + + Misalkan fungsi f : A  B dan g : B  C . Jika h +adalah fungsi komposisi dari f dan g atau h : A  C dengan +h  g  f maka invers fungsi h adalah h1 : C  A dengan +h1  f 1  g 1 jadi jika h(x)  (g  f )(x) maka +h1 (x)  (g  f )1 (x)  ( f 1  g 1 )(x) + +Contoh 5.21: + +Diketahui h(x)  (g  f )(x) dengan f (x)  2x 1 dan + x3 + +g 1  x  4 . Tentukan h 1 (x) + +Jawab: + +Jika f (x)  2x 1  f 1(x)  2x 1 + x3 x3 + +Jika h(x)  (g  f )(x) maka + +h1 (x)  (g  f )1 (x)  ( f 1  g 1 )(x) + +h1 (x)  ( f 1  g 1 )(x)  ( f 1 (g 1 (x))  f 1 (x  4) + += 3(x  4) 1  3x 11 + (x  4)  2 x  6 + + 129 | Relasi dan Fungsi + J. RANGKUMAN + +1. Suatu relasi dapat dinyatakan dengan beberapa cara + yaitu: + a. Dengan kata-kata + b. Dengan diagram panah + c. Dengan himpunan pasangan berurutan + d. Dengan grafik. + +2. Relasi dari himpunan A ke himpunan B adalah pasangan + berurutan yang merupakan himpunan bagian dari A x B + +3. Daerah asal dari suatu relasi (domain) adalah himpunan + yang beranggotakan dari unsur-unsur yang pertama dari + pasangan berurutan itu, sedangkan daerah hasil suatu + relasi adalah himpunan yang anggotanya terdiri dari + unsur-unsur kedua dari pasangan berurutan tersebut. + +4. Suatu fungsi f adalah suatu aturan yang megkaitkan + setiap elemen x dalam suatu himpunan yang disebut + daerah asal (domain) atau daerah definisi ke sebuah nilai + tunggal f(x) dari himpunan kedua yang disebut kodomain. + Himpunan nilai yang diperoleh secara demikian disebut + daerah hasil (range). + +5. Sifat-sifat fungsi + a. Sifat bijektif + b. Sifat injektif + c. Sifat surjektif + +6. Sifat-sifat relasi + a. Sifat reflektif + b. Sifat simetris + c. Sifat transitif + +130 | Matematika Dasar + K. LATIHAN + +1. Diketahui G = { 5, 7, 11 }. Tentukan G x G dan n(G x G ). + +2. Diketahui himpunan A = {a, b} dan himpunan B = { 9 }. + +Tentukan semua relasi R : A  B yang dapat + +didefinisikan dan hitung jumlahnya. + +3. Diketahui himpunan C = {x, y}. Tentukan semua relasi R : + C  C yang dapat didefinisikan dan hitung jumlahnya. + +4. Diberikan himpunan A = {1, 2, 3, 4, 5} dan himpunan B = + {2, 3, 4, 5, 6, 8, 10, 11, 12}. Nyatakan relasi A terhadap B + dengan relasi berikut. + a. Anggota himpunan A dipasangkan dengan anggota + himpuna B dengan relasi B = A + 1 + b. Anggota himpunan A dipasangkan dengan anggota + himpunan B dengan relasi B = 2A + 2 + +Kemudian periksa apakah relasi yang terbentuk adalah +fungsi atau bukan. + +5. Jika mahasiswa direlasikan dengan tanggal kelahirannya. + Apakah relasi tersebut merupakan fungsi? Berikan + penjelasan anda! + +6. Nyatakan invers dari tiap relasi berikut : + a. R = { (x,y)  x habis dibagi oleh y, x, y Z } + b. R = { (x,y)  x  y, x, y Z } + c. R = { (x,y)  x – 4 = y, x, y Z } + +7. Diketahui D = { x  x garis lurus } + Pada D didefinisikan relasi R = { (x,y)  x sejajar y, x  D + ,yD} + Relasi R tersebut bersifat ..................................................... + + 131 | Relasi dan Fungsi + 8. Diketahui P = { x  x subset dari himpunan A } + Pada P didefinisikan relasi R = { (x,y)  x  y ,x  P , y  P } + Relasi R tersebut bersifat ..................................................... + +9. Diketahui D = { x  x garis lurus } + Pada D didefinisikan relasi R = { (x,y)  x tegak lurus y, x  + D,yD} + Relasi R tersebut bersifat ..................................................... + +10. Relasi-relasi berikut didefinisikan pada himpunan B = { 2, + 4, 5 }. + a. R = { (2,2) , (4,4) , (5,5) } + b. R = { (2,4) , (4,5) , (2,5) , (5,2) , (2,2) } + c. R = { (5,4) } + d. R = { (x,y)  x habis membagi y , x,y  B }. + Tentukan sifat yang dimiliki oleh masing-masing relasi + tersebut. + +11. Relasi-relasi berikut didefinisikan pada himpunan Z + (himpunan bilangan bulat). + a. R = { (2,2) , (4,4) , (5,5) } + b. R = { (2,4) , (4,5) , (2,5) , (2,2) } + c. R = { (5,4) } + d. R = { (x,y)  x habis membagi y }. + e. R = { (x,y)  x  y }. + Tentukan sifat yang dimiliki oleh masing-masing relasi + tersebut. + +12. Diketahui D = { x  x garis lurus }. Pada D didefinisikan + relasi + a. R = { (x,y)  x sejajar y, x  D , y  D } + b. R = { (x,y)  x tegak lurus y, x  D , y  D } + c. R = { (x,y)  x berpotongan dengan y, x  D , y  D } + +132 | Matematika Dasar + Di antara ketiga relasi tersebut, sebutkan relasi yang + merupakan relasi ekivalen dan relasi yang merupakan + relasi pengurutan sebagian. + 13. Di antara relasi-relasi berikut, relasi manakah yang + merupakan fungsi ? + +14. Fungsi-fungsi berikut didefinisikan pada himpunan + bilangan riil R. Tentukan fungsi yang merupakan fungsi + satu-satu, fungsi pada atau fungsi bijektif. + a. f(x) = x + b. f(x) = x2 + c. f(x) = x3 + d. f(x) = | x | + +15. Tentukan domain dan range dari fungsi-fungsi yang + diberikan berikut : + + a. f(x) = x + b. h(x) = 1  x + + 1 + + c. g(x) = + + x + + 133 | Relasi dan Fungsi + 16. Tentukan hasil operasi f + g, f – g, f . g, f / g, dan g / f + +beserta domain dari fungsi yang diberikan berikut ini. + +a. f(x) = 1 x dan g(x) = 1 x + + 1 x x + +b. f(x) = x dan g(x) = x  1 + +c. f(x) = x dan g(x) = x  1 + +17. Tentukan domain dan range dari f dan g + a. Selidiki apakah fungsi f o g dan g o f terdefinisi + b. Jika fungsi komposisi pada poin (b) terdefinisi, + tentukan domain dan range dari masing-masing + fungsi komposisi tesebut. + + 1) f(x) = 4x – x2 dan g(x) = x + + 2) f(x) = 1 – x2 dan g(x) = 1 + 2x + + 3) f(x) = 1  x dan g(x) = 1  x + 4) f(x) = 2x dan g(x) = 1- x2. + + 1 x +18. Tentukan invers dari fungsi f (x)  3x  4 + + 2x 1 +19. Diketahui fungsi f : R  R dengan f (x)  1  2 . + + x 1 + Jika f 1 (k)  5 maka tentukanlah nilai k + + 3 +20. Jika f (x)  1 dan g(x)  2x 1, maka tentukan + + x + ( f  g)1 (x) + +134 | Matematika Dasar + BAB 6 + + PERSAMAAN DAN + PERTIDAKSAMAAN + + PENDAHULUAN + Persamaan dan pertidaksamaan adalah materi yang +sering terkait dengan kehidupan sehari-hari, ketika kita akan +menyelesaikan suatu soal yang berbentuk cerita atau +pemecahan masalah. Misalnya tentang luas tanah seseorang +dibandingkan dengan luas tanah orang lain. Demikian pula +dengan umur seseorang berapa kalinya umur orang lain. +Konsep persamaan dan pertidaksamaan berkembang dari +konsep kesamaan dan ketidaksamaan pada system bilangan +real, sehingga menyelesaikan suatu persamaan dan +pertidaksamaan banyak menggunakan sifat-sifat kesamaan +dan ketidaksamaan bilangan real. + + 135 | Persamaan dan Pertidaksamaan + A. PERSAMAAN LINEAR + Persaman adalah kalimat terbuka yang mengandung + +hubungan (relasi) sama dengan. Sedangkan persamaan linear +adalah suatu persamaan yang pangkat tertinggi dari +variabelnya adalah satu atau berderajat satu. + +1. Persamaan Linear Satu Variabel + Persamaan linear satu variable adalah persamaan linear + yang memiliki satu variabel saja. + Bentuk umum : + + ax  b  0; a,b  R, a  0 + + a adalah koefisien dari variabel x dan b adalah konstanta + Contoh 6.1: + + a. 4x + 8 = 0 + b. 2x - 18 = 0 + + Kedua persamaan di atas akan bernilai benar jika + variabelnya berturut-turut diganti dengan -2 dan 9. + +2. Persamaan Linear Dua Variabel + + Persamaan linear dua variabel adalah persamaan yang + hanya memiliki dua variabel dan masing-masing + berpangkat satu + Bentuk umum: + + ax  by  c; a,b,c  R, a  0, b  0 + + a adalah koefisien dari variable x dan b adalah koefisien + dari variable y sedangkan c adalah konstanta. + + Contoh 6.2 + Sebutkan masing-masing variabel dari persamaan linier + dua variabel berikut + + a. 6x  3y  9 merupakan persamaan linear dua + + variabel yaitu variabel x dan variabel y + +Dasar Matematika | 136 + b. 3 p  3q  18 merupakan persamaan linear dua + + variabel yaitu variabel p dan variabel q + +3. Sifat-Sifat Persamaan Linear + +a. Nilai persamaan tidak berubah, jika : + 1) Kedua ruas ditambah atau dikurangi bilangan yang + sama. + 2) Kedua ruas dikalikan atau dibagi bilangan yang + sama. + +b. Suatu persamaan jika dipindahkan ruas, maka : + 1) Penjumlahan berubah menjadi pengurangan dan + sebaliknya. + 2) Perkalian berubah menjadi pembagian dan + sebaliknya. + +Contoh 6.3: + +1. 1 x + 3 = 12 + 3 + + 1 x + 3 – 3 = 12 – 3 (kedua ruas dikurangi 3) + 3 + + 1x =9 + 3 + + 1 x . 3 = 9.3 (kedua ruas dikali 3) + 3 + + x = 27 + +2. 4x – 7 = 2x + 9 +  4x – 7 + 7 = 2x + 9 + 7 (kedua ruas ditambah 7) +  4x = 2x + 16 +  4x – 2x = 2x – 2x + 16 (kedua ruas dikurangi 2x) +  2x = 16 + + 137 | Persamaan dan Pertidaksamaan + 1 1 + 2x . = 16 . + 22 + +x=8 + +4. Himpunan Penyelesaian Persamaan Linear + Menentukan himpunan penyelesaian persamaan linear + berarti mencari harga yang memenuhi untuk pengganti + variabel pada persamaan linear yang bersangkutan. + +Contoh 6.4: + +Tentukan himpunan penyelesaian persamaan linear + +2x 1  x 1 +5 2 + +Jawab: + +2x 1  x 1 +5 2 + + 2(2x- 1) = 5(x + 1) + + 4x – 2 = 5x + 5 + + 4x – 5x = 2 + 5 + + -x = 7 + + x = -7 + +HP = {-7} + +5. Sistem Persamaan Linear Dua Variabel + Bentuk Umum + ax + by = c + px + qy =r + a, b, c, p, q, r R + a, p = koefisien dari x + b, q = koefisien dari y + c, r = konstanta + x, y = variabel + +Dasar Matematika | 138 + 1. Penyelesaian Sistem Persamaan Linear Dua Variabel + Ada beberapa cara menyelesaikan sistem persamaan + linear dua variabel, antara lain : + + a. Cara Grafik + Langkah-langkahnya sebagai berikut : + 1) Gambarlah grafik garis lurus pada bidang + koordinat. + 2) Tentukan titik potng kedua garis tersebut. + Koordinat titik potong tersebut merupakan + pasangan penyelesaian dari system persamaan + yang dimaksud. + + b. Cara Eliminasi + Langkah-langkahnya sebagai berikut : + 1) Menyamakan koefisien salah satu variabel + dengan cara mengalikan dengan bilangan selain + nol. + 2) Menjumlahkan atau mengurangkan ruas-ruas + yang bersesuaian dari kedua persamaan linear + yang baru tersebut. + + Contoh 6.5: + Tentukan himpunan penyelesaian dari sistem + persamaan : + + 5x  3y  19 + 2x  2 y  10 dengan cara eliminasi ! + + Jawab: + Eliminir y + + 5x  3y  19 x2 10x  6 y  38 + 2x  2 y  10 x2 6x  6 y  30 + + 4x = 8 + x =2 + + 139 | Persamaan dan Pertidaksamaan + Eliminir x + + 5x  3y  19 x2 10x  6 y  38 + 2x  2 y  10 x5 10x  10y  50 + + -4y = -12 + Jadi HP = {(2,3)} y=3 + + c. Cara Substitusi + Substitusi artinya mengganti. Langkah-langkahnya + sebagai berikut : + 1) Nyatakan salah satu variabel yang memuat + variabel yang lain dari salah satu persamaan. + 2) Substitusikan hasil dari langkah 1) ke persamaan + yang lain. + +Contoh 6.6: + +Tentukan himpunan penyelesaian dari system persamaan + +: + +4x  2 y  12 dengan cara substitusi ! + + x y 9 + +Jawab: + +4x  2 y  12 …………… (1) + +x + y = 9  x = 9 – y ….. (2) +(2) substitusi ke (1) +4(9-y) – 2y = 12 + 36 – 4y – 2y = 12 + -6y = 12 - 36 + -6y = -24 + y = 4 ………………… (3) +(3) substitusi ke (2) +x=9–4 +x=5 + +Jadi HP = {(5,4)} Cara Gabungan (Eliminasi dan Substitusi) + +Dasar Matematika | 140 + Contoh 6.7: +Tentukan himpunan penyelesaian dari sistem persamaan: + + 3x  y  5 +2x  y  10 dengan cara gabungan antara eliminasi + +dan substitusi ! +Jawab: +Eliminir y +3x – y = 5 +2x + y = 10 + + + 5x = 15 + x =3 + x = 3 substitusi ke 3x – y = 5 + +  3(3) – y = 5 + 9–y=5 +  -y = 5 - 9 +  -y = -4 + + y=4 + Jadi HP = {(3,4)} + +d. Cara Determinan + Determinan adalah suatu bilangan yang berkaitan + dengan matriks bujur sangkar (persegi). + Untuk menyelesaikan dengan cara determinan dari + bentuk persamaan : + ax + by = c + px + qy = r + diubah dalam susunan bilangan sebagai berikut dan + diberi notasi : D, Dx, Dy. + + 141 | Persamaan dan Pertidaksamaan + Dengan : D= ab = aq – bp + + pq + + Dx = cb = cq – br + + rq + + Dy = ac = ar – cp + + pr + +Kemudian x dan y dapat ditentukan dengan : + + x = Dx dan y = Dy + D D + +Contoh 6.8: + +Tentukan himpunan penyelesaian dari sistem persamaan: + + 2x  3y  1 dengan cara determinan ! +  +  3x  y  5 + +Jawab: + + D= 23 = 2.1 – 3.3 = 2 – 9 = -7 + + 31 + + Dx = 13 = 1.1 – 3.5 = 1 – 15 = -14 + + 51 + + Dy = 21 = 2.5 – 1.3 = 10 – 3 = 7 + + 35 + + x = Dx = 14 = 2 + D 7 + + y = Dy = 7 = -1 + D 7 + +Jadi HP = {(2, -1)} + +Dasar Matematika | 142 + B. PERSAMAAN KUADRAT + + Persamaan kuadrat adalah persamaan berderajat dua +dalam x yang dinyatakan dengan : + + ax2 + bx + c = 0; a, b, cR ; a 0 + + a = koefisien dari x2 + b = koefisien dari x + c = konstanta + + Contoh 6.9: + x2 + 2x - 15 = 0 + x2 – 9 = 0 + +1. Penyelesaian Persamaan Kuadrat +Ada beberapa cara menyelesaikan persamaan kuadrat, antara +lain : + + a. Memfaktorkan + + Contoh 6.10: + 1) Selesaikan x2 – 5x + 6 = 0 ! + + Jawab: + x2 – 5x + 6 = 0 +  (x – 3)(x – 2)= 0 +  x – 3 = 0 atau x -2 = 0 + x = 3 atau x = 2 + Jadi HP = {3, 2} + + 2) Selesaikan x2 – 25 = 0 ! + Jawab: + x2 – 25 = 0 +  (x + 5)(x – 5)= 0 +  x + 5 = 0 atau x - 5 = 0 + x = -5 atau x = 5 + + Jadi HP = {-5, 5} + + 143 | Persamaan dan Pertidaksamaan + b. Melengkapkan Kuadrat Sempurna + +Contoh 6.11: +1) Selesaikan x2 + 10x + 21 = 0 ! + + Jawab: + x2 + 10x + 21 = 0 +  x2 + 10x = -21 +  x2 + 10x + 25 = -21 + 25 + + ( 1 koefisien x)2 + 2 + + (x + 5)2 = 4 + + x + 5 =  4  2 + + x + 5 = 2 atau x + 5 = -2 + +x = -3 atau x = -7 + +Jadi HP ={-3, -7} + +2) Selesaikan 4x2 + 8x + 3 = 0 ! + Jawab: + 4x2 + 8x + 3 = 0 +  4x2 + 8x = -3 + + 3 +  x 2 + 2x =  + + 4 + 3 + +  x 2 + 2x + 1 =  + 1 + 4 + +  (x + 1)2 = 1 + 4 + +x+1=  1 1 + 42 + +1 1 + x + 1 = atau x + 1 = - +2 2 + +Dasar Matematika | 144 + 1 3 + x = - atau x = - + 2 2 + +Jadi HP =  1 , 3 +  2  + 2  + +c. Dengan Rumus ABC + + x1,2   b  b2  4ac + 2a + +Contoh 6.12: +1) Selesaikan x2 + 6x - 16 = 0 ! + +Jawab: +a = 1, b = 6, c = -16 + +x1,2   6  62  4(1)(16) + + 2(1) + +=  6  100 + 2 + +  6 10 + += + + 2 + +x1   6 10  4  2 atau x2   6 10   16  8 + 2 2 2 2 + +Jadi HP = {2, -8} + +2. Sifat-sifat Akar persamaan Kuadrat + + Sifat-sifat akar persamaan kuadrat yang menyangkut +banyaknya akar persamaan kuadrat, ditentukan oleh nilai +diskriminannya yaitu D = b2 – 4ac. + + (i) D > 0  kedua akar real dan berbeda + (ii) D = 0  kedua akar sama (kembar) + (iii) D < 0  Persamaan kuadrat tidak mempunyai akar + + nyata + + 145 | Persamaan dan Pertidaksamaan + Contoh 6.13: + Tentukan sifat-sifat akar persamaan berikut ini ! + 1) x2 – 4x + 3 = 0 + 2) x2 + 6x + 9 = 0 + 3) x2 + 3x + 3 = 0 + + Jawab: + 1) x2 – 4x + 3 = 0 + + a = 1, b = -4, c = 3 + D = b2 – 4ac = (-4)2 – 4(1)(3) = 16 – 12 = 4 + D > 0, kedua akar real dan berbeda. + 2) x2 + 6x + 9 = 0 + a = 1, b = 6, c = 9 + D = b2 – 4ac = 62 – 4(1)(9) = 36 – 36 = 0 + D = 0, kedua akar sama (kembar) + 3) x2 + 3x + 3 = 0 + a = 1, b = 3, c = 3 + D = b2 – 4ac = 32 – 4(1)(3) = 9 – 13 = -3 + D < 0, persamaan tidak mempunyai akar nyata. + +C. PERTIDAKSAMAAN LINEAR + Pertidaksamaan linear adalah suatu pertidaksamaan + +yang variabelnya paling tinggi berderajat satu. +Bentuk umum : + + ax + b (R) 0 ; a, b  R, a  0 + + a = koefisien dari x + x = variabel + b = konstanta + (R) = salah satu relasi pertidakamaan ( , , ,  ) + +Dasar Matematika | 146 + Contoh 6.14: + 5x + 5  25 + 3x – 3  12 + x+y8 + +1. Sifat-sifat Pertidaksamaan + a. Arah tanda pertidaksaman tetapjika ruas kiri dan ruas + kanan pertidaksamaan ditambah, dikurangi, dikalikan, + atau dibagi dengan bilangan positif yang sama. + + 1) a  b  a + c  b + c + 2) a  b  a – d  b – d + 3) a  b dan c  0  ac  bc + + ab + + 4) a  b dan d  0   + + dd + + b. Arah tanda pertidaksamaan berubah jika ruas kiri dan + ruas kanan dikalikan atau dibagi dengan bilangan + negatif yang sama. + + 1) a  b dan c  0  ac  bc + + ab + + 2) a  b dan d  0   + + dd + + Contoh 6.15: + 1) Selesaikan 6x + 2  4x + 10 ! + + Jawab: + 6x + 2  4x + 10 +  6x + 2 – 2  4x + 10 – 2 +  6x  4x + 8 +  6x – 4x  4x – 4x + 8 +  2x  8 + + 11 + +  .2x  .8 + + 22 + + x4 + + 147 | Persamaan dan Pertidaksamaan + 2) Selesaikan 6x – 5  9x + 10 ! + +Jawab: + +6x – 5  9x + 10 + + 6x – 5 + 5  9x + 10 + 5 + + 6x  9x + 15 + + 6x – 9x  9x – 9x + 15 + + -3x  15 + +   1  (-3x)    1  (15) + 3  3 + +x5 + +2. Himpunan Penyelesaian Pertidaksaman Linear + +Contoh 6.16: +a. Tentukan himpunan penyelesaian dari 6x + 4  4x + 20, + + xB ! + Jawab: + 6x + 4  4x + 20 +  6x + 4 - 4  4x + 20 – 4 +  6x  4x + 16 +  6x – 4x  4x – 4x + 16 +  2x  16 + + 11 + +  .2x  .16 + + 22 + + x8 + + 8 +Jadi HP = { x x  8, xB} + +Dasar Matematika | 148 + b. Tentukan himpunan penyelesaian dari 5x + 10 > 8x + 4, + +xR ! + +Jawab: + +5x + 10 > 8x + 4 + + 5x + 10 – 10 > 8x + 4 – 10 + + 5x > 8x – 6 + + 5x – 8x > 8x – 8x – 6 + + -3x > -6 + +   1  (-3x) <   1  (-6) + 3  3 + +x<2 + +Jadi HP ={ x x < 2 , xR} + +D. PERTIDAKSAMAAN KUADRAT + + Pertidaksamaan kuadrat adalah suatu pertidaksamaan +yang mempunyai variabel paling tinggi berderajat dua dan +koefisien variabel pangkat duanya tidak sama dengan nol. + +Bentuk umum : + + ax2 + bx + c (R) 0; a, b, cR ; a 0 + a = koefisien dari x2 + b = koefisien dari x + c = konstanta + (R) = salah satu relasi pertidakamaan ( , , ,  ) + + Contoh 6.17: + x2 + 5x + 6  0 + x2 – x - 6 < 0 + 2x2 + 9x + 5  0 + + 149 | Persamaan dan Pertidaksamaan + 1. Sifat-sifat Pertidaksamaan Kuadrat + Secara umum sifat-sifat pertidaksamaan kuadrat sama + dengan sifat-sifat pertidaksamaan linear. + +2. Himpunan Penyelesaian Pertidaksamaan Kuadrat + Langkah-langkah menentukan himpunan penyelesaian + suatu pertidaksamaan kuadrat adalah sebagai berikut : + (i) Ubah bentuk pertidaksamaan ke dalam bentuk + umum. + (ii) Tentukan pembuat nol ruas kiri. + (iii) Letakkan pembuat nol pada garis bilangan. + (iv) Substitusi sembarang bilangan pada pertidaksamaan + kecuali pembuat nol. + +Jika benar, maka daerah yang memuat bilangan tersebut +merupakan daerah penyelesaian. + +Contoh 6.18: + +1. Tentukan himpunan penyelesaian dari x2 + 6x + 8  0 + +untuk x R ! + +Jawab: + +(i) x2 + 6x + 8  0 + +(ii) Pembuat nol + +x2 + 6x + 8 = 0 + + (x + 4)(x + 2) = 0 + + x + 4 = 0 atau x + 2 = 0 + +x = -4 atau x = -2 + +(iii) (B) (S) (B) + ++ - + + + -4 -2 + +(iv) Ambil x = 0  x2 + 6x + 8  0 + 8  0 (B) + +Jadi HP = { xx  -4 atau x  -2 } + +Dasar Matematika | 150 + 2. Tentukan himpunan penyelesaian dari 2x2 + 3x - 5 < 0 + untuk x R ! + Jawab: + 2x2 + 3x - 5 < 0 + Pembuat nol + 2x2 + 3x - 5 = 0 +  (2x + 5)(x – 1) = 0 +  2x + 5 = 0 atau x – 1 =0 +  2x = -5 atau x = 1 + + x =  5 atau x = 1 + 2 + +(S) (B) (S) + ++ - B + +  5 1 + 2 + +Ambil x = 0  2x2 + 3x - 5 < 0 + + - 5 < 0 (B) + +Jadi HP = { x  5 < x < 1 } + 2 + +E. APLIKASI PERSAMAAN DAN PERTIDAKSAMAAN LINIER + + Beberapa masalah dalam kehidupan sehari - hari dapat +diselesaikan dengan konsep peramaan maupun dengan +pertidaksamaan linier. Langkah pertama yang dilakukan adlah +menterjemahkan masalah tersebut kedalam kalimat +matematika. Untuk lebih jelasnya, perhatikan contoh - contoh +berikut. + + Contoh 6.19: + 1. Ahli kesehatan mengatakan bahwa akibat menghisab + + satu batang rokok waktu hidup seseorang akan + + 151 | Persamaan dan Pertidaksamaan + berkurang selama 5,5 menit. Berapa rokok yang + dihisab Fahri tiap selama 275 hari(1 tahun = 360 hari). + + Jawab: + misalkan banyaknya rokok yang dihisab tiap hari + adalah x, maka waktu hidup berkurang tiap harinya + 5,5 x menit. + Dalam setahun waktu hidup, berkurang banyak 5,5x + +  360 hari. Dalam 20 tahun waktu hidup berkurang + banyak 5,5x  360  20 menit. Sehingga diperoleh + + persamaan : + + 5,5x  360 20 = 275  60  24 + + 39.600x = 396.000 + x = 396.000/39.600 + x = 10 + jadi, fahri menghisap rokok 10 batang setiap hari. + + 2. Upah seorang teknisi untuk memperbaiki suatu mesin + bubut adalah Rp. 250.000,- ditambah biaya Rp. 75.000 + tiap jamnya. Karena pekerjaanya kurang rapi, + pembayaranya dip[otong 10% dari upah total yang + harus diterima. Jika teknisi tersebut mendapat upah + sebesar Rp. 798.750,- Berapa jam mesin bubut + tersebut diperbaiki? + + Jawab: + Misalkan teknisi bekerja selama x jam, dan upah yang + diterima hanya (100 - 10)% = + 90%, maka diperoleh persamaan berikut: + (75.000x + 250.000) X 90% = 798.750 + 67.500x + 225.000 = 798.750 + 67.500x = 798.750 – 225.000 + 67.500x = 573.750 + +Dasar Matematika | 152 + x = 573.750/67.500 = 8.5 + Jadi, teknisi tersebut bekerja memperbaiki mesin + selama 8,5 jam. + +3. Untuk dapat diterima sebagai karyawan di PT.Teknik + Sejahtera, calon karyawan akan menjalani tes + sebanyak 4 kali, yaitu tes tertulis, psikotes, tes + ketrampilan, dan wawancara dengan perbandingan + hasil tes berturut-turut adalah 4 : 3 : 2 : 1. Total nilai + tes tidak boleh kurang dari 827. Azam telah mengikuti + tes dengan hasil sebagai berikut. Psikotes =80, tes + ketrampilan =95, dan wawancara =85. Tentukan nilai + terendah tes tertulisnya agar azam dapat diterima + menjadi karyawan. + Jawab : + Misalkan nilai tes tertulis adalah x,maka diperoleh + pertidaksamaan : + 4x + 3 . 80 + 2 . 95 + 1 .85 > 827 + 4x + 240 + 190 + 85 > 827 + 4x > 827 – 240 – 190 – 85 + 4x > 312 + x > 78 + Jadi, nilai terendah tes tertulis azam adalah agar + diterima sebagai karyawan adalah 78. + + 153 | Persamaan dan Pertidaksamaan + F. RANGKUMAN + + 1. Persamaan adalah kalimat terbuka yang mengandung + hubungan (relasi) sama dengan. + Bentuk umum persamaan linier: + ax + b = 0; a,b ∈ R, a≠0 + a adalah koefisen dari variabel x dan b adalah + konstanta + + 2. Sifat-sifat persamaan linier + a. nilai persamaan tidak berubah, jika: + kedua ruas ditambahkan atau dikurangi + bilangan yang sama + kedua ruas dikalikan atau dibagi bilangan yang + sama + b. suatu persamaan jika dipindahkan ruas, maka: + penjumlahan berubah menjadi pengurang, + demikian pula sebaliknya + perkalian berubah menjadi pembagian dan + sebaliknya + + 3. Ada beberapa cara menyelsaikan sistem persamaan + linier dua variabel yaitu: + a. Cara grafik + b. Cara eliminasi + c. Cara subtitusi + d. Cara gabungan (eliminasi-subtitusi + e. Cara determinan + + 4. Persamaan kuadrat adalah persamaan berderajat dua + dalam x dinyatakan dengan: ax2 + bx + c = 0; a,b,c ∈ R, + a≠0 + + 5. Cara menyelesaikan persamaan kuadrat, antara lain: + a. Memfaktorkan + +Dasar Matematika | 154 + b. Melengkapkan kuadrat sempurna + c. Rumus ABC +6. Sifat-sifat akar persamaan kuadrat ditentukan oleh + nilai diskriminannya yaitu D = b2 – 4ac + D > 0  kedua akar real dan berbeda + D = 0  kedua akar sama (kembar) + D < 0  Persamaan kuadrat tidak mempunyai akar + nyata +7. Sifat-sifat pertidaksamaan + a. Arah tanda pertidaksamaan tetap jika ruas kiri dan + + ruas kanan pertidaksamaan ditambah, dikurangi, + dikalikan dan dibagi dengan bilangan positif yang + sama + b. Arah tanda pertidaksamaan berubah jika ruas kiri + dan ruas kanan dikalikan dan dibagi dengan + bilangan negatif yang sama. + + 155 | Persamaan dan Pertidaksamaan + G. LATIHAN + +1. Tentukan himpunan penyelesaian persamaan linear + berikut ! + a. 5 + 3(2 – x) + 2 = 2(x – 3) + b. 8x – 3 = 4(x + 1) + 5 + +2. Tentukan himpunan penyelesaian persamaan linear + +berikut ! + +3x  2  x +a. 5 3 + +b. x  3x  x  2 + 34 + +c. 3 x  1 x  2x  3 +52 4 + +3. Tentukan penyelesaian soal-soal berikut ! + + a. 6x + 3  -2x + 1 + + 1 + + b. x + 2 > (x + 1) + + 2 + c. x 1 1  3 + + 2 + +4. Tentukan himpunan penyelesaian sistem persamaan + +kuadrat berikut dengan menggunakan pemfaktoran! + +a. x2 – 5x - 36 = 0 b. x2 – 13x + 22 = 0 + +5. Tentukan himpunan penyelesaian sistem persamaan + +kuadrat berikut dengan melengkapkan kuadrat sempurna! + +a. x2 + 5x + 4 = 0 b. x2 – 11x + 24 = 0 + +Dasar Matematika | 156 + 6. Tentukan himpunan penyelesaian sistem persamaan + +kuadrat berikut dengan menggunakan rumus abc ! + +a. x2 – 4x - 45 = 0 b. . x2 + 2x - 3 = 0 + 4 + +7. Tentukan himpunan penyelesaian sistem persamaan + kuadrat berikut dari x2 + 4x – 60 = 0 ! + +8. Jika x1 dan x2 adalah akar-akar persamaan kuadrat x2 + 5x + - 36 = 0, tentukan x1 dan x2 ! + +9. Tentukan himpunan penyelesaian pertidaksamaan + +kuadrat berikut ! + +a. x2 – 2x - 8 < 0 d. x2 – 5x < 0 g. x2 –x - 2 < 0 + +b. x2 – 3x  0 e. x2 – 3 x + 1 > 0 h. x  x 1 + 2 x4 + +c. x2 – 10x + 21 < 0 f. x2 + x - 12  0 + +10. Suatu persegi panjang memiliki ukuran panjang (4x + 2) cm + dan lebar (x + 1) cm. + a. Tentukan keliling persegi panjang + b. Jika kelilingnya 66 cm, tentukan x. + c. Tentukan panjang dan lebarnya + d. Tentukan luas persegi panjang tersebut. + +11. Dua kali suatu bilangan jika ditambah dengan lima hasilnya + sama dengan 27. Tuliskan kalimat matematikanya. + +12. Usman memiliki uang Rp 3.800,00 lebih banyak dari uang + Adi. Jika jumlah uang mereka Rp 10.200,00 maka banyak + uang Usman adalah… + +13. Bastian berusia 3 tahun lebih tua dari Diah. Jumlah usia + mereka kurang dari 15 tahun, usia Diah sekarang adalah….. + + 157 | Persamaan dan Pertidaksamaan + 14. Lebar sebuah persegi panjang lebih pendek 4 cm dari + panjangnya. Jika keliling nya sama dengan 72 cm, panjang + persegi panjang adalah + +15. Sebuah kawat yang panjangnya tidak lebih dari 72 cm + dibuat kerangka balok dengan kedua ujung kerangka balok + tersebut berbentuk persegi. Panjang balok lebih 6 cm dari + pada lebarnya. Maka tentukan panjang, lebar dan tinggi + balok tersebut? + +16. Ukuran panjang lapangan tenis 16 m lebihnya daripada + lebar lapangan tersebut. Apabila luas lapangan tenis 225 + m2, berapakah ukuran panjang dan lebar lapangan tenis + tersebut? + +17. Untuk dapat diterima sabagai suster di RS SEHAT, seorang + calon suster akan menjalani tes sebanyak 4 kali, yaitu tes + tertulis, psikotes, tes keterampilan dan wawancara dengan + perbandingan hasil tes berturut-turut 3 : 2 : 4 : 1 dan total + tes tidak boleh kurang dari 793. Windy adalah salah + seorang calon suster yang telah mengikuti tes dengan hasil + sebagai berikut: tes tertulis = 75, psikotes = 78, dan nilai + wawancara = 92. Tentukan nilai terendah tes keterampilan + agar ia diterima di rumah sakit tersebut. + +18. Dua bilangan mempunyai selisih 495. Jika yang satu dibagi + yang lain, maka hasilnya 4 dengan sisa 6. Bilangan- + bilangan yang manakah itu? + +19. Empat kali ukuran tinggi suatu jajar genjang sama dengan + 3 kali ukuran alasnya dikurangi 9 cm. jika alas ditambah 4 + dan tingginya dikurangi 2 cm, maka luas daerahnya + berkurang 6 cm. Berapakah tinggi jajar genjang tersebut? + +20. Dalam suatu kelas terdapat anak laki-laki dan anak + perempuan. Jika ada 4 anak laki-laki masuk dan 5 anak + +Dasar Matematika | 158 + perempuan masuk maka rasio banyaknya anak laki-laki + dan anak perempuan adalah 3:4. Jika ada 3 anak laki-laki + dan 2 anak perempuan keluar, maka rasio banyaknya anak + laki-laki dan anak perempuan menjadi 2 : 3. Berapa + banyaknya anak laki-laki dan anak perempuan? +21. Beni memiliki sejumlah uang logam. Uang tersebut + disusun dalam suatu jajaran. Jika banyaknya uang logam + pada tiap baris dikurangi 2, maka banyanya baris + bertambah 2. Jika pada tiap baris ditambahkan 4 uang + logam, maka banyaknya baris berkurang 3. Berapa + banyaknya uamg logam tersebut? + + 159 | Persamaan dan Pertidaksamaan + Dasar Matematika | 160 + BAB 7 + + TRIGONOMETRI + PENDAHULUAN + + Trigonometri adalah cabang matematika yang +mempelajari hubungan yang meliputi panjang dan sudut +segitiga. Trigonometri berasal dari bahasa Yunani yaitu +trigonom = tiga sudut dan metron adalah mengukur. Dari dua +kata tersebut, trigonometri dapat diartikan cabang ilmu +matematika yang mempelajari tentang perbandingan ukuran +sisi siatu segitiga apabila ditinjau dari salah satu sudut yang +terdapat pada segitiga tersebut. Dalam mempelajari +perbandingan sisi-sisi segitiga pada trigonometri, maka +segitiga mempunyai satu tepat sudutnya 900 artinya segitiga +itu tidak lain adalah segitiga siku-siku. Jadi, konsep dasar dari +trigonometri adalah sudut dan segitiga siku-siku. Awal +trigonometri pada zaman Mesir kuno dan Babilonia. +Matematikawan India adalah perintis perhitungan variabel +aljabar yang digunakan untuk menghitung astronomi. Aplikasi +trigonometri banyak kita temukan dalam kehidupan sehari- +sehari terutama yang bergerak di bidang ilmu astronomi yang +digunakan untuk menghitung jarak ke bintang-bintang +terdekat, navigasi satelit, geografi, teknik dan sebagainya. + + Trigonometri merupakan suatu metode dalam +perhitungan untuk menyelesaikan masalah yang berkaitan +dengan perbandingan-perbandingan pada bangun geometri, +khususnya bangun yang berbentuk segitiga. Selain itu, + + 161 | Trigonometri Pendahuluan + trigonometri bermanfaat untuk menghitung ketinggian suatu +tempat tanpa mengukur secara langsung sehingga bersifat +lebih praktis dan efesien. + + Pada bab 6 memuat materi tentang perbandingan +trigonometri, penentuan nilai perbandingan trigonometri +diberbagai kuadran, penggunaan aturan sinus dan cosinus, +rumus luas segitiga, dan identitas trigonometri + +A. PENGERTIAN TRIGONOMETRI + Trigonometri merupakan ilmu ukur segitiga atau + +pengukuran segitiga yang memperlajari sudut, dan sisi-sisi +segitiga (segitiga siku-siku). Jadi trigonometri merupakan nilai +perbandingan yang dikaitkan dengan sebuah sudut. +Perbandingan tersebut meliputi sin (sinus), cos (cosinus), tan +(tangen), cosec (cosecant), sec( secan) dan cotan (cotangent). + + Pada umumnya, ada dua ukuran untuk menyatakan +besaran sudut yaitu derajat dan radian. Tanda “0” dan “rad” +berturut –turut merupakan simbol dari derajat dan radian. + +B. SATUAN SUDUT + + Derajat + + Apabila satu lingkaran penuh dibagi + 360 bagian yang sama, maka setiap + bagian disebut satu derajat. Satu + derajat didefinisikan sebagai sudut + yang besarnya 1/360 keliling lingkaran. +Satu derajat dapat dibagi menjadi 60 bagian yang sama besar +yang disebut satu menit, dan satu menit dapat diab gi menjadi +60 bagian sama besar yang disebut detik. + +162 | Dasar Matematika +  Radian + Satu radian adalah besarnya sudut dalam lingkaran yang + panjang busur di depannya sama dengan jari-jarinya. Atau + ukuran sudut pusat yang panjang busurnya sama dengan + jari-jarinya. Apabila keliling lingkaran K dan jari-jarinya r, + maka K = 2, sehingga besar sudut satu keliling lingkaran + adalah 2 radian. Jadi konversi derajat dan radian adalah: + 2 radian = 3600 + radian = 1800 + +C. PERBANDINGAN TRIGONOMETRI + Perbandingan trigonometri pada segitiga siku-siku: + Perhatikan gambar berikut: + + 163 | Trigonometri Pendahuluan + Contoh 7.1: sebagai +Jika sin = 2 , tentukan nilai dari cos2x + tan2x ! + + 3 + +Penyelesaian: +Karena sin = 2 maka dapat digambarkan + + 3 + +berikut: + +C + + 3 +2 + +A b xB + +Berdasarkan teorema Pythagoras diperoleh: + +AB2 = BC2 – AC2 + +AB2 = 32 - 22 + +AB2 = 5 + +AB = √5 + +Akibatnya: + +Cos x = = √5 dan tan x = = 2 + 3 √5 + +Jadi cos2x + tan2x = (√5)2 + ( 2 2 = 5 + 4 = 61 + + 3 √5 ) 9 5 45 + +Contoh 7.2: +Tentukan nilai sin ∝, cos ∝ dan tan ∝ dari segitiga +dberikut: jika DE = 6 cm dan DF = 8 cm +penyelesain: + + Pandang  DEF yang salah satu sudutnya + siku-siku sehingga berlaku dalil Pythagoras + EF2 = DE2 + DF2 + EF2 = 62 + 82 = 100 + EF = √100 = 10 cm. + +Jadi, sin ∝= = 8 , cos ∝= = 6 , ∝= = 8 + 10 10 6 + +164 | Dasar Matematika + Contoh 7.3: +Perhatikan segitiga berikut: + +Tentukan panjang SR, QS dan SP! + +Penyelesaian: +QR2 = PQ2 + PR2 +QR2 = 152 + 82 +QR2 = 289 +QR = 17 + +Perhatikan ∆ : ? = = 15 dan ∆: cos? = + 17 15 + +Nilai cos ? dari ∆ = nilai cos ? dari ∆ (besar sudut + +sama besar) + +Sehingga diperoleh: + + = ⟹ 15 = + + 15 17 15 + +17. = 15.15 + + = 225 = 13 4 +17 17 + +Untuk QS  QR = QS + SR sehingga + +QS = QR – SR = 17 - 13 4 = 3 13 + 17 17 + +Untuk PS  Perhatikan : ∆ = sin? = = 8 dan + + 17 + +∆ = sin? = = + + 15 + + 165 | Trigonometri Pendahuluan + Sehingga diperoleh: =  8 = + + 17 15 + +17. = 8 15 + + = 120 = 7 1 +17 17 + +D. NILAI TRIGONOMETRI SUDUT ISTIMEWA + + Sudut istimewa pada trigonometri adalah sudut-sudut +yang besarnya 0, 30, 45, 60 dan 90 derajat. Untuk mencari nilai +sinus, cosinus dan tangen. Perhatikan gambar segitiga berikut: + +Pada segitiga I + +sin 300 = = 1; 600 = = √3 = 1 √3 + 2 2 + 2 + +cos 600 = = 1 ; 300 = = √3 = 1 √3 + 2 2 + 2 + + 300 = = 1 = 1 √3; tan 600 = = √3 = √3 + √3 3 1 + +Pada segitiga II + +sin 450 = = = 1 = 1 √2; + 2 + √2 + +cos 450 = = = 1 = 1 √2; + 2 + √2 + + 450 = = = 1 + + + + Untuk sudut 0 dan sudut 90 dari + + sinus, cosinu dan tangen, + + perhatikan gambar berikut: + + Misalkan suatu lingkaran berpusat + +166 | Dasar Matematika + di titik (0,0) dan berjari-jari r satuan. Ambil suatu titik pada + +lingkaran yaitu titik T(x,y). + +pada gambar didapat nilai sin ? = ; cos? = ; tan? = . + + +Sudut 0 terjadi jika titik T berimpit dengan sumbu x + +sehingga sin 00 = 0 = 0; cos00 = = 1 ; tan 00 = 0 = 0. + + +Sedangkan sudut siku-siku atau 900 terjadi jika titik T + +berimpit dengan sumbu y sehingga di peroleh: sin 900 = 1, + +cos 900 = 0 dan tan 900 tak terdefinisi (tidak mempunyai + +nilai. Berikut tabel sudut-sudut istimewa + + 00 300 450 600 900 + 1 1 +Sin ∝ 0 1 1 2 √3 +Cos ∝ 2 √2 0 +tan ∝ 2 1 1 + 2 √2 Tidak + 1 1 2 terdefinisi + 2 √3 1 √3 + + 0 1 + 3 √3 + +E. PERBANDINGAN TRIGONOMETRI DI BERBAGAI + KUADRAN + + Sistem kuadran pada bidang cartesius terbagi menjadi +4 bagian yang ditetapkan yaitu: Kuadran II: daerah yang +dibatasi oleh sumbu x positif dan sumbu y positif; kuadran II: +daerah yang dibatasi oleh sumbu x negatif dengan sumbu y +positif, kuadran III: daerah yang dibatasi oleh sumbu x negatif +dan sumbu y negatif, dan kaudran IV: daerah yang dibatasi +oleh sumbu x positif dan sumbu y negatif. Perbandingan +trigonometri pada kuadran dapat digambarkan sebagai +berikut: + + 167 | Trigonometri Pendahuluan + 900 + +1800 Kuadran II Kuadran I 00 + SIN + SEMUA + 3600 + + Kuadran III Kuadran IV + TAN + COS + + + 2700 + +Contoh 7.4: + +Nilai dari sin 300+cos 600 = ⋯ + 245 + +Penyelesaian: + +Ingat: sec 450 = 1 = √2 + cos 450 + +Sehingga diperoleh sin 300+cos 600 = 12+12 = 1 + 245 (√2)2 2 + +Contoh 7.5: +Sebuah tangga disandarkan pada suatu tembok. Sudut +yang dibentuk oleh tangga tersebut dengan lantai adalah +600. Jika jarak kaki tangga ke tembok adalah 6 m. +Hitunglah: +a. Panjang tangga tersebut +b. Tinggi tembok dari ujung tangga ke lantai +c. Misal sudut antara tangga dan lantai adalah ∝, + + tentukan nilai ∝ apabila panjang tangga 6√2 + +168 | Dasar Matematika + Penyelesaian: + + Perhatikan segitiga ABC yang siku-siku di A. BC adalah + panjang tangga dan AC adalah tinggi tembok. +a. Menurut perbandingan cosinus + + cos 600 = = 6 + + + + Cos 600 . BC = 6 + 1 . BC = 6 + + 2 + + = 12 m + Jadi panjang tangga adalah 12 m +b. Menurut perbandingan tangen + tan 600 = = + + 6 + + Tan 600.6 = AC + √3 .6 = AC + Jadi tinggi tembok dari ujung tangga ke lantai = 6√3 m +c. Menurut perbandingan cosinus + cos = = 6 = 1 . Jadi besar = 450 + + 6√2 √2 + + 169 | Trigonometri Pendahuluan + F. IDENTITAS TRIGONOMETRI + + Identitas terigonometri merupakan pernyataan yang +memuat kesamaan dua bentuk untuk setiap pengantian +variabelnya dengan nilai di mana bentuk tersebut +didefinisikan. Untuk membuktikan identitas trigonometri +digunakan subtitusi trigonometri dan manipulasi aljabar +dengan tujuan mengubah bentuk trigonometri menjadi lebih +sederhana. Dalam membuktikan identitas trigonometri +dengan menyelesaikan masing-masing ruas secara terpisah. +Berikut rumus identitas trigonometri: + +Contoh 7.6: +Butkikan bahwa sin cot = cos + +Penyelesaian: +sin cot = sin cos + + sin + +sin cot = cos terbukti + +Contoh 7.7: + +Buktikan bahwa tan + cos = sin (sec + cot ) + +Penyelesaian + +sin (sec + cot ) = sin sec + sin cot + + 1 cos + = sin cos + sin sin + + = tan + cos + +Terbukti bahwa tan + cos = sin (sec + cot ) + +170 | Dasar Matematika + Contoh 7.8: + +Buktikan identitas trigonometri dari 1 (12 − 1) = 1 + 2 + +Penyelesaian: + + 1 1 2 1 − 2 +2 (2 − 1) = 2 ( 2 ) + + 2 2 + = (2 ) (2) + + =1 + +Dalam membuktikan identitas trigonometri: + +1. Manipulasi ruas persamaan yang lebih rumit terlebih + +dahulu + +2. Carilah bentuk yang dapat disubtitusi dengan bentuk + +trigonometri yang ada dalam identitas trigonometri + +sehingga diperoleh bentuk sederhana + +3. Perhatikan operasi-operasi aljabar dalam + +penerapannya + +4. Jika kita tidak tahu apa yang harus dilakukan, + +ubahlah bentuk trigonometri menjadi bentuk sinus + +dan cosinus (mungkin dapat membantu dalam + +menyelesaikan identitas trigonometri) + +5. Selalu perhatikan ruas persamaan yang tidak kita + +manipulasi untuk memastikan langkah-langkah yang + +kita lakukan menunju bentuk ruas tersebut. + + 171 | Trigonometri Pendahuluan + G. ATURAN SINUS DAN COSINUS +Mencari rumus Sinus +Perhatikan gambar segitga ABC berikut: + + Misalkan ∆ adalah segitiga dengan ∠ = , ∠ = + ∠ = serta panjang BC, AC dan AB berturut-turut + adalah a, b dan c. tarik garis melalui titik C di luar garis AB + tegak lurus garis tersebut misalkan ̅̅̅̅. + sin = → = . sin diperoleh CD = b sin A ………(1) + + + + sin = → = . sin diperoleh CD = a sin B ………(2) + + + + Dari (1) dan (2) di dapat: + b sin A = a sin B  = ……………(3) + + sin sin + + Tarik garis melalui titik B diluar garis AC tegak lurus garis + tersebut, misalkan ̅̅̅̅ + sin = → = . sin diperoleh BE = c sin A ………..(4) + + + + sin = → = . sin diperoleh BE = a sin C ………..(5) + + + + Dari (4) dan (5) di dapat: + sin = sin → = ………… (6) + + sin sin + + Dari (3) dan (6) diperoleh: + = = → = = disebut rumus sinus / + + sin sin sin sin sin sin + + aturan sinus + +172 | Dasar Matematika + Mencari rumus cosinus +Perhatikan segitiga berikut: + +sin = → = sin ……… (1) + + + +cos = → = cos + + + +BD = AB – AD = c – b cos A ……… (2) +Perhatikan sudut BDC siku-siku di D, maka berlaku teorema +Pythagoras: +BC2 = BD2 + CD2 +a2 = (c – b cos A)2 + (b sin A)2 +a2 = c2 – 2bc Cos A + b2 cos2 A + b2 sin2 A +a2 = c2 – 2bc Cos A + b2 +a2 = b2 + c2 – 2bc Cos A +dengan cara yang sama, akan diperoleh rumus cosinus yang +lain yaitu: +b2 = a2 + c2 – 2ac cos B +c2 = a2 + b2 – 2bc cos C +Buktikan! + + 173 | Trigonometri Pendahuluan + Contoh 7.9: + +Diketahui segitiga ABC dengan AB = 4 cm, ∠ = 300 dan + +∠ 450. Tentukan panjang BC? + +Penyelesaian: + + Berdasarkan aturan sinus: + + = + sin 300 sin 450 + + = 4 → 1 √2. = 1.4 + 1 21√2 + 2 2 2 + + = 2√2 + + Jadi panjang BC = 2√2 cm. + +Contoh 7.10: +Diketahui segitiga ABC dengan AB = 4 cm dan AC = 2√2 +cm dan ∠ = 300. Tentukan panjang BC! +Penyelesaian: + + Berdasarkan aturan cosinus: + a2 = b2 + c2 – 2 bc cos A + a2 = (2√2)2 + 42 – 2(2√2)(4) cos + 300 + a2 = 8 + 16 - 16√2(1 √3) + + 2 + + a2 = 24 - 8√6 + + a = √24 − 8√6 = 2√6 − 2√6 cm + + jadi panjang BC = 2√6 − 2√6 cm + +Contoh 7.11 + +diketahui segitiga PQR dengan ∠ = 600, = 3 √6 dan + + 4 + + = 9 cm. Tentukan besar sudut PRQ dan RPQ! + + 4 + +Penyelesaian: + + = → 9 = 34√6 +sin 60 sin ∠ 4 sin ∠ + 12√3 + +9 . sin ∠ = 3 √6 1 √3 = 3 √18 + 4 2 8 +4 + +174 | Dasar Matematika + sin ∠ = 1 √2 = 450 + + 2 + +Jadi besar sudut PQR adalah 450 sedangkan besar sudut RPQ = +180 – (65 + 45) = 700 + +H. LUAS SEGITIGA + Luas segitiga adalah banyaknya satuan luas yang tepat + +menutupi permukaan segitiga tersebut. Rumus luas segitiga, +ada tiga cara yaitu: +1. Luas segitiga = ½ x alas x tinggi (jika alas dan tinggi pada + + alas diketahui). + +2. Luas segitiga dengan menggunakan perbandingan + trigonometri + Aturan sinus: Jika diketahui satu sudut dan diapit dua sisi + ∆ ABC = 1 a. b sin C + + 2 + + ∆ ABC = 1 a. c sin B + + 2 + + ∆ ABC = 1 b. c sin A + + 2 + + Jika diketahui satu sisi diapit dua sudut + ∆ ABC = a2 sin B sin C + + 2 sin(B+C) + + ∆ ABC = b2 sin A sin C + + 2 sin(A+C) + + ∆ ABC = c2 sin A sin B + + 2 sin(A+B) + +3. Jika diketahui tiga sisi + Luas ∆ ABC = √( − )( − )( − ) dimana = ++ + + 2 + + 175 | Trigonometri Pendahuluan + Contoh 7.12: +Diketahui segitiga ABC dengan AC = BC = 6 cm dan sudut +BAC = 1350. Tentukan luas segitiga ABC! + +Penyelesaian: +Karena diketahui satu sudut diapit dua sisi maka +digunakan aturan sinus + +Luas ∆ ABC = 1 AC. BC sin ∠BAC + + 2 + +Luas ∆ ABC = 1 . 6.6 sin 135 + + 2 + +Luas ∆ ABC = 18. 1 √2 = 9√2 + 2 + +Contoh 6.13: +Diketahui segitiga ABC dengan panjang sisi AB = 6 cm dan +besar sudut A = 300 dan sudut C = 1200. Tentukan luas +segitiga ABC! + +Penyelesaian: + +∠ = 300 + +Sehingga: + + = 2 sin sin = 62300 sin 300 = 9 = 3√3 cm + 2 sin 2 sin 1200 √3 + +176 | Dasar Matematika + I. RANGKUMAN +1. Perbandingan trigonometri pada segitiga siku-siku + + Sin α = + + + + cos = + + + + tan = + + + + = 1 + + sin + + sec = 1 + + cos + + = 1 = cos + + tan sin + +2. Identitas Trigonometri + sin2A + cos2A = 1 + tan2A - sec2A = 1 + tan = sin + + cos + + = cos + + sin + + = 1 + + sin + + sec = 1 + + cos + +3. Aturan Cosinus + a2 = b2 + c2 – 2bc Cos A + b2 = a2 + c2 – 2ac cos B + c2 = a2 + b2 – 2bc cos C + +4. Luas Segitiga + Luas segitiga dengan menggunakan perbandingan + trigonometri + + 177 | Trigonometri Pendahuluan + Aturan sinus: Jika diketahui satu sudut dan diapit dua sisi + ∆ ABC = 1 a. b sin C + + 2 + + ∆ ABC = 1 a. c sin B + + 2 + + ∆ ABC = 1 b. c sin A + + 2 + + Jika diketahui satu sisi diapit dua sudut + ∆ ABC = a2 sin B sin C + + 2 sin(B+C) + + ∆ ABC = b2 sin A sin C + + 2 sin(A+C) + + ∆ ABC = c2 sin A sin B + + 2 sin(A+B) + + Jika diketahui tiga sisi + Luas ∆ ABC = √( − )( − )( − ) dimana = ++ + + 2 + +178 | Dasar Matematika + J. LATIHAN + +1. Jika sin = 2. Tentukanlah nilai dari cos2x + tan2x! + + 3 + +2. Jika nilai dari sin = √2 dan tan = √2. Berapakah p2 + + − + + = q2? + +3. Perhatikan gambar berikut: + + Q R + + 8 cm + + 600 + + P S + + Tentukan panjang QR! + +4. Sebuah tangga yang panjangnya 2 m disandarkan ke + bagian paling atas sebuah tembok. Tangga tersebut + membentuk sudut terhadap tanah. Jika tinggi tembok + √3 m, berapakah besar sudut ? + +5. Buktikan bahwa 3sin2x – 2 cos2x = 5 sin2x – 2 + +6. Jika sin x + cos x = 1, berapakah nilai dari sin3x + cos3x + + 2 + +7. Buktikan 1−sin = 1 + 2 1+sin + +8. Buktikan bahwa 2 tan = 2 sin cos + 1+2 + +9. Jika x1 dan x2 memenuhi 12 cos2x – cos x – 1 = 0 maka + berapakah sec2x1 + sec2x2? + +10. Buktikan bahwa 2 sin cos −cos = + 1−sin +2−2 + + 179 | Trigonometri Pendahuluan + 11. Pada gambar berikut, jika PQ = 10√3, berapakah nilai PS? + R + + 300 600 + +P S + +12. Dalam ∆, jika AB = 3, AC = 4 dan ∠ = 600, + tentukanlah nilai dari tan ∠ + +13. Diketahui segitiga ABC dengan AB = 4 cm, AC = 6 cm dan + BC = 8 cm dan ∠ = . Berapakah nilai cos ? + +14. Diketahui ABCD dengan P dan Q masing-masing terletak + pada BC dan CD sehingga 5 BP = PC dan jika sudut PAQ = + . Berapakah nilai dari cos ? + +15. Buktikan identitas trigonometri dari (1 + tan2x)(1 + + cotan2x) = sec2x. cosec2x! + +180 | Dasar Matematika + DAFTAR PUSTAKA + +Alimuddin. (2012). Proses Berpikir Kreatif Mahasiswa Calon Guru + Kreatif dalam Pemecahan Masalah Matematika + Berdasarkan Gender. Disertasi Tidak diterbitkan + Surabaya: PPs. Universitas Negeri Surabaya + +Bahar. (2013). Investigasi Karakteristik Kesalahan Siswa SMK + dalam Pemecahan Soal Cerita Program Linier Ditinjau + dari Kemampuan Awal. Tesis Tidak diterbitkan. + Makassar: PPs UNM. + +Dwijono, Djoni dan Soesianto. F. (2006). Logika Matematika + untuk Ilmu Komputer. Yogyakarta: Andi Yoyakarta + +Kemendikbud. (2013). Matematika Kelas X kurikulum 2013. + Jakarta: Politeknik negeri media kreatif. + +Kemendikbud. (2014). Matematika Kelas VII semester 1 + kurikulum 2013 Edisi Revisi. Jakarta: Pusat kurikulum + dan Perbukuan, Balitban + +KBBI online ( 2012). Kamus Besar Bahasa Indonesia. + pada + [online] tersedia + + www.pusatbahasa.diknas.go.id/kbbi/ + + 181 | Daftar Pustaka + Prihandoko, Antonius Cahya. (2005). Memahami Konsep + Matematika Secara Benar dan Menyajikannya dengan + Menarik. [pdf] Departemen Pendidikan Nasional, Dirjen + Dikti. + +Ruseffendi, E.T. (1997). Materi Pokok Pendidikan Matematika 3. + Jakarta: Universitas Terbuka. + +Seputro, Thresia. (1992). Pengantar Dasar Matematika; Logika + dan Himpunan. Jakarta: Erlangga + +Siang, Jomg Jek. (2014). Logika Matematika. Yogyakarta: Andi + Ofset + +Siswanto (2013). Matematika untuk kelas X SMA dan MA Program + Wajib. Solo: Global + +Sri Handoko B dan Johannes. H (1974). Pengantar Matematika + untuk Ekonomi. Jakarta: LP3ES + +Soedjadi, R. (2000) Kiat Pendidikan Matematika di Indonesia. + Jakarta: Dirjen Dikti, Departemen Pendidikan Nasional. + +Soekisno, Aryan. R.B. (2010). Persamaan dan Pertidaksamaan + Linier. Jakarta: Reka + +Sukirman dkk. (2007). Matematika. Jakarta: Universitas Terbuka + +Purcell, E.J. dan Varberg, D. (1996). Kalkulus dan Geometri + Analitis. Jakarta: Erlangga. + +R. Johnsonbaugh, Matematika Diskrit Jilid 1, Prenhallindo, 1998 + +Ruseffendi, E.T. (1984). Dasar-dasar Matematika Modern untuk + Guru. Bandung: Tarsito. + +Dasar Matematika | 182 + Upu, Hamzah. 2004. Problem Possing dan Problem Solving + dalam Pembelajaran Matematika. Bandung: Pustaka + Ramadan. + +Yahya Yusuf, dkk. (2014). Matematika Dasar Untuk Perguruan + Tinggi. Jakarta: Ghalia Indonesia + + 183 | Daftar Pustaka + diff --git a/storage/app/books/senja.pdf b/storage/app/books/senja.pdf new file mode 100644 index 0000000..f811bc9 --- /dev/null +++ b/storage/app/books/senja.pdf @@ -0,0 +1 @@ + diff --git a/storage/app/private/.gitignore b/storage/app/private/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/app/private/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/storage/app/public/.gitignore b/storage/app/public/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/app/public/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/storage/framework/.gitignore b/storage/framework/.gitignore new file mode 100644 index 0000000..05c4471 --- /dev/null +++ b/storage/framework/.gitignore @@ -0,0 +1,9 @@ +compiled.php +config.php +down +events.scanned.php +maintenance.php +routes.php +routes.scanned.php +schedule-* +services.json diff --git a/storage/framework/cache/.gitignore b/storage/framework/cache/.gitignore new file mode 100644 index 0000000..01e4a6c --- /dev/null +++ b/storage/framework/cache/.gitignore @@ -0,0 +1,3 @@ +* +!data/ +!.gitignore diff --git a/storage/framework/cache/data/.gitignore b/storage/framework/cache/data/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/framework/cache/data/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/storage/framework/sessions/.gitignore b/storage/framework/sessions/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/framework/sessions/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/storage/framework/testing/.gitignore b/storage/framework/testing/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/framework/testing/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/storage/framework/views/.gitignore b/storage/framework/views/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/framework/views/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/storage/logs/.gitignore b/storage/logs/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/logs/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/tests/Feature/Auth/AuthenticationTest.php b/tests/Feature/Auth/AuthenticationTest.php new file mode 100644 index 0000000..a272b9d --- /dev/null +++ b/tests/Feature/Auth/AuthenticationTest.php @@ -0,0 +1,41 @@ +get('/login'); + + $response->assertStatus(200); +}); + +test('users can authenticate using the login screen', function () { + $user = User::factory()->create(); + + $response = $this->post('/login', [ + 'email' => $user->email, + 'password' => 'password', + ]); + + $this->assertAuthenticated(); + $response->assertRedirect(route('dashboard', absolute: false)); +}); + +test('users can not authenticate with invalid password', function () { + $user = User::factory()->create(); + + $this->post('/login', [ + 'email' => $user->email, + 'password' => 'wrong-password', + ]); + + $this->assertGuest(); +}); + +test('users can logout', function () { + $user = User::factory()->create(); + + $response = $this->actingAs($user)->post('/logout'); + + $this->assertGuest(); + $response->assertRedirect('/'); +}); diff --git a/tests/Feature/Auth/EmailVerificationTest.php b/tests/Feature/Auth/EmailVerificationTest.php new file mode 100644 index 0000000..f282dff --- /dev/null +++ b/tests/Feature/Auth/EmailVerificationTest.php @@ -0,0 +1,46 @@ +unverified()->create(); + + $response = $this->actingAs($user)->get('/verify-email'); + + $response->assertStatus(200); +}); + +test('email can be verified', function () { + $user = User::factory()->unverified()->create(); + + Event::fake(); + + $verificationUrl = URL::temporarySignedRoute( + 'verification.verify', + now()->addMinutes(60), + ['id' => $user->id, 'hash' => sha1($user->email)] + ); + + $response = $this->actingAs($user)->get($verificationUrl); + + Event::assertDispatched(Verified::class); + expect($user->fresh()->hasVerifiedEmail())->toBeTrue(); + $response->assertRedirect(route('dashboard', absolute: false).'?verified=1'); +}); + +test('email is not verified with invalid hash', function () { + $user = User::factory()->unverified()->create(); + + $verificationUrl = URL::temporarySignedRoute( + 'verification.verify', + now()->addMinutes(60), + ['id' => $user->id, 'hash' => sha1('wrong-email')] + ); + + $this->actingAs($user)->get($verificationUrl); + + expect($user->fresh()->hasVerifiedEmail())->toBeFalse(); +}); diff --git a/tests/Feature/Auth/PasswordConfirmationTest.php b/tests/Feature/Auth/PasswordConfirmationTest.php new file mode 100644 index 0000000..8a42902 --- /dev/null +++ b/tests/Feature/Auth/PasswordConfirmationTest.php @@ -0,0 +1,32 @@ +create(); + + $response = $this->actingAs($user)->get('/confirm-password'); + + $response->assertStatus(200); +}); + +test('password can be confirmed', function () { + $user = User::factory()->create(); + + $response = $this->actingAs($user)->post('/confirm-password', [ + 'password' => 'password', + ]); + + $response->assertRedirect(); + $response->assertSessionHasNoErrors(); +}); + +test('password is not confirmed with invalid password', function () { + $user = User::factory()->create(); + + $response = $this->actingAs($user)->post('/confirm-password', [ + 'password' => 'wrong-password', + ]); + + $response->assertSessionHasErrors(); +}); diff --git a/tests/Feature/Auth/PasswordResetTest.php b/tests/Feature/Auth/PasswordResetTest.php new file mode 100644 index 0000000..0504276 --- /dev/null +++ b/tests/Feature/Auth/PasswordResetTest.php @@ -0,0 +1,60 @@ +get('/forgot-password'); + + $response->assertStatus(200); +}); + +test('reset password link can be requested', function () { + Notification::fake(); + + $user = User::factory()->create(); + + $this->post('/forgot-password', ['email' => $user->email]); + + Notification::assertSentTo($user, ResetPassword::class); +}); + +test('reset password screen can be rendered', function () { + Notification::fake(); + + $user = User::factory()->create(); + + $this->post('/forgot-password', ['email' => $user->email]); + + Notification::assertSentTo($user, ResetPassword::class, function ($notification) { + $response = $this->get('/reset-password/'.$notification->token); + + $response->assertStatus(200); + + return true; + }); +}); + +test('password can be reset with valid token', function () { + Notification::fake(); + + $user = User::factory()->create(); + + $this->post('/forgot-password', ['email' => $user->email]); + + Notification::assertSentTo($user, ResetPassword::class, function ($notification) use ($user) { + $response = $this->post('/reset-password', [ + 'token' => $notification->token, + 'email' => $user->email, + 'password' => 'password', + 'password_confirmation' => 'password', + ]); + + $response + ->assertSessionHasNoErrors() + ->assertRedirect(route('login')); + + return true; + }); +}); diff --git a/tests/Feature/Auth/PasswordUpdateTest.php b/tests/Feature/Auth/PasswordUpdateTest.php new file mode 100644 index 0000000..e3d1278 --- /dev/null +++ b/tests/Feature/Auth/PasswordUpdateTest.php @@ -0,0 +1,40 @@ +create(); + + $response = $this + ->actingAs($user) + ->from('/profile') + ->put('/password', [ + 'current_password' => 'password', + 'password' => 'new-password', + 'password_confirmation' => 'new-password', + ]); + + $response + ->assertSessionHasNoErrors() + ->assertRedirect('/profile'); + + $this->assertTrue(Hash::check('new-password', $user->refresh()->password)); +}); + +test('correct password must be provided to update password', function () { + $user = User::factory()->create(); + + $response = $this + ->actingAs($user) + ->from('/profile') + ->put('/password', [ + 'current_password' => 'wrong-password', + 'password' => 'new-password', + 'password_confirmation' => 'new-password', + ]); + + $response + ->assertSessionHasErrorsIn('updatePassword', 'current_password') + ->assertRedirect('/profile'); +}); diff --git a/tests/Feature/Auth/RegistrationTest.php b/tests/Feature/Auth/RegistrationTest.php new file mode 100644 index 0000000..352ca78 --- /dev/null +++ b/tests/Feature/Auth/RegistrationTest.php @@ -0,0 +1,19 @@ +get('/register'); + + $response->assertStatus(200); +}); + +test('new users can register', function () { + $response = $this->post('/register', [ + 'name' => 'Test User', + 'email' => 'test@example.com', + 'password' => 'password', + 'password_confirmation' => 'password', + ]); + + $this->assertAuthenticated(); + $response->assertRedirect(route('dashboard', absolute: false)); +}); diff --git a/tests/Feature/ExampleTest.php b/tests/Feature/ExampleTest.php new file mode 100644 index 0000000..8b5843f --- /dev/null +++ b/tests/Feature/ExampleTest.php @@ -0,0 +1,7 @@ +get('/'); + + $response->assertStatus(200); +}); diff --git a/tests/Feature/ProfileTest.php b/tests/Feature/ProfileTest.php new file mode 100644 index 0000000..1536458 --- /dev/null +++ b/tests/Feature/ProfileTest.php @@ -0,0 +1,85 @@ +create(); + + $response = $this + ->actingAs($user) + ->get('/profile'); + + $response->assertOk(); +}); + +test('profile information can be updated', function () { + $user = User::factory()->create(); + + $response = $this + ->actingAs($user) + ->patch('/profile', [ + 'name' => 'Test User', + 'email' => 'test@example.com', + ]); + + $response + ->assertSessionHasNoErrors() + ->assertRedirect('/profile'); + + $user->refresh(); + + $this->assertSame('Test User', $user->name); + $this->assertSame('test@example.com', $user->email); + $this->assertNull($user->email_verified_at); +}); + +test('email verification status is unchanged when the email address is unchanged', function () { + $user = User::factory()->create(); + + $response = $this + ->actingAs($user) + ->patch('/profile', [ + 'name' => 'Test User', + 'email' => $user->email, + ]); + + $response + ->assertSessionHasNoErrors() + ->assertRedirect('/profile'); + + $this->assertNotNull($user->refresh()->email_verified_at); +}); + +test('user can delete their account', function () { + $user = User::factory()->create(); + + $response = $this + ->actingAs($user) + ->delete('/profile', [ + 'password' => 'password', + ]); + + $response + ->assertSessionHasNoErrors() + ->assertRedirect('/'); + + $this->assertGuest(); + $this->assertNull($user->fresh()); +}); + +test('correct password must be provided to delete account', function () { + $user = User::factory()->create(); + + $response = $this + ->actingAs($user) + ->from('/profile') + ->delete('/profile', [ + 'password' => 'wrong-password', + ]); + + $response + ->assertSessionHasErrorsIn('userDeletion', 'password') + ->assertRedirect('/profile'); + + $this->assertNotNull($user->fresh()); +}); diff --git a/tests/Pest.php b/tests/Pest.php new file mode 100644 index 0000000..40d096b --- /dev/null +++ b/tests/Pest.php @@ -0,0 +1,47 @@ +extend(Tests\TestCase::class) + ->use(Illuminate\Foundation\Testing\RefreshDatabase::class) + ->in('Feature'); + +/* +|-------------------------------------------------------------------------- +| Expectations +|-------------------------------------------------------------------------- +| +| When you're writing tests, you often need to check that values meet certain conditions. The +| "expect()" function gives you access to a set of "expectations" methods that you can use +| to assert different things. Of course, you may extend the Expectation API at any time. +| +*/ + +expect()->extend('toBeOne', function () { + return $this->toBe(1); +}); + +/* +|-------------------------------------------------------------------------- +| Functions +|-------------------------------------------------------------------------- +| +| While Pest is very powerful out-of-the-box, you may have some testing code specific to your +| project that you don't want to repeat in every file. Here you can also expose helpers as +| global functions to help you to reduce the number of lines of code in your test files. +| +*/ + +function something() +{ + // .. +} diff --git a/tests/TestCase.php b/tests/TestCase.php new file mode 100644 index 0000000..fe1ffc2 --- /dev/null +++ b/tests/TestCase.php @@ -0,0 +1,10 @@ +toBeTrue(); +}); diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 0000000..b963627 --- /dev/null +++ b/vite.config.js @@ -0,0 +1,11 @@ +import { defineConfig } from 'vite'; +import laravel from 'laravel-vite-plugin'; + +export default defineConfig({ + plugins: [ + laravel({ + input: ['resources/scss/app.scss', 'resources/js/app.js'], + refresh: true, + }), + ], +});