File size: 18,446 Bytes
b81a86b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
"""
Generator sample data CSV untuk 38 kabupaten/kota Jawa Timur.

Data sources:
    - Kode wilayah & nama: Permendagri 137/2017
    - IPM 2024: BPS Jatim (https://jatim.bps.go.id/)
                ringkasan: jatimtimes.com & manadopost berdasarkan Berita Resmi Statistik
    - Koordinat: Approximate kabupaten/kota center (lat/lon)
    - Population 2024: BPS Jawa Timur Dalam Angka 2025
    - 8 Kota IHK: PIHPS Bank Indonesia (https://www.bi.go.id/hargapangan/)

Catatan: Beberapa IPM di proposal v7/v8 (e.g., Sampang 61.6) berasal dari
data tahun lebih lawas. v9 pakai IPM 2024 BPS. Tim wajib refresh tahunan
saat BPS publish data baru (biasanya November-Desember).
"""

import csv
import os
import sys

# Force UTF-8 stdout di Windows (default cp1252 crash di "βœ“").
if sys.platform == "win32":
    try:
        sys.stdout.reconfigure(encoding="utf-8")
    except (AttributeError, OSError):
        pass

OUTPUT_DIR = os.path.dirname(os.path.abspath(__file__))


# =============================================================================
# 38 Kabupaten/Kota Jawa Timur β€” Master Data
# =============================================================================
# Kolom: kab_id, nama, latitude, longitude, ipm_2024, population_2024, tier
# Tier: TIER_1_HIGH untuk 8 kota IHK, TIER_2_MEDIUM untuk sisanya
# IPM mengikuti sumber BPS 2024 (atau estimasi konservatif jika tidak tersedia)

