345 lines
11 KiB
Markdown
345 lines
11 KiB
Markdown
# Ringkasan Fitur Prediksi Harga Cabai Jember
|
|
|
|
Dokumen ini merangkum fitur yang terdeteksi pada seluruh proyek `PrediksiHargaCabe`, terutama folder `api` dan `website`.
|
|
|
|
## 1. Gambaran Umum
|
|
|
|
Proyek terdiri dari dua bagian utama:
|
|
|
|
- **Backend `api`**: REST API berbasis Flask untuk membaca data harga, memuat model LSTM tersimpan, menghasilkan prediksi, serta menyediakan data untuk peta.
|
|
- **Frontend `website`**: aplikasi React + Vite untuk menampilkan peta pasar, harga aktual, prediksi, riwayat harga, dan indikator tren.
|
|
|
|
Walaupun beberapa instruksi atau dokumentasi lama menyebut FastAPI, implementasi backend yang aktif saat ini menggunakan **Flask**. Entry point-nya adalah `api/main.py` dan aplikasi dibuat melalui `app.create_app()`.
|
|
|
|
## 2. Fitur Backend
|
|
|
|
### 2.1 Status API
|
|
|
|
- `GET /`
|
|
- Mengecek bahwa API aktif.
|
|
- Mengembalikan pesan status dalam bahasa Indonesia.
|
|
- `GET /api/v1/health`
|
|
- Menampilkan status kesehatan API.
|
|
- Menampilkan jumlah model yang berhasil dimuat.
|
|
- Menampilkan daftar model yang berhasil dimuat per komoditas.
|
|
- Menampilkan daftar artefak model yang dilewati beserta alasannya.
|
|
|
|
### 2.2 Informasi Komoditas dan Pasar
|
|
|
|
- `GET /api/v1/commodities`
|
|
- Mengembalikan komoditas yang memiliki model tersedia.
|
|
- Menyertakan nama komoditas dan jumlah pasar yang tersedia.
|
|
- `GET /api/v1/markets`
|
|
- Mengembalikan lima pasar di Kabupaten Jember beserta koordinatnya.
|
|
- Dapat difilter dengan query `commodity`.
|
|
- Menandai komoditas yang tersedia untuk setiap pasar.
|
|
|
|
Komoditas yang didefinisikan backend:
|
|
|
|
| Slug | Nama |
|
|
|---|---|
|
|
| `rawit` | Cabai Rawit |
|
|
| `merah` | Cabai Merah Besar |
|
|
| `keriting` | Cabai Merah Keriting |
|
|
|
|
Pasar yang didefinisikan backend:
|
|
|
|
- Pasar Tanjung
|
|
- Pasar Kreongan
|
|
- Pasar Tegal Besar
|
|
- Pasar Mangli
|
|
- Pasar Wirolegi
|
|
|
|
### 2.3 Riwayat Harga
|
|
|
|
- `GET /api/v1/history?commodity={komoditas}&market={pasar}&days={jumlah_hari}`
|
|
- Mengambil riwayat harga dari CSV.
|
|
- Nilai `days` default-nya 90 hari dan dibatasi antara 1 sampai 365 hari.
|
|
- Data tanggal diurutkan dan data tanggal duplikat menggunakan nilai terakhir.
|
|
- Nilai kosong atau tidak valid diproses sebagai data yang tidak tersedia.
|
|
- Nilai nol diperlakukan sebagai data kosong, lalu nilai kosong di tengah rangkaian dapat diinterpolasi secara linear hingga dua titik.
|
|
- Nilai harga dikonversi menggunakan `PRICE_UNIT_SCALE`, default `1000`.
|
|
|
|
### 2.4 Prediksi Multi-Langkah
|
|
|
|
- `GET /api/v1/predict?commodity={komoditas}&market={pasar}&horizon={hari}`
|
|
- Horizon yang tersedia secara default: 1, 7, 24, dan 30 hari.
|
|
- Prediksi menggunakan pendekatan **recursive multi-step forecasting**.
|
|
- Hasil prediksi mencakup:
|
|
- harga aktual terakhir;
|
|
- tanggal prediksi;
|
|
- harga setiap langkah;
|
|
- perubahan harga dalam rupiah;
|
|
- perubahan persentase;
|
|
- harga minimum, maksimum, dan rata-rata;
|
|
- tren `up`, `down`, atau `flat`;
|
|
- umur data;
|
|
- peringatan data lama atau prediksi di luar rentang training;
|
|
- metadata metode dan `time_step`.
|
|
- Hasil prediksi disimpan dalam cache berdasarkan komoditas, pasar, dan tanggal data terakhir.
|
|
|
|
### 2.5 Prediksi untuk Peta
|
|
|
|
- `GET /api/v1/predict/map?commodity={komoditas}&horizon={hari}`
|
|
- Menghasilkan ringkasan prediksi untuk seluruh pasar.
|
|
- Setiap lokasi dapat berisi:
|
|
- koordinat pasar;
|
|
- ketersediaan model;
|
|
- harga aktual terakhir;
|
|
- harga prediksi;
|
|
- perubahan harga;
|
|
- persentase perubahan;
|
|
- arah tren.
|
|
- Jika model atau data suatu pasar tidak tersedia, lokasi tetap dikembalikan dengan status tidak tersedia dan alasan kegagalan.
|
|
|
|
### 2.6 Pemuatan Model dan Scaler
|
|
|
|
- Model dan scaler dimuat ketika aplikasi dibuat melalui `ModelRegistry`.
|
|
- Model Keras dimuat menggunakan `compile=False`.
|
|
- Scaler dimuat menggunakan `joblib`, dengan fallback ke `pickle`.
|
|
- Setiap konfigurasi model dapat menentukan nama file model dan scaler melalui `config.json`.
|
|
- Path artefak divalidasi agar tidak keluar dari folder pasar.
|
|
- Model yang tidak lengkap atau gagal dimuat dilewati dan dicatat pada informasi health.
|
|
- API tidak melakukan training atau `model.fit()` ketika melayani prediksi.
|
|
|
|
Artefak yang tersedia:
|
|
|
|
- **Cabai Rawit**: model untuk lima pasar.
|
|
- **Cabai Merah Besar**: model untuk lima pasar.
|
|
- **Cabai Merah Keriting**: model untuk Pasar Kreongan, Pasar Mangli, dan Pasar Wirolegi.
|
|
- Setiap kombinasi model menggunakan file model Keras `.h5`, scaler `.pkl`, dan konfigurasi `.json` jika lengkap.
|
|
|
|
### 2.7 Validasi dan Error Handling
|
|
|
|
Backend memiliki format error terstruktur:
|
|
|
|
```json
|
|
{
|
|
"error": {
|
|
"code": "ERROR_CODE",
|
|
"message": "Pesan kesalahan",
|
|
"details": {}
|
|
}
|
|
}
|
|
```
|
|
|
|
Validasi yang tersedia meliputi:
|
|
|
|
- komoditas tidak dikenal;
|
|
- pasar tidak dikenal;
|
|
- model tidak tersedia;
|
|
- parameter query wajib;
|
|
- horizon tidak valid;
|
|
- jumlah data historis tidak mencukupi;
|
|
- file CSV tidak ditemukan;
|
|
- kolom tanggal atau kolom pasar tidak ditemukan;
|
|
- kesalahan internal server.
|
|
|
|
### 2.8 CORS dan Konfigurasi
|
|
|
|
Konfigurasi backend dapat diubah melalui environment variable:
|
|
|
|
- `MODELS_DIR`: lokasi folder model;
|
|
- `DATA_DIR`: lokasi CSV;
|
|
- `PRICE_UNIT_SCALE`: skala harga, default `1000`;
|
|
- `ALLOWED_HORIZONS`: daftar horizon yang dipisahkan koma, default `1,3,7`;
|
|
- `MAX_HORIZON`: batas horizon maksimum, default `7`;
|
|
- `CORS_ORIGINS`: origin frontend yang diizinkan;
|
|
- `STALE_DATA_DAYS`: ambang data dianggap lama;
|
|
- `TREND_THRESHOLD_PCT`: ambang perubahan untuk menentukan tren.
|
|
|
|
Nilai default `CORS_ORIGINS` saat ini adalah `*` untuk kemudahan pengembangan. Untuk deployment produksi, sebaiknya diisi dengan daftar origin frontend yang spesifik.
|
|
|
|
## 3. Fitur Frontend
|
|
|
|
### 3.1 Dashboard Publik
|
|
|
|
Frontend menampilkan dashboard bernama **Panen Harga** dengan fokus pada harga cabai Kabupaten Jember.
|
|
|
|
Fitur dashboard:
|
|
|
|
- indikator koneksi API;
|
|
- pilihan komoditas;
|
|
- pilihan horizon 1, 7, 24, atau 30 hari;
|
|
- pencarian pasar;
|
|
- notifikasi kesalahan dan tombol coba lagi;
|
|
- tampilan tanggal data terakhir;
|
|
- tata letak responsif untuk layar desktop dan mobile.
|
|
|
|
### 3.2 Peta Interaktif
|
|
|
|
- Menggunakan React Leaflet dan OpenStreetMap.
|
|
- Menampilkan marker untuk lokasi pasar.
|
|
- Marker dapat dipilih untuk membuka detail lokasi.
|
|
- Peta otomatis memusatkan tampilan ke pasar yang dipilih.
|
|
- Marker dibedakan berdasarkan status terpilih dan ketersediaan model/data.
|
|
- Popup marker menampilkan nama pasar dan prediksi harga.
|
|
- Daftar pasar di samping peta dapat digunakan sebagai alternatif pemilihan lokasi.
|
|
|
|
### 3.3 Panel Detail Pasar
|
|
|
|
Untuk pasar yang dipilih, frontend menampilkan:
|
|
|
|
- nama pasar;
|
|
- koordinat;
|
|
- komoditas;
|
|
- indikator tren naik, turun, atau datar;
|
|
- prediksi pada horizon yang dipilih;
|
|
- harga aktual terakhir;
|
|
- tanggal data terakhir;
|
|
- tabel prediksi per langkah;
|
|
- perubahan harga per langkah;
|
|
- peringatan jika data sudah lama atau prediksi berada di luar rentang training.
|
|
|
|
Untuk horizon lebih dari tujuh hari, tabel visual menampilkan tujuh langkah pertama dan mengarahkan pengguna ke endpoint API untuk data lengkap.
|
|
|
|
### 3.4 Riwayat Harga
|
|
|
|
- Menampilkan ringkasan harga aktual terbaru.
|
|
- Menampilkan riwayat 30 hari untuk pasar yang dipilih.
|
|
- Menggunakan visualisasi sparkline sederhana berbasis elemen HTML/CSS.
|
|
- Menampilkan tanggal awal dan tanggal akhir riwayat.
|
|
|
|
### 3.5 State dan Loading UI
|
|
|
|
Frontend memiliki state untuk:
|
|
|
|
- daftar komoditas;
|
|
- daftar pasar;
|
|
- prediksi peta;
|
|
- pasar terpilih;
|
|
- horizon;
|
|
- pencarian pasar;
|
|
- detail prediksi;
|
|
- riwayat harga;
|
|
- status loading;
|
|
- status error;
|
|
- filter mobile.
|
|
|
|
Tersedia tampilan loading saat menghubungkan ke API dan tampilan kosong ketika data API belum tersedia.
|
|
|
|
## 4. Alur Integrasi Frontend dan Backend
|
|
|
|
1. Frontend memanggil `/commodities` dan `/markets` ketika halaman dibuka.
|
|
2. Frontend memanggil `/predict/map` ketika komoditas atau horizon berubah.
|
|
3. Frontend memanggil `/predict` dan `/history` ketika pasar, komoditas, atau horizon berubah.
|
|
4. Respons API dipetakan ke marker, daftar pasar, panel detail, dan riwayat harga.
|
|
5. Error dari backend dibaca dari format `error.message` dan ditampilkan kepada pengguna.
|
|
|
|
Base URL frontend dapat diubah dengan:
|
|
|
|
```powershell
|
|
$env:VITE_API_BASE_URL="http://127.0.0.1:8000/api/v1"
|
|
```
|
|
|
|
Jika environment variable tersebut tidak diatur, frontend menggunakan default:
|
|
|
|
```text
|
|
http://127.0.0.1:8000/api/v1
|
|
```
|
|
|
|
## 5. Data dan Model
|
|
|
|
Data input yang ditemukan di backend:
|
|
|
|
- CSV Cabai Rawit;
|
|
- CSV Cabai Merah Keriting;
|
|
- CSV Cabai Merah Besar.
|
|
|
|
Data tersebut digunakan oleh `CsvPriceRepository`, bukan database relasional.
|
|
|
|
Folder model tersimpan di `api/models` dan dikelompokkan berdasarkan komoditas lalu pasar. Model di-load dari file yang dirujuk oleh `config.json`; nama file tidak ditebak secara bebas ketika konfigurasi tersedia.
|
|
|
|
## 6. Pengujian
|
|
|
|
Backend memiliki pengujian untuk:
|
|
|
|
- proses recursive forecasting;
|
|
- perlindungan agar hasil prediksi tidak negatif;
|
|
- pemuatan registry dengan artefak tidak lengkap;
|
|
- kontrak endpoint health;
|
|
- validasi komoditas;
|
|
- validasi horizon;
|
|
- format error API.
|
|
|
|
Perintah pengujian:
|
|
|
|
```powershell
|
|
cd api
|
|
pytest
|
|
```
|
|
|
|
Perintah menjalankan backend:
|
|
|
|
```powershell
|
|
cd api
|
|
python main.py
|
|
```
|
|
|
|
Atau dengan Flask CLI:
|
|
|
|
```powershell
|
|
cd api
|
|
flask --app main:app run --host 127.0.0.1 --port 8000
|
|
```
|
|
|
|
Perintah menjalankan frontend:
|
|
|
|
```powershell
|
|
cd website
|
|
npm install
|
|
npm run dev -- --host 127.0.0.1
|
|
```
|
|
|
|
Perintah build dan lint frontend:
|
|
|
|
```powershell
|
|
cd website
|
|
npm run build
|
|
npm run lint
|
|
```
|
|
|
|
## 7. Struktur File Penting
|
|
|
|
```text
|
|
api/
|
|
├── main.py
|
|
├── requirements.txt
|
|
├── app/
|
|
│ ├── __init__.py
|
|
│ ├── config.py
|
|
│ ├── errors.py
|
|
│ ├── api/
|
|
│ │ ├── routes.py
|
|
│ │ └── schemas.py
|
|
│ ├── data/
|
|
│ │ ├── markets.json
|
|
│ │ └── repository.py
|
|
│ └── services/
|
|
│ ├── forecaster.py
|
|
│ ├── model_registry.py
|
|
│ └── prediction_service.py
|
|
├── models/
|
|
└── tests/
|
|
|
|
website/
|
|
├── package.json
|
|
├── vite.config.js
|
|
├── index.html
|
|
└── src/
|
|
├── App.jsx
|
|
├── main.jsx
|
|
├── services/api.js
|
|
├── data/mockData.js
|
|
├── Public.css
|
|
└── assets/
|
|
```
|
|
|
|
## 8. Catatan Implementasi Saat Ini
|
|
|
|
- Backend aktual adalah Flask dengan prefix API `/api/v1`.
|
|
- Dokumentasi `website/README.md` masih menyebut fase mock data dan integrasi backend belum dilakukan, tetapi kode `website/src/services/api.js` dan `website/src/App.jsx` saat ini sudah memanggil API backend secara langsung.
|
|
- `website/src/data/mockData.js` masih tersimpan sebagai data contoh/warisan, tetapi bukan sumber data utama pada alur dashboard saat ini.
|
|
- Folder `node_modules`, cache Python, dan `website/dist` merupakan dependensi atau hasil build; folder tersebut tidak dianggap sebagai fitur aplikasi inti.
|
|
- Halaman publik yang aktif pada implementasi saat ini adalah satu dashboard React. Rute hash seperti `#/home`, `#/map`, `#/about`, dan `#/admin` yang tertulis di README belum terlihat di komponen `App.jsx`.
|