ALAMDIENG commited on
Commit
79346b2
·
1 Parent(s): f821799

docs: write comprehensive frontend and backend documentation

Browse files
Files changed (2) hide show
  1. BACKEND_DOC.md +133 -0
  2. FRONTEND_API_DOC.md +87 -257
BACKEND_DOC.md ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Aeterna AI - Backend Architecture & ML Engine Documentation (v4.0.0)
2
+
3
+ Dokumen ini menjelaskan detail teknis arsitektur sistem backend, model machine learning (Gradient Boosting & Amazon Chronos), rekayasa fitur (*feature engineering*), serta panduan kontainerisasi dan *deployment* untuk **Aeterna AI (Waste Intelligence Platform)**.
4
+
5
+ ---
6
+
7
+ ## 🏗️ 1. Desain Arsitektur Backend
8
+
9
+ Backend Aeterna AI dibangun menggunakan **FastAPI (Python)**, sebuah kerangka kerja web asinkron dengan performa tinggi yang setara dengan Node.js dan Go.
10
+
11
+ ```
12
+ +-----------------------------------------------------------------+
13
+ | FASTAPI BACKEND |
14
+ | |
15
+ | [ /api/v1/predict ] [ /api/v1/autopilot ] [ /api/v1/news ]
16
+ | | | | |
17
+ | v v | |
18
+ | +---------------+ +------------------+ | |
19
+ | | Chronos T5 | | GBR Model | | |
20
+ | | Transformer | | (GridSearchCV) | | |
21
+ | +---------------+ +------------------+ | |
22
+ | | | | |
23
+ | +------------+------------+ | |
24
+ | | | |
25
+ | v v |
26
+ | +-----------------------+ +-------------+ |
27
+ | | Feature Engineering | | News DB | |
28
+ | | - Weather (OpenMeteo) | | (JSON) | |
29
+ | | - Event Multipliers | +-------------+ |
30
+ | | - Spatial Calibration | |
31
+ | +-----------------------+ |
32
+ +-----------------------------------------------------------------+
33
+ ```
34
+
35
+ ### Komponen Utama:
36
+ 1. **Asynchronous Handling**: Memanfaatkan FastAPI dengan `run_in_threadpool` untuk menjalankan inferensi deep learning (Chronos Transformer) tanpa memblokir thread event loop utama.
37
+ 2. **CORS Security Middleware**: Dikonfigurasi secara wildcard (`*`) untuk mengizinkan aplikasi client-side (seperti dashboard Vercel) melakukan kueri asinkron lintas asal (*cross-origin*).
38
+ 3. **Automatic Swagger Docs**: Endpoint mendefinisikan tipe data masukan menggunakan model **Pydantic** yang secara otomatis membuat spesifikasi OpenAPI dan dokumentasi interaktif di `/docs`.
39
+
40
+ ---
41
+
42
+ ## 🧠 2. Mesin Machine Learning (ML Engine)
43
+
44
+ Aeterna AI mengadopsi arsitektur model hibrida:
45
+
46
+ ### A. Gradient Boosting Regressor (GBR) - Model Prediksi Harian
47
+ Model regresi teroptimasi yang memprediksi volume timbulan sampah harian tingkat kecamatan berdasarkan fitur-fitur spasial dan kontekstual.
48
+ * **Hyperparameter Terbaik (GridSearchCV)**:
49
+ * `n_estimators` (Jumlah pohon keputusan): **100**
50
+ * `learning_rate` (Laju pembelajaran): **0.03**
51
+ * `max_depth` (Kedalaman pohon maksimal): **3**
52
+ * `subsample` (Rasio sampel acak per pohon): **0.9**
53
+ * **Metrik Evaluasi Model**:
54
+ * **Mean Absolute Error (MAE)**: `132.29 Ton` (Rata-rata kesalahan tebakan sekitar 132 ton).
55
+ * **Root Mean Squared Error (RMSE)**: `165.46 Ton` (Tebakan stabil tanpa kesalahan ekstrem).
56
+ * **R-Squared ($R^2$ Score)**: `81.51%` (81.5% pola data berhasil dijelaskan oleh fitur).
57
+ * **Mean Absolute Percentage Error (MAPE)**: **`1.59%`** (Tingkat persentase kesalahan di bawah 2%, masuk kategori *Highly Accurate Forecasting*).
58
+
59
+ ### B. Amazon Chronos-T5 (Tiny) - Model Deret Waktu (Time-Series)
60
+ Model Transformer terlatih dari Amazon yang digunakan untuk memprediksi tren masa depan 7 s.d. 30 hari ke depan pada kueri simulasi. Chronos membaca barisan data historis dan melakukan peramalan probabilistik (diambil kuantil median `0.5`).
61
+
62
+ ---
63
+
64
+ ## 🌦️ 3. Rekayasa Fitur Dinamis (Feature Engineering)
65
+
66
+ AI mengalibrasi prediksi mentah berdasarkan faktor riil eksternal:
67
+
68
+ ### A. Multiplier Curah Hujan (Rainfall Multiplier)
69
+ Sampah terbuka di Tempat Penampungan Sementara (TPS) menyerap air hujan, yang meningkatkan berat massa jenis sampah basah.
70
+ * Sistem memanggil **Open-Meteo API** secara dinamis menggunakan titik koordinat presisi dari kecamatan target.
71
+ * **Multiplier Formula**:
72
+ $$\text{Volume}_{\text{calibrated}} = \text{Volume}_{\text{pred}} \times \left(1.0 + \frac{\text{Precipitation (mm)}}{1000} \right)$$
73
+ *Curah hujan lebat (misal 50 mm) akan menambah berat jenis timbulan sekitar 5%.*
74
+
75
+ ### B. Multiplier Skala Keramaian & Event (Event Multiplier)
76
+ Jadwal acara besar Jakarta (`event_jakarta_2026.txt`) dipindai secara berkala berdasarkan tanggal kueri.
77
+ * Jika ada event aktif, sistem mendeteksi nama acara dan skala keramaian (1 s.d. 5).
78
+ * **Skala Multiplier**:
79
+ * Skala 1 s.d. 2 (Keramaian lokal): **+10% s.d. +15%** volume sampah.
80
+ * Skala 3 s.d. 4 (Keramaian regional, misal BTN Marathon): **+20% s.d. +25%** volume sampah.
81
+ * Skala 5 (Keramaian masif, misal Idul Fitri): **+30% s.d. +35%** volume sampah.
82
+
83
+ ---
84
+
85
+ ## ⏰ 4. Timezone-Aware Engine (WIB / Asia/Jakarta)
86
+
87
+ Agar hasil prediksi antara server lokal pengembang dan server Hugging Face (yang biasanya berlokasi di Amerika Serikat) sinkron 100%, backend Aeterna AI dilengkapi dengan pengunci zona waktu WIB (UTC+7):
88
+
89
+ ```python
90
+ from datetime import datetime, timezone, timedelta
91
+
92
+ def get_jakarta_now() -> datetime:
93
+ # Memaksa system time menggunakan Waktu Indonesia Barat (WIB)
94
+ return datetime.now(timezone(timedelta(hours=7)))
95
+ ```
96
+ Semua query default, pencocokan kalender event, serta umpan berita menggunakan `get_jakarta_now()` untuk mencegah pergeseran penanggalan akibat perbedaan lokasi server fisik.
97
+
98
+ ---
99
+
100
+ ## 🐳 5. Panduan Kontainerisasi & Deployment (Hugging Face Spaces)
101
+
102
+ Aplikasi dideploy ke **Hugging Face Spaces** menggunakan **Docker**.
103
+
104
+ ### Berkas Dockerfile:
105
+ ```dockerfile
106
+ FROM python:3.11-slim
107
+
108
+ # System setup
109
+ WORKDIR /code
110
+ RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*
111
+
112
+ # Install dependencies
113
+ COPY requirements.txt .
114
+ RUN pip install --no-cache-dir -r requirements.txt
115
+
116
+ # Copy application files
117
+ COPY . .
118
+
119
+ # Expose port (Hugging Face standard port)
120
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
121
+ ```
122
+
123
+ ### Langkah Deployment ke Hugging Face:
124
+ 1. Buat Space baru di Hugging Face, pilih SDK **Docker** (Blank template).
125
+ 2. Tambahkan remote git Hugging Face ke repositori lokal Anda:
126
+ ```bash
127
+ git remote add huggingface https://huggingface.co/spaces/USERNAME/SPACE_NAME
128
+ ```
129
+ 3. Dorong perubahan langsung ke Space:
130
+ ```bash
131
+ git push huggingface main
132
+ ```
133
+ 4. Hugging Face akan mendeteksi `Dockerfile`, membangun *image*, dan menyalakan API pada port `7860` secara otomatis.
FRONTEND_API_DOC.md CHANGED
@@ -1,289 +1,119 @@
1
- # Aeterna AI - Front-End API Integration Guide (v4.0.0)
2
 