KABUPATEN_DATA = [
    # ===== TIER 1 β€” 8 Kota IHK Jatim =====
    ("3578", "Kota Surabaya",      -7.2575, 112.7521, 84.69, 2949496, "TIER_1_HIGH"),
    ("3573", "Kota Malang",        -7.9666, 112.6326, 84.68,  844614, "TIER_1_HIGH"),
    ("3571", "Kota Kediri",        -7.8166, 112.0114, 81.48,  287609, "TIER_1_HIGH"),
    ("3577", "Kota Madiun",        -7.6298, 111.5300, 81.67,  178540, "TIER_1_HIGH"),
    ("3574", "Kota Probolinggo",   -7.7543, 113.2159, 79.20,  239649, "TIER_1_HIGH"),
    ("3510", "Banyuwangi",         -8.2192, 114.3691, 73.45, 1719287, "TIER_1_HIGH"),
    ("3529", "Sumenep",            -7.0067, 113.8525, 68.79, 1144719, "TIER_1_HIGH"),
    ("3509", "Jember",             -8.1727, 113.7000, 71.86, 2606656, "TIER_1_HIGH"),

    # ===== TIER 2 β€” 30 Kabupaten Non-IHK =====
    ("3501", "Pacitan",            -8.1985, 111.1014, 71.40,  592786, "TIER_2_MEDIUM"),
    ("3502", "Ponorogo",           -7.8674, 111.4625, 73.20,  956000, "TIER_2_MEDIUM"),
    ("3503", "Trenggalek",         -8.0497, 111.7100, 73.85,  733700, "TIER_2_MEDIUM"),
    ("3504", "Tulungagung",        -8.0658, 111.9028, 75.30, 1077500, "TIER_2_MEDIUM"),
    ("3505", "Blitar",             -8.0950, 112.1658, 73.85, 1213000, "TIER_2_MEDIUM"),
    ("3506", "Kediri",             -7.7960, 112.1700, 74.50, 1626100, "TIER_2_MEDIUM"),
    ("3507", "Malang",             -8.1706, 112.5290, 75.50, 2716000, "TIER_2_MEDIUM"),
    ("3508", "Lumajang",           -8.1336, 113.2245, 70.10, 1129500, "TIER_2_MEDIUM"),
    ("3511", "Bondowoso",          -7.9134, 113.8217, 69.62,  790180, "TIER_2_MEDIUM"),
    ("3512", "Situbondo",          -7.7068, 114.0093, 71.20,  690600, "TIER_2_MEDIUM"),
    ("3513", "Probolinggo",        -7.8742, 113.4675, 69.40, 1208400, "TIER_2_MEDIUM"),
    ("3514", "Pasuruan",           -7.7460, 112.9237, 71.30, 1683700, "TIER_2_MEDIUM"),
    ("3515", "Sidoarjo",           -7.4549, 112.7178, 80.13, 2185300, "TIER_2_MEDIUM"),
    ("3516", "Mojokerto",          -7.4720, 112.4390, 76.50, 1175000, "TIER_2_MEDIUM"),
    ("3517", "Jombang",            -7.5460, 112.2308, 75.10, 1357300, "TIER_2_MEDIUM"),
    ("3518", "Nganjuk",            -7.6050, 111.9023, 75.20, 1075800, "TIER_2_MEDIUM"),
    ("3519", "Madiun",             -7.5570, 111.6890, 73.55,  743200, "TIER_2_MEDIUM"),
    ("3520", "Magetan",            -7.6515, 111.3287, 75.80,  679000, "TIER_2_MEDIUM"),
    ("3521", "Ngawi",              -7.4080, 111.4458, 74.40,  889600, "TIER_2_MEDIUM"),
    ("3522", "Bojonegoro",         -7.1500, 111.8800, 73.10, 1357000, "TIER_2_MEDIUM"),
    ("3523", "Tuban",              -6.8970, 111.9750, 74.30, 1218000, "TIER_2_MEDIUM"),
    ("3524", "Lamongan",           -7.1155, 112.4170, 75.60, 1378200, "TIER_2_MEDIUM"),
    ("3525", "Gresik",             -7.1568, 112.6510, 77.61, 1330000, "TIER_2_MEDIUM"),
    ("3526", "Bangkalan",          -7.0317, 112.7491, 67.70, 1062200, "TIER_2_MEDIUM"),
    ("3527", "Sampang",            -7.1924, 113.2473, 66.72,  984000, "TIER_2_MEDIUM"),
    ("3528", "Pamekasan",          -7.1565, 113.4785, 70.43,  892800, "TIER_2_MEDIUM"),
    ("3572", "Kota Blitar",        -8.0980, 112.1681, 80.20,  148800, "TIER_2_MEDIUM"),
    ("3575", "Kota Pasuruan",      -7.6469, 112.9070, 79.50,  211800, "TIER_2_MEDIUM"),
    ("3576", "Kota Mojokerto",     -7.4719, 112.4341, 80.85,  146100, "TIER_2_MEDIUM"),
    ("3579", "Kota Batu",          -7.8740, 112.5240, 78.30,  213700, "TIER_2_MEDIUM"),
]

assert len(KABUPATEN_DATA) == 38, f"Expected 38 kab, got {len(KABUPATEN_DATA)}"


# =============================================================================
# 19 Komoditas Bapanas + spec konstrain
# =============================================================================
# Kolom: code, nama, max_distance_km, min_viable_tons, max_fresh_age_days,
#        baseline_price_idr_per_kg

KOMODITAS_DATA = [
    ("cabai_merah",    "Cabai Merah Besar",            200, 1.0,   5,  45000),
    ("cabai_rawit",    "Cabai Rawit Merah",            200, 1.0,   5,  60000),
    ("bawang_merah",   "Bawang Merah",                 400, 2.0,  30,  35000),
    ("bawang_putih",   "Bawang Putih (Bonggol)",       600, 2.0,  60,  40000),
    ("tomat",          "Tomat Sayur",                  150, 1.0,   7,  12000),
    ("kentang",        "Kentang",                      400, 2.0,  21,  14000),
    ("kol",            "Kol/Kubis",                    300, 2.0,  14,   8000),
    ("wortel",         "Wortel",                       300, 2.0,  14,  11000),
    ("beras_premium",  "Beras Premium",                800, 5.0, 180,  15500),
    ("beras_medium",   "Beras Medium",                 800, 5.0, 180,  13000),
    ("jagung",         "Jagung Pipilan Kering",        600, 5.0, 120,   6000),
    ("kedelai",        "Kedelai Lokal",                600, 3.0, 120,  11000),
    ("telur_ayam",     "Telur Ayam Ras",               300, 1.0,  21,  29000),
    ("daging_ayam",    "Daging Ayam Ras",              200, 0.5,   3,  37000),
    ("daging_sapi",    "Daging Sapi Murni",            200, 0.5,   3, 138000),
    ("gula_pasir",     "Gula Pasir Lokal",             600, 3.0, 365,  18000),
    ("minyak_goreng",  "Minyak Goreng Curah",          600, 3.0, 180,  16500),
    ("ikan_segar",     "Ikan Segar (Bandeng/Tongkol)", 150, 0.5,   2,  35000),
    ("tepung_terigu",  "Tepung Terigu",                600, 3.0, 180,  13000),
]

