144 lines
6.5 KiB
PHP
144 lines
6.5 KiB
PHP
<?php
|
|
// includes/config.php v2.0
|
|
// ============================================================
|
|
// Konfigurasi Database & Konstanta Aplikasi
|
|
// ============================================================
|
|
|
|
// ── Database ──────────────────────────────────────────────
|
|
define('DB_HOST', getenv('DB_HOST') ?: 'localhost');
|
|
define('DB_USER', getenv('DB_USER') ?: 'root');
|
|
define('DB_PASS', getenv('DB_PASS') ?: '');
|
|
define('DB_NAME', getenv('DB_NAME') ?: 'sig_kemiskinan');
|
|
define('DB_CHARSET', 'utf8mb4');
|
|
|
|
// ── Aplikasi ──────────────────────────────────────────────
|
|
define('APP_NAME', 'SIG Kemiskinan v2.0');
|
|
define('NOMINATIM_URL', 'https://nominatim.openstreetmap.org');
|
|
|
|
// ── Upload Foto ────────────────────────────────────────────
|
|
define('UPLOAD_DIR', __DIR__ . '/../assets/img/uploads/');
|
|
define('UPLOAD_URL', 'assets/img/uploads/');
|
|
define('MAX_FOTO_SIZE', 5 * 1024 * 1024); // 5 MB
|
|
define('ALLOWED_EXT', ['jpg','jpeg','png','webp']);
|
|
|
|
// ── Threshold Kategori Kemiskinan (Rp/bulan) ──────────────
|
|
// Disesuaikan dengan standar BPS & UMR Kalimantan Barat 2024
|
|
define('BATAS_SANGAT_MISKIN', 1500000); // < 1.5jt → sangat_miskin
|
|
define('BATAS_MISKIN', 3000000); // < 3jt → miskin
|
|
define('BATAS_HAMPIR_MISKIN', 5000000); // < 5jt → hampir_miskin
|
|
// >= 5jt → mampu
|
|
// ── Notifikasi ────────────────────────────────────────────
|
|
define('DATA_USANG_HARI', 30); // data > 30 hari belum update = notif usang
|
|
|
|
// ============================================================
|
|
// FUNGSI: Koneksi Database (Singleton PDO)
|
|
// ============================================================
|
|
function getDB(): PDO {
|
|
static $pdo = null;
|
|
if ($pdo === null) {
|
|
$dsn = "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=" . DB_CHARSET;
|
|
$options = [
|
|
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
|
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
|
PDO::ATTR_EMULATE_PREPARES => false,
|
|
];
|
|
try {
|
|
$pdo = new PDO($dsn, DB_USER, DB_PASS, $options);
|
|
} catch (PDOException $e) {
|
|
http_response_code(500);
|
|
die(json_encode(['success' => false, 'error' => 'Database connection failed: ' . $e->getMessage()]));
|
|
}
|
|
}
|
|
return $pdo;
|
|
}
|
|
|
|
// ============================================================
|
|
// FUNGSI: Response JSON
|
|
// ============================================================
|
|
function jsonResponse(mixed $data, int $code = 200): void {
|
|
http_response_code($code);
|
|
header('Content-Type: application/json; charset=utf-8');
|
|
header('Access-Control-Allow-Origin: *');
|
|
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
|
|
header('Access-Control-Allow-Headers: Content-Type, Authorization');
|
|
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
|
exit;
|
|
}
|
|
|
|
// ============================================================
|
|
// FUNGSI: Baca Input (JSON body atau $_POST)
|
|
// ============================================================
|
|
function getInput(): array {
|
|
$raw = file_get_contents('php://input');
|
|
$data = json_decode($raw, true);
|
|
if (json_last_error() !== JSON_ERROR_NONE) {
|
|
$data = $_POST;
|
|
}
|
|
return $data ?? [];
|
|
}
|
|
|
|
// ============================================================
|
|
// FUNGSI: Hitung Jarak Haversine (meter)
|
|
// ============================================================
|
|
function haversine(float $lat1, float $lng1, float $lat2, float $lng2): float {
|
|
$R = 6371000;
|
|
$dLat = deg2rad($lat2 - $lat1);
|
|
$dLng = deg2rad($lng2 - $lng1);
|
|
$a = sin($dLat/2)**2 + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * sin($dLng/2)**2;
|
|
return $R * 2 * atan2(sqrt($a), sqrt(1 - $a));
|
|
}
|
|
|
|
// ============================================================
|
|
// FUNGSI: Hitung Kategori Kemiskinan Otomatis
|
|
// ============================================================
|
|
function hitungKategori(?float $penghasilan): string {
|
|
if ($penghasilan === null || $penghasilan < BATAS_SANGAT_MISKIN) return 'sangat_miskin';
|
|
if ($penghasilan < BATAS_MISKIN) return 'miskin';
|
|
if ($penghasilan < BATAS_HAMPIR_MISKIN) return 'hampir_miskin';
|
|
return 'mampu';
|
|
}
|
|
|
|
// ============================================================
|
|
// FUNGSI: Assign Rumah Ibadah (kompatibel v1.1)
|
|
// ============================================================
|
|
function assignRumahIbadah(int $pendudukId): void {
|
|
try {
|
|
$db = getDB();
|
|
$p = $db->prepare("SELECT lat, lng FROM penduduk_miskin WHERE id = ?");
|
|
$p->execute([$pendudukId]);
|
|
$row = $p->fetch();
|
|
if (!$row) return;
|
|
|
|
$ibadahList = $db->query("SELECT id, lat, lng, radius FROM rumah_ibadah")->fetchAll();
|
|
$closest = null;
|
|
$closestDist = PHP_FLOAT_MAX;
|
|
|
|
foreach ($ibadahList as $ri) {
|
|
$dist = haversine((float)$row['lat'], (float)$row['lng'], (float)$ri['lat'], (float)$ri['lng']);
|
|
if ($dist <= $ri['radius'] && $dist < $closestDist) {
|
|
$closest = $ri['id'];
|
|
$closestDist = $dist;
|
|
}
|
|
}
|
|
|
|
$db->prepare("UPDATE penduduk_miskin SET rumah_ibadah_id = ?, jarak_ke_ibadah = ? WHERE id = ?")
|
|
->execute([$closest, $closest ? round($closestDist, 2) : null, $pendudukId]);
|
|
} catch (\Exception $e) { /* abaikan error assign ibadah */ }
|
|
}
|
|
|
|
function reassignAll(): void {
|
|
$db = getDB();
|
|
$all = $db->query("SELECT id FROM penduduk_miskin")->fetchAll();
|
|
foreach ($all as $row) assignRumahIbadah((int)$row['id']);
|
|
}
|
|
|
|
// ============================================================
|
|
// FUNGSI: Catat Riwayat Verifikasi
|
|
// ============================================================
|
|
function catatRiwayat(int $pendudukId, int $userId, string $aksi, ?string $catatan = null, ?array $dataLama = null): void {
|
|
$db = getDB();
|
|
$db->prepare("
|
|
INSERT INTO riwayat_verifikasi (penduduk_id, user_id, aksi, catatan, data_lama)
|
|
VALUES (?, ?, ?, ?, ?)
|
|
")->execute([$pendudukId, $userId, $aksi, $catatan, $dataLama ? json_encode($dataLama, JSON_UNESCAPED_UNICODE) : null]);
|
|
} |