3
- Dokumen ini ditujukan bagi tim Front-End untuk mengintegrasikan antarmuka pengguna dengan backend **Aeterna AI (Waste Intelligence Platform)**.
4
 
5
  ---
6
 
7
- ## 📡 Konfigurasi Global
8
- * **Base URL (Local)**: `http://localhost:8001`
9
- * **Content-Type**: `application/json`
10
- * **CORS**: Diaktifkan secara wildcard (`*`) untuk semua origin, method, dan header.
11
 
12
- ---
13
-
14
- ## 🗺️ Konstanta Wilayah (44 Kecamatan DKI Jakarta)
15
- Untuk memetakan wilayah pada leaflet/map atau drop-down pilihan di FE, gunakan konstanta koordinat dan baseline berikut:
16
-
17
- ```typescript
18
- export interface RegionMetadata {
19
- latitude: number;
20
- longitude: number;
21
- normal_avg: number;
22
- warning_threshold: number;
23
- critical_threshold: number;
24
- city: 'Jakarta Pusat' | 'Jakarta Utara' | 'Jakarta Barat' | 'Jakarta Selatan' | 'Jakarta Timur' | 'Kepulauan Seribu';
25
- }
26
-
27
- export const KECAMATAN_DATABASE: Record<string, RegionMetadata> = {
28
- // JAKARTA PUSAT
29
- "Menteng": { latitude: -6.1950, longitude: 106.8322, normal_avg: 120.0, warning_threshold: 160.0, critical_threshold: 180.0, city: "Jakarta Pusat" },
30
- "Senen": { latitude: -6.1822, longitude: 106.8452, normal_avg: 180.0, warning_threshold: 220.0, critical_threshold: 240.0, city: "Jakarta Pusat" },
31
- "Cempaka Putih": { latitude: -6.1802, longitude: 106.8686, normal_avg: 90.0, warning_threshold: 120.0, critical_threshold: 140.0, city: "Jakarta Pusat" },
32
- "Johar Baru": { latitude: -6.1866, longitude: 106.8572, normal_avg: 70.0, warning_threshold: 95.0, critical_threshold: 110.0, city: "Jakarta Pusat" },
33
- "Kemayoran": { latitude: -6.1628, longitude: 106.8438, normal_avg: 180.0, warning_threshold: 220.0, critical_threshold: 240.0, city: "Jakarta Pusat" },
34
- "Sawah Besar": { latitude: -6.1554, longitude: 106.8322, normal_avg: 110.0, warning_threshold: 145.0, critical_threshold: 165.0, city: "Jakarta Pusat" },
35
- "Tanah Abang": { latitude: -6.2104, longitude: 106.8122, normal_avg: 250.0, warning_threshold: 320.0, critical_threshold: 350.0, city: "Jakarta Pusat" },
36
- "Gambir": { latitude: -6.1764, longitude: 106.8190, normal_avg: 150.0, warning_threshold: 195.0, critical_threshold: 215.0, city: "Jakarta Pusat" },
37
-
38
- // JAKARTA UTARA
39
- "Penjaringan": { latitude: -6.1264, longitude: 106.7822, normal_avg: 280.0, warning_threshold: 350.0, critical_threshold: 380.0, city: "Jakarta Utara" },
40
- "Tanjung Priok": { latitude: -6.1322, longitude: 106.8722, normal_avg: 260.0, warning_threshold: 320.0, critical_threshold: 350.0, city: "Jakarta Utara" },
41
- "Koja": { latitude: -6.1214, longitude: 106.9133, normal_avg: 190.0, warning_threshold: 240.0, critical_threshold: 270.0, city: "Jakarta Utara" },
42
- "Cilincing": { latitude: -6.1288, longitude: 106.9452, normal_avg: 290.0, warning_threshold: 370.0, critical_threshold: 400.0, city: "Jakarta Utara" },
43
- "Pademangan": { latitude: -6.1328, longitude: 106.8422, normal_avg: 140.0, warning_threshold: 180.0, critical_threshold: 200.0, city: "Jakarta Utara" },
44
- "Kelapa Gading": { latitude: -6.1552, longitude: 106.9022, normal_avg: 190.0, warning_threshold: 240.0, critical_threshold: 270.0, city: "Jakarta Utara" },
45
-
46
- // JAKARTA BARAT
47
- "Cengkareng": { latitude: -6.1528, longitude: 106.7322, normal_avg: 340.0, warning_threshold: 420.0, critical_threshold: 460.0, city: "Jakarta Barat" },
48
- "Grogol Petamburan": { latitude: -6.1622, longitude: 106.7882, normal_avg: 220.0, warning_threshold: 280.0, critical_threshold: 310.0, city: "Jakarta Barat" },
49
- "Kalideres": { latitude: -6.1428, longitude: 106.7022, normal_avg: 260.0, warning_threshold: 330.0, critical_threshold: 360.0, city: "Jakarta Barat" },
50
- "Kebon Jeruk": { latitude: -6.1922, longitude: 106.7722, normal_avg: 210.0, warning_threshold: 260.0, critical_threshold: 290.0, city: "Jakarta Barat" },
51
- "Kembangan": { latitude: -6.1828, longitude: 106.7382, normal_avg: 180.0, warning_threshold: 230.0, critical_threshold: 250.0, city: "Jakarta Barat" },
52
- "Palmerah": { latitude: -6.2028, longitude: 106.7882, normal_avg: 160.0, warning_threshold: 200.0, critical_threshold: 220.0, city: "Jakarta Barat" },
53
- "Taman Sari": { latitude: -6.1454, longitude: 106.8182, normal_avg: 100.0, warning_threshold: 130.0, critical_threshold: 150.0, city: "Jakarta Barat" },
54
- "Tambora": { latitude: -6.1500, longitude: 106.8000, normal_avg: 80.0, warning_threshold: 110.0, critical_threshold: 125.0, city: "Jakarta Barat" },
55
 
56
- // JAKARTA SELATAN
57
- "Cilandak": { latitude: -6.2928, longitude: 106.7922, normal_avg: 180.0, warning_threshold: 230.0, critical_threshold: 250.0, city: "Jakarta Selatan" },
58
- "Jagakarsa": { latitude: -6.3328, longitude: 106.8222, normal_avg: 220.0, warning_threshold: 280.0, critical_threshold: 310.0, city: "Jakarta Selatan" },
59
- "Kebayoran Baru": { latitude: -6.2422, longitude: 106.7982, normal_avg: 210.0, warning_threshold: 260.0, critical_threshold: 290.0, city: "Jakarta Selatan" },
60
- "Kebayoran Lama": { latitude: -6.2488, longitude: 106.7722, normal_avg: 230.0, warning_threshold: 290.0, critical_threshold: 320.0, city: "Jakarta Selatan" },
61
- "Mampang Prapatan": { latitude: -6.2522, longitude: 106.8182, normal_avg: 120.0, warning_threshold: 150.0, critical_threshold: 170.0, city: "Jakarta Selatan" },
62
- "Pancoran": { latitude: -6.2622, longitude: 106.8382, normal_avg: 130.0, warning_threshold: 160.0, critical_threshold: 180.0, city: "Jakarta Selatan" },
63
- "Pasar Minggu": { latitude: -6.2828, longitude: 106.8438, normal_avg: 240.0, warning_threshold: 300.0, critical_threshold: 330.0, city: "Jakarta Selatan" },
64
- "Pesanggrahan": { latitude: -6.2588, longitude: 106.7588, normal_avg: 160.0, warning_threshold: 200.0, critical_threshold: 220.0, city: "Jakarta Selatan" },
65
- "Setiabudi": { latitude: -6.2228, longitude: 106.8282, normal_avg: 190.0, warning_threshold: 240.0, critical_threshold: 270.0, city: "Jakarta Selatan" },
66
- "Tebet": { latitude: -6.2288, longitude: 106.8482, normal_avg: 170.0, warning_threshold: 210.0, critical_threshold: 230.0, city: "Jakarta Selatan" },
67
-
68
- // JAKARTA TIMUR
69
- "Cakung": { latitude: -6.1828, longitude: 106.9482, normal_avg: 350.0, warning_threshold: 430.0, critical_threshold: 470.0, city: "Jakarta Timur" },
70
- "Cipayung": { latitude: -6.3128, longitude: 106.9022, normal_avg: 140.0, warning_threshold: 180.0, critical_threshold: 200.0, city: "Jakarta Timur" },
71
- "Ciracas": { latitude: -6.3228, longitude: 106.8782, normal_avg: 190.0, warning_threshold: 240.0, critical_threshold: 270.0, city: "Jakarta Timur" },
72
- "Duren Sawit": { latitude: -6.2228, longitude: 106.9282, normal_avg: 300.0, warning_threshold: 370.0, critical_threshold: 410.0, city: "Jakarta Timur" },
73
- "Jatinegara": { latitude: -6.2222, longitude: 106.8682, normal_avg: 240.0, warning_threshold: 300.0, critical_threshold: 330.0, city: "Jakarta Timur" },
74
- "Kramat Jati": { latitude: -6.2722, longitude: 106.8682, normal_avg: 220.0, warning_threshold: 270.0, critical_threshold: 300.0, city: "Jakarta Timur" },
75
- "Makasar": { latitude: -6.2622, longitude: 106.8782, normal_avg: 160.0, warning_threshold: 200.0, critical_threshold: 220.0, city: "Jakarta Timur" },
76
- "Matraman": { latitude: -6.2022, longitude: 106.8582, normal_avg: 130.0, warning_threshold: 160.0, critical_threshold: 180.0, city: "Jakarta Timur" },
77
- "Pasar Rebo": { latitude: -6.3122, longitude: 106.8522, normal_avg: 150.0, warning_threshold: 190.0, critical_threshold: 210.0, city: "Jakarta Timur" },
78
- "Pulo Gadung": { latitude: -6.1922, longitude: 106.8922, normal_avg: 220.0, warning_threshold: 270.0, critical_threshold: 300.0, city: "Jakarta Timur" },
79
-
80
- // KEPULAUAN SERIBU
81
- "Kepulauan Seribu Utara": { latitude: -5.5722, longitude: 106.5522, normal_avg: 11.0, warning_threshold: 15.0, critical_threshold: 18.0, city: "Kepulauan Seribu" },
82
- "Kepulauan Seribu Selatan": { latitude: -5.7722, longitude: 106.6522, normal_avg: 9.0, warning_threshold: 12.0, critical_threshold: 15.0, city: "Kepulauan Seribu" }
83
- };
84
  ```
 