assert len(KOMODITAS_DATA) == 19, f"Expected 19 komoditas, got {len(KOMODITAS_DATA)}"


# =============================================================================
# Sample Surplus / Deficit per kabupaten (realistic seasonal pattern)
# =============================================================================
# Pattern berbasis observasi pasar Jatim April 2026:
#   - Kediri, Tulungagung, Blitar: sentra cabai (surplus)
#   - Probolinggo, Pasuruan, Lumajang: sentra bawang (surplus)
#   - Madura (Bangkalan/Sampang/Pamekasan/Sumenep): sentra bawang (surplus)
#   - Banyuwangi, Jember: sentra hortikultura mixed
#   - Tuban, Lamongan, Bojonegoro, Ngawi: sentra padi (surplus beras)
#   - Surabaya, Sidoarjo, Gresik, Malang Kota: pasar besar (deficit)
#   - Pacitan, Trenggalek: relatif kecil, mostly subsisten
#
# Format: (kab_id, commodity_code, role, volume_tons, price_idr_per_kg, harvest_age_days)
# role: "SURPLUS" atau "DEFICIT"

SURPLUS_DEFICIT_DATA = [
    # ===== Cabai merah =====
    # Sentra cabai Jatim
    ("3506", "cabai_merah", "SURPLUS",  85.0, 38000, 2),  # Kab Kediri
    ("3504", "cabai_merah", "SURPLUS",  60.0, 39000, 1),  # Tulungagung
    ("3505", "cabai_merah", "SURPLUS",  45.0, 40000, 2),  # Kab Blitar
    ("3503", "cabai_merah", "SURPLUS",  20.0, 41000, 1),  # Trenggalek
    ("3508", "cabai_merah", "SURPLUS",  15.0, 42000, 2),  # Lumajang
    # Pasar besar (deficit)
    ("3578", "cabai_merah", "DEFICIT",  80.0, 65000, 0),  # Surabaya
    ("3515", "cabai_merah", "DEFICIT",  35.0, 62000, 0),  # Sidoarjo
    ("3525", "cabai_merah", "DEFICIT",  30.0, 60000, 0),  # Gresik
    ("3573", "cabai_merah", "DEFICIT",  25.0, 58000, 0),  # Kota Malang
    # Skenario A3: Sampang surplus mini, demand jauh
    ("3527", "cabai_merah", "SURPLUS",   2.0, 42000, 3),  # Sampang (mini)

    # ===== Cabai rawit =====
    ("3506", "cabai_rawit", "SURPLUS",  40.0, 52000, 2),  # Kab Kediri
    ("3504", "cabai_rawit", "SURPLUS",  30.0, 53000, 1),  # Tulungagung
    ("3508", "cabai_rawit", "SURPLUS",  25.0, 54000, 2),  # Lumajang
    ("3578", "cabai_rawit", "DEFICIT",  60.0, 75000, 0),  # Surabaya
    ("3573", "cabai_rawit", "DEFICIT",  20.0, 72000, 0),  # Kota Malang

    # ===== Bawang merah =====
    # Sentra Probolinggo / Pasuruan / Madura
    ("3513", "bawang_merah", "SURPLUS", 120.0, 28000, 5),  # Kab Probolinggo
    ("3514", "bawang_merah", "SURPLUS",  80.0, 29000, 6),  # Kab Pasuruan
    ("3526", "bawang_merah", "SURPLUS",  40.0, 30000, 4),  # Bangkalan (cluster Madura)
    ("3527", "bawang_merah", "SURPLUS",  35.0, 30000, 3),  # Sampang   (cluster Madura)
    ("3528", "bawang_merah", "SURPLUS",  45.0, 29500, 5),  # Pamekasan (cluster Madura)
    ("3529", "bawang_merah", "SURPLUS",  60.0, 29000, 6),  # Sumenep   (cluster Madura)
    ("3578", "bawang_merah", "DEFICIT", 150.0, 42000, 0),  # Surabaya
    ("3515", "bawang_merah", "DEFICIT",  60.0, 40000, 0),  # Sidoarjo
    ("3573", "bawang_merah", "DEFICIT",  35.0, 41000, 0),  # Kota Malang
    ("3525", "bawang_merah", "DEFICIT",  40.0, 39000, 0),  # Gresik

    # ===== Tomat =====
    ("3507", "tomat", "SURPLUS", 50.0, 8000, 2),   # Kab Malang (Pujon-Batu area)
    ("3579", "tomat", "SURPLUS", 30.0, 8500, 1),   # Kota Batu
    ("3505", "tomat", "SURPLUS", 25.0, 9000, 2),   # Kab Blitar
    ("3578", "tomat", "DEFICIT", 60.0, 14000, 0),  # Surabaya
    ("3525", "tomat", "DEFICIT", 25.0, 13500, 0),  # Gresik

    # ===== Kentang =====
    ("3507", "kentang", "SURPLUS", 35.0, 10000, 5),  # Kab Malang
    ("3579", "kentang", "SURPLUS", 25.0, 10500, 4),  # Kota Batu
    ("3578", "kentang", "DEFICIT", 45.0, 16000, 0),  # Surabaya
    ("3573", "kentang", "DEFICIT", 15.0, 15000, 0),  # Kota Malang

    # ===== Kol =====
    ("3579", "kol",    "SURPLUS", 40.0, 5500, 3),   # Kota Batu
    ("3507", "kol",    "SURPLUS", 30.0, 5800, 4),   # Kab Malang
    ("3578", "kol",    "DEFICIT", 50.0, 9500, 0),   # Surabaya

    # ===== Wortel =====
    ("3579", "wortel", "SURPLUS", 28.0, 8000, 3),   # Kota Batu
    ("3507", "wortel", "SURPLUS", 22.0, 8200, 4),   # Kab Malang
    ("3578", "wortel", "DEFICIT", 35.0, 12500, 0),  # Surabaya

    # ===== Beras premium =====
    ("3523", "beras_premium", "SURPLUS", 850.0, 14500, 30),  # Tuban
    ("3524", "beras_premium", "SURPLUS", 700.0, 14600, 25),  # Lamongan
    ("3522", "beras_premium", "SURPLUS", 650.0, 14400, 35),  # Bojonegoro
    ("3521", "beras_premium", "SURPLUS", 500.0, 14300, 28),  # Ngawi
    ("3578", "beras_premium", "DEFICIT", 800.0, 17000,  0),  # Surabaya
    ("3525", "beras_premium", "DEFICIT", 350.0, 16800,  0),  # Gresik
    ("3515", "beras_premium", "DEFICIT", 400.0, 16500,  0),  # Sidoarjo

    # ===== Beras medium (Bulog priority candidate) =====
    ("3519", "beras_medium",  "SURPLUS", 1200.0, 12500, 20), # Madiun (Bulog priority)
    ("3520", "beras_medium",  "SURPLUS",  800.0, 12600, 22), # Magetan
    ("3521", "beras_medium",  "SURPLUS",  900.0, 12400, 25), # Ngawi
    ("3578", "beras_medium",  "DEFICIT", 1000.0, 14500,  0), # Surabaya

    # ===== Jagung =====
    ("3522", "jagung", "SURPLUS", 800.0, 5500, 15),  # Bojonegoro
    ("3521", "jagung", "SURPLUS", 600.0, 5400, 18),  # Ngawi
    ("3502", "jagung", "SURPLUS", 400.0, 5600, 20),  # Ponorogo
    ("3578", "jagung", "DEFICIT", 700.0, 7200,  0),  # Surabaya (industri pakan)
    ("3525", "jagung", "DEFICIT", 400.0, 7000,  0),  # Gresik

    # ===== Telur ayam =====
    ("3505", "telur_ayam", "SURPLUS", 80.0, 26000, 1),   # Kab Blitar (sentra)
    ("3506", "telur_ayam", "SURPLUS", 50.0, 26500, 2),   # Kab Kediri
    ("3578", "telur_ayam", "DEFICIT", 90.0, 32000, 0),   # Surabaya
    ("3573", "telur_ayam", "DEFICIT", 25.0, 30500, 0),   # Kota Malang

    # ===== Daging ayam =====
    ("3505", "daging_ayam", "SURPLUS", 30.0, 32000, 1),  # Kab Blitar
    ("3506", "daging_ayam", "SURPLUS", 20.0, 33000, 1),  # Kab Kediri
    ("3578", "daging_ayam", "DEFICIT", 40.0, 40000, 0),  # Surabaya

    # ===== Ikan segar =====
    ("3525", "ikan_segar", "SURPLUS", 25.0, 28000, 1),   # Gresik (pesisir)
    ("3525", "ikan_segar", "SURPLUS", 20.0, 30000, 1),   # Lamongan
    ("3573", "ikan_segar", "DEFICIT", 15.0, 38000, 0),   # Kota Malang
    ("3577", "ikan_segar", "DEFICIT",  8.0, 36000, 0),   # Kota Madiun (pegunungan)

    # ===== Deficits di kab IPM rendah (demonstrate equity multiplier v9) =====
    # Threshold v9: <68β†’1.30 | <72β†’1.15 | <78β†’1.05 | β‰₯78β†’1.00 (kalibrasi BPS 2024)
    # Madura tidak produksi padi β†’ impor beras
    ("3527", "beras_premium", "DEFICIT", 200.0, 16500, 0),   # Sampang IPM 66.72 β†’ +30%
    ("3526", "beras_premium", "DEFICIT", 250.0, 16400, 0),   # Bangkalan IPM 67.70 β†’ +30%
    ("3528", "beras_medium",  "DEFICIT", 180.0, 14000, 0),   # Pamekasan IPM 70.43 β†’ +15%
    # Bondowoso pegunungan β†’ defisit ikan & sayur
    ("3511", "ikan_segar", "DEFICIT",  6.0, 38000, 0),   # Bondowoso IPM 69.62 β†’ +15%
    ("3511", "tomat",      "DEFICIT", 12.0, 13500, 0),   # Bondowoso β†’ +15%
    # Sumenep (Tier 1 IHK tapi IPM rendah β†’ equity boost +15%)
    ("3529", "cabai_merah", "DEFICIT", 8.0, 60000, 0),   # Sumenep IPM 68.79 β†’ +15%
]


# =============================================================================
# Weather forecast sample untuk sebagian rute (BMKG-style)
# =============================================================================
# Skenario D1 Banjir Rute: hujan deras di rute Kediri β†’ Surabaya (April monsoon)
# Format: origin_kab_id, dest_kab_id, max_rain_mm, transit_window_days, source

WEATHER_DATA = [
    # Hujan deras di rute Kediri-Surabaya (skenario D1)
    ("3506", "3578", 75.0, 1, "BMKG"),   # Kab Kediri β†’ Surabaya
    ("3571", "3578", 70.0, 1, "BMKG"),   # Kota Kediri β†’ Surabaya
    # Rute Madura cerah
    ("3527", "3578", 5.0, 1, "BMKG"),    # Sampang β†’ Surabaya
    ("3526", "3578", 8.0, 1, "BMKG"),    # Bangkalan β†’ Surabaya
    # Rute pegunungan moderate
    ("3507", "3578", 25.0, 1, "BMKG"),   # Kab Malang β†’ Surabaya
    ("3579", "3578", 30.0, 1, "BMKG"),   # Kota Batu β†’ Surabaya
    # Rute Probolinggo cerah
    ("3513", "3578", 10.0, 1, "BMKG"),   # Probolinggo β†’ Surabaya
    ("3514", "3578", 12.0, 1, "BMKG"),   # Pasuruan β†’ Surabaya
    # Rute Lumbung Padi (default cerah)
    ("3523", "3578",  8.0, 1, "BMKG"),   # Tuban β†’ Surabaya
    ("3524", "3578",  6.0, 1, "BMKG"),   # Lamongan β†’ Surabaya
]