85
 
86
  ---
87
 
88
- ## 🔌 Referensi API Endpoint
89
-
90
- ### 1. Mengambil Berita Ter-crawled Harian
91
- Endpoint ini menyajikan database berita seputar persampahan DKI Jakarta yang diperbarui berkala setiap 1 jam.
92
-
93
- * **URL**: `/api/v1/news`
94
- * **Method**: `GET`
95
- * **Headers**: `Accept: application/json`
96
- * **Response Schema (`200 OK`)**:
97
- ```json
98
- [
99
- {
100
- "title": "DKI Uji Coba Penarikan Retribusi Sampah Pelayanan Kebersihan Harian",
101
- "source": "Antara News",
102
- "url": "https://www.antaranews.com/tag/sampah-jakarta",
103
- "date_fetched": "2026-07-10",
104
- "summary": "Pemprov DKI Jakarta merencanakan uji coba penarikan retribusi pelayanan kebersihan/sampah berdasarkan golongan daya listrik..."
105
- }
106
- ]
107
- ```
108
-
109
- ---
110
-
111
- ### 2. Prediksi AI Otonom (Autopilot Mode)
112
- Mengambil prediksi otonom untuk ke-44 kecamatan sekaligus untuk hari ini. Berguna untuk dashboard autopilot utama.
113
 
114
- * **URL**: `/api/v1/autopilot`
115
- * **Method**: `GET`
116
- * **Response Schema (`200 OK`)**:
117
- ```json
118
- {
119
- "status": "success",
120
- "date": "2026-07-10",
121
- "total_volume_ton": 8105.42,
122
- "total_trucks": 1640,
123
- "top_kecamatan": [
124
- {
125
- "location": "Cakung",
126
- "volume_ton": 355.20,
127
- "trucks": 72,
128
- "status": "SAFE",
129
- "city": "Jakarta Timur"
130
- }
131
- ],
132
- "rainy_regions": 0,
133
- "event_today": null
134
- }
135
- ```
136
 
137
- ---
138
-
139
- ### 3. Simulasi Prediksi Wilayah (Predictor Tool)
140
- Melakukan peramalan timbulan sampah untuk kecamatan tertentu dengan parameter simulasi cuaca/event keramaian.
 
141
 
142
- * **URL**: `/api/v1/predict`
143
- * **Method**: `POST`
144
- * **Request Body**:
145
- ```typescript
146
- interface PredictionRequest {
147
- forecast_days: number; // Ambang batas: 1 - 30 hari
148
- rainfall_mm: number; // Curah hujan override (0.0 = Auto Open-Meteo)
149
- event_scale: number; // 0 (none) sampai 5 (massive crowd)
150
- location: string; // Salah satu nama dari 44 kecamatan
151
- granularity: 'daily' | 'hourly';
152
- model_type: 'chronos' | 'gradient_boosting';
153
- }
154
- ```
155
- * **Contoh Request Payload**:
156
- ```json
157
- {
158
- "forecast_days": 7,
159
- "rainfall_mm": 0.0,
160
- "event_scale": 0,
161
- "location": "Menteng",
162
- "granularity": "daily",
163
- "model_type": "gradient_boosting"
164
- }
165
- ```
166
- * **Response Schema (`200 OK`)**:
167
- ```json
168
- {
169
- "status": "success",
170
- "message": "Normal conditions.",
171
- "confidence_score": 0.9828,
172
- "data": {
173
- "prediction_results": [
174
- {
175
- "date": "2026-07-10",
176
- "location": "Menteng",
177
- "total_volume_ton": 120.54,
178
- "organic_waste_ton": 60.11,
179
- "plastic_waste_ton": 27.66,
180
- "paper_waste_ton": 13.86,
181
- "glass_waste_ton": 3.86,
182
- "metal_waste_ton": 2.53,
183
- "textile_waste_ton": 5.06,
184
- "other_waste_ton": 7.46,
185
- "recommended_trucks": 25,
186
- "risk_status": "SAFE",
187
- "event_info": null,
188
- "hourly_breakdown": null
189
- }
190
- ],
191
- "logistics_plan": {
192
- "trucks_needed": 25,
193
- "manpower": 75,
194
- "estimated_duration_hours": 24.1,
195
- "efficiency_rate": "85% (Optimal)"
196
- }
197
- }
198
- }
199
- ```
200
 