# =============================================================================
# Historical price stats untuk anomaly detection (skenario D3)
# =============================================================================
# 30-day rolling median + std per komoditas. Kalau current price > 3Οƒ β†’ outlier.
# Format: commodity_code, median_idr_per_kg, std_idr_per_kg

HISTORICAL_PRICE_STATS = [
    ("cabai_merah",    45000, 8000),
    ("cabai_rawit",    60000, 12000),
    ("bawang_merah",   35000, 5000),
    ("bawang_putih",   40000, 6000),
    ("tomat",          12000, 2500),
    ("kentang",        14000, 2000),
    ("kol",             8000, 1500),
    ("wortel",         11000, 2000),
    ("beras_premium",  15500, 1500),
    ("beras_medium",   13000, 1200),
    ("jagung",          6000,  800),
    ("kedelai",        11000, 1500),
    ("telur_ayam",     29000, 3500),
    ("daging_ayam",    37000, 4500),
    ("daging_sapi",   138000,12000),
    ("gula_pasir",     18000, 1500),
    ("minyak_goreng",  16500, 2000),
    ("ikan_segar",     35000, 5000),
    ("tepung_terigu",  13000, 1200),
]


# =============================================================================
# WRITE CSV FILES
# =============================================================================

def write_csv(filename, header, rows):
    path = os.path.join(OUTPUT_DIR, filename)
    with open(path, "w", newline="", encoding="utf-8") as f:
        w = csv.writer(f)
        w.writerow(header)
        w.writerows(rows)
    print(f"  βœ“ {filename} ({len(rows)} rows)")