201
  ---
202
 
203
- ### 4. Unduh Berkas CSV Prediksi
204
- Mengunduh berkas tabel data hasil simulasi prediksi.
205
 
206
- * **URL**: `/api/v1/predict/csv`
207
- * **Method**: `POST`
208
- * **Request Body**: Sama dengan request `/api/v1/predict`
209
- * **Response**: Binary Blob (`text/csv` stream file).
210
 
211
- ---
212
-
213
- ### 5. Mengambil Peringatan Operasional Dinamis (Alerts)
214
- Mendapatkan peringatan kritis wilayah yang volumenya melebihi ambang batas warning/critical.
 
 
 
215
 
216
- * **URL**: `/api/v1/alerts`
217
- * **Method**: `GET`
218
- * **Query Parameters**: `location` (opsional, untuk menyaring satu kecamatan)
219
- * **Response Schema (`200 OK`)**:
220
- ```json
221
- {
222
- "status": "success",
223
- "alert_count": 2,
224
- "alerts": [
225
- {
226
- "date": "2026-07-10",
227
- "location": "Cakung",
228
- "status": "WARNING",
229
- "estimated_volume_ton": 435.0,
230
- "message": "Alert: WARNING volume expected at Cakung"
231
- }
232
- ],
233
- "last_updated": "2026-07-10T20:52:00.123456"
234
- }
235
- ```
236
 
237
  ---
238
 
239
- ## ⚡ Contoh Integrasi Frontend (Axios / JavaScript)
240
 
241
- Berikut adalah contoh cara menarik data prediksi Autopilot dan memuatnya ke komponen halaman FE Anda:
242
 
243
  ```javascript
244
- import axios from 'axios';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
 
246
- const BACKEND_URL = 'http://localhost:8001';
247
 
248
- // 1. Memuat Umpan Berita AI
249
- export async function getWasteNews() {
250
- try {
251
- const res = await axios.get(`${BACKEND_URL}/api/v1/news`);
252
- return res.data; // Mengembalikan array berita
253
- } catch (error) {
254
- console.error("Gagal menarik berita sampah:", error);
255
- return [];
256
- }
257
- }
258
 
259
- // 2. Memuat Data Autopilot Otonom DKI
260
- export async function getAutopilotData() {
261
- try {
262
- const res = await axios.get(`${BACKEND_URL}/api/v1/autopilot`);
263
- return res.data;
264
- } catch (error) {
265
- console.error("Gagal memuat autopilot data:", error);
266
- return null;
267
- }
268
  }
269
 
270
- // 3. Menjalankan Prediksi Manual (Simulation)
271
- export async function postSimulationPrediction(kecamatan, hari = 7, model = 'gradient_boosting') {
272
- const payload = {
273
- forecast_days: hari,
274
- rainfall_mm: 0.0, // Auto
275
- event_scale: 0,
276
- location: kecamatan,
277
- granularity: hari <= 7 ? 'hourly' : 'daily',
278
- model_type: model
279
- };
280
-
281
- try {
282
- const res = await axios.post(`${BACKEND_URL}/api/v1/predict`, payload);
283
- return res.data;
284
- } catch (error) {
285
- console.error("Gagal melakukan prediksi simulasi:", error);
286
- throw error;
287
- }
288
  }
289
  ```
 
 
 
 