def main():
    print("Generating AgriFlow sample data CSVs...")

    write_csv(
        "kabupaten_jatim.csv",
        ["kab_id", "nama", "latitude", "longitude", "ipm_2024",
         "population_2024", "tier"],
        KABUPATEN_DATA,
    )
    write_csv(
        "komoditas_constraints.csv",
        ["code", "nama", "max_distance_km", "min_viable_tons",
         "max_fresh_age_days", "baseline_price_idr_per_kg"],
        KOMODITAS_DATA,
    )
    write_csv(
        "surplus_deficit.csv",
        ["kab_id", "commodity_code", "role", "volume_tons",
         "price_idr_per_kg", "harvest_age_days"],
        SURPLUS_DEFICIT_DATA,
    )
    write_csv(
        "weather_forecast.csv",
        ["origin_kab_id", "dest_kab_id", "max_rain_mm",
         "transit_window_days", "source"],
        WEATHER_DATA,
    )
    write_csv(
        "historical_price_stats.csv",
        ["commodity_code", "median_idr_per_kg", "std_idr_per_kg"],
        HISTORICAL_PRICE_STATS,
    )

    # Summary
    n_surplus = sum(1 for r in SURPLUS_DEFICIT_DATA if r[2] == "SURPLUS")
    n_deficit = sum(1 for r in SURPLUS_DEFICIT_DATA if r[2] == "DEFICIT")
    print(f"\nSummary:")
    print(f"  - {len(KABUPATEN_DATA)} kabupaten/kota")
    print(f"    - Tier 1 (HIGH):  {sum(1 for r in KABUPATEN_DATA if r[6] == 'TIER_1_HIGH')}")
    print(f"    - Tier 2 (MEDIUM): {sum(1 for r in KABUPATEN_DATA if r[6] == 'TIER_2_MEDIUM')}")
    print(f"  - {len(KOMODITAS_DATA)} komoditas")
    print(f"  - {n_surplus} surplus + {n_deficit} deficit nodes "
          f"({len(SURPLUS_DEFICIT_DATA)} total)")
    print(f"  - {len(WEATHER_DATA)} weather forecast entries")
    print(f"  - {len(HISTORICAL_PRICE_STATS)} historical price stats")


if __name__ == "__main__":
    main()