1
+ # Aeterna AI - Front-End API Integration & UI Development Guide (v4.0.0)
2
 
3
+ Dokumen ini ditujukan sebagai panduan bagi developer Front-End (FE) untuk mengintegrasikan antarmuka pengguna dengan backend **Aeterna AI (Waste Intelligence Platform)**, menjelaskan konfigurasi perutean, Leaflet map, interaktivitas, dan visualisasi chart.
4
 
5
  ---
6
 
7
+ ## 📡 1. Konfigurasi Dynamic Routing & Vercel Compatibility
 
 
 
8
 
9
+ Untuk memastikan frontend dapat dipublikasikan secara terpisah di **Vercel** dan berkomunikasi secara aman dengan API backend di **Hugging Face Spaces**, perutean URL disetel secara dinamis di `frontend/app.js`:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
+ ```javascript
12
+ // Deteksi otomatis domain client untuk perutean API
13
+ const API_BASE_URL = window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1"
14
+ ? "" // Menggunakan path relatif jika berjalan di lokal (localhost)
15
+ : "https://alamdieng-waste-prediction-api.hf.space"; // Mengarah langsung ke API Hugging Face jika di-host di Vercel
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  ```
17
+ Semua pemanggilan AJAX `fetch()` harus menggunakan template literal `${API_BASE_URL}` (contoh: `fetch(`${API_BASE_URL}/api/v1/news`)`).
18
 
19
  ---
20
 
21
+ ## 🗺️ 2. Integrasi Leaflet Map & Custom Markers
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
+ Peta interaktif menggunakan **Leaflet.js** untuk memvisualisasikan timbulan sampah di 44 kecamatan:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
+ ### A. Pengelompokan Kelas Risiko Spasial
26
+ Tiap penanda (marker) kecamatan di peta memiliki kelas CSS dinamis berdasarkan tingkat bahayanya:
27
+ * `.safe`: Warna hijau (`--green`), menyala redup.
28
+ * `.warning`: Warna kuning (`--yellow`), berdenyut sedang.
29
+ * `.critical`: Warna merah (`--red`), berdenyut kencang.
30
 
31
+ ### B. Route Drawing & Haversine Formula
32
+ Ketika penanda kecamatan diklik, rute pengiriman logistik langsung digambar ke **TPST Bantargebang** (`[-6.3477, 106.9939]`):
33
+ ```javascript
34
+ // polyline digambar putus-putus berwarna cyan bercahaya
35
+ routeLine = L.polyline([startCoords, BANTARGEBANG_COORDS], {
36
+ color: '#00F0FF',
37
+ weight: 3.5,
38
+ opacity: 0.75,
39
+ dashArray: '8, 8',
40
+ className: 'glowing-route'
41
+ }).addTo(map);
42
+ ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
 
44
  ---
45
 
46
+ ## 🖱️ 3. Interaktivitas Cyber HUD & Custom Cursor
 
47
 
48
+ UI terinspirasi dari `floodzy.id` menggunakan kursor delay kustom di desktop:
 
 
 
49
 
50
+ ### A. Animasi Kursor Lerp (Linear Interpolation)
51
+ Kursor dibagi menjadi dua bagian: titik tengah (`#cursor-dot`) dan cincin luar (`#cursor-ring`). Cincin luar bergerak mengikuti kursor dengan sedikit delay menggunakan rumus interpolasi lerp:
52
+ ```javascript
53
+ // Lerp formula untuk pergerakan cincin kursor yang smooth
54
+ ringX += (mouseX - ringX) * 0.15;
55
+ ringY += (mouseY - ringY) * 0.15;
56
+ ```
57
 
58
+ ### B. Hover State
59
+ Saat kursor melintasi elemen interaktif (tombol, tautan berita, baris alert), kelas `.hover-state` diterapkan ke cincin luar untuk memperbesar ukurannya dan memancarkan bias cahaya cyan:
60
+ ```javascript
61
+ document.querySelectorAll("a, button, select, input, .alert-row").forEach(el => {
62
+ el.addEventListener("mouseenter", () => cursorRing.classList.add("hover-state"));
63
+ el.addEventListener("mouseleave", () => cursorRing.classList.remove("hover-state"));
64
+ });
65
+ ```
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
  ---
68
 
69
+ ## 🚨 4. Aliran Navigasi Interaktif (Clickable Alerts & Autopilot)
70
 
71
+ Semua baris peringatan di tab **REGIONAL ALERTS** dan daftar **Top 5 High-Risk** di halaman Autopilot dikonfigurasi agar dapat diklik oleh pengguna untuk berpindah halaman dan menampilkan detail secara otomatis:
72
 
73
  ```javascript
74
+ row.addEventListener("click", () => {
75
+ // 1. Pilih kecamatan target di dropdown
76
+ selectedLocation = item.location;
77
+ if (locationSelect) locationSelect.value = item.location;
78
+
79
+ // 2. Geser dan fokuskan peta ke kecamatan target
80
+ updateActiveMapMarker(item.location);
81
+ panToLocation(item.location);
82
+ fetchLiveWeather(item.location);
83
+
84
+ // 3. Pindah tab navigasi ke menu "SIMULATION TOOL"
85
+ switchPage("page-predictor");
86
+
87
+ // 4. Jalankan inferensi AI secara instan setelah tab terbuka
88
+ setTimeout(() => {
89
+ runPrediction();
90
+ }, 500);
91
+ });
92
+ ```
93
+
94
+ ---
95
 
96
+ ## 📊 5. Format Data Tipe Komposisi & Truk Sampah
97
 
98
+ Timbulan sampah total dipecah menjadi 6 kategori persentase untuk divisualisasikan dalam bentuk progress bar neon di UI:
 
 
 
 
 
 
 
 
 
99
 
100
+ ```typescript
101
+ interface WasteCompositionBreakdown {
102
+ organic_waste_ton: number; // ~50.2% (Sisa Makanan)
103
+ plastic_waste_ton: number; // ~22.8% (Plastik)
104
+ paper_waste_ton: number; // ~11.5% (Kertas)
105
+ glass_waste_ton: number; // ~3.2% (Kaca)
106
+ textile_waste_ton: number; // ~4.2% (Tekstil)
107
+ metal_waste_ton: number; // ~8.1% (Logam/Lainnya)
 
108
  }
109
 
110
+ interface LogisticsPlan {
111
+ trucks_needed: number; // Total timbulan / 5 Ton kapasitas truk
112
+ manpower: number; // Jumlah truk * 4 crew (1 sopir + 3 petugas)
113
+ estimated_duration_hours: number; // Jarak rute / 28 km/jam kecepatan truk
114
+ efficiency_rate: string; // Status efisiensi rute pengangkutan
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  }
116
  ```
117
+ Untuk memperbarui lebar grafik bar di HTML, hitung persentase dinamis:
118
+ $$\text{Width (\%)} = \left( \frac{\text{Kategori Ton}}{\text{Total Timbulan Ton}} \right) \times 100$$
119
+ Lalu masukkan nilainya ke CSS `style.width` masing-masing baris.