From 503e9421a980edda0113de01a40069d314b25051 Mon Sep 17 00:00:00 2001 From: envicy Date: Thu, 11 Jun 2026 16:37:05 +0700 Subject: [PATCH] Initial commit --- index.php | 531 ++ jalan/index.php | 1468 ++++++ jalan/jalan.sql | 26 + penduduk/index.php | 163 + penduduk/pontianak.js | 59 + penduduk/pontianak.json | 8 + penduduk/us-states.js | 4386 +++++++++++++++++ spbu/index.php | 750 +++ spbu/spbu.sql | 21 + webgis-poverty-pontianak.zip | Bin 0 -> 68238 bytes webgis-poverty-pontianak/README.md | 84 + webgis-poverty-pontianak/api/auth_helper.php | 56 + .../api/check_session.php | 27 + .../api/dashboard/stats.php | 196 + .../api/dashboard/stats_extended.php | 171 + webgis-poverty-pontianak/api/db_connect.php | 17 + .../api/log_bantuan/create.php | 37 + .../api/log_bantuan/read.php | 37 + webgis-poverty-pontianak/api/login.php | 55 + webgis-poverty-pontianak/api/logout.php | 21 + .../api/penduduk_miskin/bulk_create.php | 83 + .../api/penduduk_miskin/create.php | 109 + .../api/penduduk_miskin/delete.php | 65 + .../api/penduduk_miskin/read.php | 28 + .../api/penduduk_miskin/update.php | 148 + .../api/rumah_ibadah/create.php | 28 + .../api/rumah_ibadah/delete.php | 22 + .../api/rumah_ibadah/read.php | 27 + .../api/rumah_ibadah/update.php | 30 + webgis-poverty-pontianak/api/users/create.php | 47 + webgis-poverty-pontianak/api/users/delete.php | 30 + webgis-poverty-pontianak/api/users/read.php | 31 + webgis-poverty-pontianak/api/users/update.php | 52 + webgis-poverty-pontianak/assets/css/style.css | 1341 +++++ .../assets/js/features/auth.js | 383 ++ .../assets/js/features/dashboard.js | 468 ++ .../assets/js/features/geojson.js | 181 + .../assets/js/features/geolocation.js | 30 + .../assets/js/features/kemiskinan.js | 916 ++++ webgis-poverty-pontianak/assets/js/map.js | 242 + webgis-poverty-pontianak/assets/js/panel.js | 465 ++ webgis-poverty-pontianak/database.sql | 90 + webgis-poverty-pontianak/index.php | 408 ++ webgis-poverty-pontianak/test_miskin.csv | 4 + webgis-poverty-pontianak/test_miskin.geojson | 29 + 45 files changed, 13370 insertions(+) create mode 100644 index.php create mode 100644 jalan/index.php create mode 100644 jalan/jalan.sql create mode 100644 penduduk/index.php create mode 100644 penduduk/pontianak.js create mode 100644 penduduk/pontianak.json create mode 100644 penduduk/us-states.js create mode 100644 spbu/index.php create mode 100644 spbu/spbu.sql create mode 100644 webgis-poverty-pontianak.zip create mode 100644 webgis-poverty-pontianak/README.md create mode 100644 webgis-poverty-pontianak/api/auth_helper.php create mode 100644 webgis-poverty-pontianak/api/check_session.php create mode 100644 webgis-poverty-pontianak/api/dashboard/stats.php create mode 100644 webgis-poverty-pontianak/api/dashboard/stats_extended.php create mode 100644 webgis-poverty-pontianak/api/db_connect.php create mode 100644 webgis-poverty-pontianak/api/log_bantuan/create.php create mode 100644 webgis-poverty-pontianak/api/log_bantuan/read.php create mode 100644 webgis-poverty-pontianak/api/login.php create mode 100644 webgis-poverty-pontianak/api/logout.php create mode 100644 webgis-poverty-pontianak/api/penduduk_miskin/bulk_create.php create mode 100644 webgis-poverty-pontianak/api/penduduk_miskin/create.php create mode 100644 webgis-poverty-pontianak/api/penduduk_miskin/delete.php create mode 100644 webgis-poverty-pontianak/api/penduduk_miskin/read.php create mode 100644 webgis-poverty-pontianak/api/penduduk_miskin/update.php create mode 100644 webgis-poverty-pontianak/api/rumah_ibadah/create.php create mode 100644 webgis-poverty-pontianak/api/rumah_ibadah/delete.php create mode 100644 webgis-poverty-pontianak/api/rumah_ibadah/read.php create mode 100644 webgis-poverty-pontianak/api/rumah_ibadah/update.php create mode 100644 webgis-poverty-pontianak/api/users/create.php create mode 100644 webgis-poverty-pontianak/api/users/delete.php create mode 100644 webgis-poverty-pontianak/api/users/read.php create mode 100644 webgis-poverty-pontianak/api/users/update.php create mode 100644 webgis-poverty-pontianak/assets/css/style.css create mode 100644 webgis-poverty-pontianak/assets/js/features/auth.js create mode 100644 webgis-poverty-pontianak/assets/js/features/dashboard.js create mode 100644 webgis-poverty-pontianak/assets/js/features/geojson.js create mode 100644 webgis-poverty-pontianak/assets/js/features/geolocation.js create mode 100644 webgis-poverty-pontianak/assets/js/features/kemiskinan.js create mode 100644 webgis-poverty-pontianak/assets/js/map.js create mode 100644 webgis-poverty-pontianak/assets/js/panel.js create mode 100644 webgis-poverty-pontianak/database.sql create mode 100644 webgis-poverty-pontianak/index.php create mode 100644 webgis-poverty-pontianak/test_miskin.csv create mode 100644 webgis-poverty-pontianak/test_miskin.geojson diff --git a/index.php b/index.php new file mode 100644 index 0000000..0ea163e --- /dev/null +++ b/index.php @@ -0,0 +1,531 @@ +connect_error) return null; + $conn->set_charset("utf8mb4"); + $r = $conn->query("SELECT COUNT(*) AS c FROM `$table`"); + $val = ($r) ? (int)$r->fetch_assoc()['c'] : null; + $conn->close(); + return $val; + } catch (Throwable $e) { return null; } +} + +function safeSum($db, $table, $col) { + try { + $conn = @new mysqli("localhost", "root", "", $db); + if (!$conn || $conn->connect_error) return null; + $conn->set_charset("utf8mb4"); + $r = $conn->query("SELECT COALESCE(SUM(`$col`),0) AS s FROM `$table`"); + $val = ($r) ? (float)$r->fetch_assoc()['s'] : null; + $conn->close(); + return $val; + } catch (Throwable $e) { return null; } +} + +function safeQuery($db, $sql) { + try { + $conn = @new mysqli("localhost", "root", "", $db); + if (!$conn || $conn->connect_error) return null; + $conn->set_charset("utf8mb4"); + $r = $conn->query($sql); + $val = ($r) ? $r->fetch_assoc() : null; + $conn->close(); + return $val; + } catch (Throwable $e) { return null; } +} + +// Coba kedua nama database untuk kemiskinan +$dbPoverty = null; +foreach (['webgis_poverty', 'webgis'] as $dbName) { + try { + $test = @new mysqli("localhost", "root", "", $dbName); + if ($test && !$test->connect_error) { $dbPoverty = $dbName; $test->close(); break; } + } catch (Throwable $e) { continue; } +} + +$stats = [ + 'jalan_ruas' => safeCount('jalan', 'jalan'), + 'jalan_km' => round((safeSum('jalan', 'jalan', 'panjang_meter') ?? 0) / 1000, 2), + 'parsil' => safeCount('jalan', 'parsil_tanah'), + 'spbu_total' => safeCount('spbu', 'spbu'), + 'spbu_24' => null, + 'kk_miskin' => $dbPoverty ? safeCount($dbPoverty, 'penduduk_miskin') : null, + 'log_bantuan' => $dbPoverty ? safeCount($dbPoverty, 'log_bantuan') : null, + 'ibadah' => $dbPoverty ? safeCount($dbPoverty, 'rumah_ibadah') : null, +]; + +$spbuRow = safeQuery('spbu', "SELECT SUM(buka_24_jam=1) AS b FROM spbu"); +if ($spbuRow) $stats['spbu_24'] = (int)$spbuRow['b']; + +// Helper: tampilkan nilai atau dash +function sv($v, $suffix = '') { + if ($v === null) return ''; + return htmlspecialchars($v . $suffix); +} + +$year = date('Y'); +?> + + + + + +WebGIS Pontianak — Portal + + + + + + + + +
+
+ +
+ + +
+
+ + WebGIS Kota Pontianak +
+

+ Portal Sistem Informasi
Geospasial +

+

+ Platform terpadu pemetaan infrastruktur, kependudukan, energi, dan kemiskinan + Kota Pontianak — Kalimantan Barat. +

+
+ + +
Ringkasan Data
+
+
+
+
Ruas Jalan
+
+
+
6
+
Kecamatan
+
+
+
+
SPBU Terdaftar
+
+
+
+
KK Miskin
+
+
+ +
+ + +
Aplikasi Tersedia
+ + + +
+
WebGIS Pontianak © — Sistem Informasi Geospasial Kota
+
+
+
Kalimantan Barat, Indonesia
+
+
+ +
+ + diff --git a/jalan/index.php b/jalan/index.php new file mode 100644 index 0000000..cae2bb2 --- /dev/null +++ b/jalan/index.php @@ -0,0 +1,1468 @@ +connect_error) die(json_encode(['error' => $conn->connect_error])); + +// ════════════════════════════════ +// JALAN (POLYLINE) — CRUD +// ════════════════════════════════ + +// INSERT jalan +if (isset($_POST['action']) && $_POST['action'] === 'insert_jalan') { + $nama = $conn->real_escape_string($_POST['nama']); + $status = $conn->real_escape_string($_POST['status']); + $panjang = floatval($_POST['panjang']); + $geojson = $conn->real_escape_string($_POST['geojson']); + $conn->query("INSERT INTO jalan (nama_jalan, status_jalan, panjang_meter, geojson) + VALUES ('$nama','$status','$panjang','$geojson')"); + echo json_encode(['id' => $conn->insert_id]); + exit; +} + +// UPDATE jalan +if (isset($_POST['action']) && $_POST['action'] === 'update_jalan') { + $id = intval($_POST['id']); + $nama = $conn->real_escape_string($_POST['nama']); + $status = $conn->real_escape_string($_POST['status']); + $panjang = floatval($_POST['panjang']); + $geojson = $conn->real_escape_string($_POST['geojson']); + $conn->query("UPDATE jalan SET nama_jalan='$nama', status_jalan='$status', + panjang_meter='$panjang', geojson='$geojson' WHERE id=$id"); + echo json_encode(['ok' => true]); + exit; +} + +// DELETE jalan +if (isset($_POST['action']) && $_POST['action'] === 'delete_jalan') { + $id = intval($_POST['id']); + $conn->query("DELETE FROM jalan WHERE id=$id"); + echo json_encode(['ok' => true]); + exit; +} + +// GET jalan +if (isset($_GET['get']) && $_GET['get'] === 'jalan') { + $result = $conn->query("SELECT * FROM jalan ORDER BY id DESC"); + $data = []; + while ($row = $result->fetch_assoc()) $data[] = $row; + echo json_encode($data); + exit; +} + +// ════════════════════════════════ +// PARSIL TANAH (POLYGON) — CRUD +// ════════════════════════════════ + +// INSERT parsil +if (isset($_POST['action']) && $_POST['action'] === 'insert_parsil') { + $nama = $conn->real_escape_string($_POST['nama']); + $status = $conn->real_escape_string($_POST['status']); + $luas = floatval($_POST['luas']); + $geojson = $conn->real_escape_string($_POST['geojson']); + $conn->query("INSERT INTO parsil_tanah (nama_parsil, status_kepemilikan, luas_m2, geojson) + VALUES ('$nama','$status','$luas','$geojson')"); + echo json_encode(['id' => $conn->insert_id]); + exit; +} + +// UPDATE parsil +if (isset($_POST['action']) && $_POST['action'] === 'update_parsil') { + $id = intval($_POST['id']); + $nama = $conn->real_escape_string($_POST['nama']); + $status = $conn->real_escape_string($_POST['status']); + $luas = floatval($_POST['luas']); + $geojson = $conn->real_escape_string($_POST['geojson']); + $conn->query("UPDATE parsil_tanah SET nama_parsil='$nama', status_kepemilikan='$status', + luas_m2='$luas', geojson='$geojson' WHERE id=$id"); + echo json_encode(['ok' => true]); + exit; +} + +// DELETE parsil +if (isset($_POST['action']) && $_POST['action'] === 'delete_parsil') { + $id = intval($_POST['id']); + $conn->query("DELETE FROM parsil_tanah WHERE id=$id"); + echo json_encode(['ok' => true]); + exit; +} + +// GET parsil +if (isset($_GET['get']) && $_GET['get'] === 'parsil') { + $result = $conn->query("SELECT * FROM parsil_tanah ORDER BY id DESC"); + $data = []; + while ($row = $result->fetch_assoc()) $data[] = $row; + echo json_encode($data); + exit; +} +?> + + + + + +WebGIS - Jalan dan Tanah + + + + + + + + + + + + +
+ + + + + +
+ +
+ + +
+ + +
+
+ Klik peta untuk mulai menggambar... +
+ + +
+
+ + +
+
+ Seret titik untuk mengubah bentuk + + +
+ + +
+
+ +
+ + +
+
+
Status Jalan
+
Jalan Nasional
+
Jalan Provinsi
+
Jalan Kabupaten
+
+
+
Kepemilikan Tanah
+
SHM
+
HGB
+
HGU
+
HP
+
+
+ + +
+
+ Pilih tool di atas untuk menambah data +
+ + + + + + + + + + \ No newline at end of file diff --git a/jalan/jalan.sql b/jalan/jalan.sql new file mode 100644 index 0000000..987a4a1 --- /dev/null +++ b/jalan/jalan.sql @@ -0,0 +1,26 @@ + +CREATE DATABASE IF NOT EXISTS jalan + CHARACTER SET utf8mb4 + COLLATE utf8mb4_unicode_ci; + +USE jalan; + +-- Tabel Jalan (Polyline) +CREATE TABLE IF NOT EXISTS jalan ( + id INT(11) NOT NULL AUTO_INCREMENT, + nama_jalan VARCHAR(255) NOT NULL, + status_jalan ENUM('Nasional','Provinsi','Kabupaten') NOT NULL DEFAULT 'Kabupaten', + panjang_meter FLOAT NOT NULL DEFAULT 0, + geojson LONGTEXT NOT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Tabel Parsil Tanah (Polygon) +CREATE TABLE IF NOT EXISTS parsil_tanah ( + id INT(11) NOT NULL AUTO_INCREMENT, + nama_parsil VARCHAR(255) NOT NULL, + status_kepemilikan ENUM('SHM','HGB','HGU','HP') NOT NULL DEFAULT 'SHM', + luas_m2 FLOAT NOT NULL DEFAULT 0, + geojson LONGTEXT NOT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/penduduk/index.php b/penduduk/index.php new file mode 100644 index 0000000..593db46 --- /dev/null +++ b/penduduk/index.php @@ -0,0 +1,163 @@ + + + + + + + Kepadatan Penduduk Pontianak + + + + + + +
+ + + \ No newline at end of file diff --git a/penduduk/pontianak.js b/penduduk/pontianak.js new file mode 100644 index 0000000..331a5c3 --- /dev/null +++ b/penduduk/pontianak.js @@ -0,0 +1,59 @@ +var statesData = { + type: "FeatureCollection", + features: [ + { + type: "Feature", + id: "1", + properties: { name: "Pontianak Selatan", density: 5.673 }, + geometry: { + type: "Polygon", + coordinates: [[[315791.7496880172,-2872.6773100267],[315493.9173600795,-3043.9080895001625],[315326.6521934429,-3151.333180362999],[315140.4188381387,-3281.935194921576],[315066.9918184001,-3327.8058926928916],[314996.8467820659,-3371.6262979517323],[314888.67104393616,-3478.080758171731],[314812.70706351567,-3552.7994604061805],[314746.1257071411,-3618.2893480278017],[314655.6433510417,-3707.2884260803185],[314606.10591966007,-3756.013789919325],[314454.0137261031,-3905.612734831022],[314344.4320643814,-3996.3010035972147],[314259.6778418068,-4066.4424268491857],[314085.032268201,-4210.976689869447],[313840.1791924136,-4413.613711391907],[313536.192724674,-4712.359024276697],[313300.8322324334,-4943.661570138169],[312916.42216176353,-5321.443869765168],[312612.50988089014,-5620.11627486908],[312370.45105957426,-5854.688712254208],[312057.7659053877,-6157.703154576355],[311585.92455374077,-6614.9514189124275],[311333.4393242495,-6891.340090787351],[313474.832878937,-8889.931704557468],[313757.1209584046,-8461.458752544078],[314215.6677178042,-7765.450320278544],[314471.81653076597,-7473.440609211619],[314877.1271904595,-7011.386355436478],[315170.0992892701,-6667.707583206353],[315565.04540335014,-6204.405459439875],[315762.9765556948,-5956.206301724727],[315946.9456108697,-5783.346926725002],[316115.1479424136,-5571.442019498811],[316233.71287194826,-5370.136871324419],[316413.0633267751,-5142.274731615995],[316588.3382888399,-4973.07120414943],[315803.17076956015,-2870.648806607189],[315791.7496880172,-2872.6773100267]]] + } + }, + { + type: "Feature", + id: "2", + properties: { name: "Pontianak Utara", density: 3.642 }, + geometry: { + type: "Polygon", + coordinates: [[[309688.2266975902,951.2434479881485],[310155.9051329456,933.8867466094162],[310357.96077316906,885.1327602118836],[311332.6877226224,552.8154289115046],[312269.31459587533,306.7524367839651],[313016.67581282463,28.516046978937084],[313225.22203908674,-84.19626616407731],[313546.372705549,-322.5867385597503],[313720.9980547987,-448.5286571102988],[314170.79062105156,-811.0085487379129],[314504.16628780216,-895.1462170118866],[314775.1001630025,-1443.89314784007],[315291.5124306837,-1928.5005853951407],[315734.48124843184,-2324.9574099686342],[316159.40293160826,-2368.349163418803],[316654.17475448735,-2251.9322639187267],[317038.8796905633,-2161.4445829436972],[317913.59393999074,-2046.6151866172168],[318283.48217976745,-2054.023534766595],[318775.15660756174,-2147.859083549327],[319287.81429954246,-2395.9329130315673],[319416.881835456,-2033.8234388107558],[319526.1020538965,-1800.9896398106011],[319533.72206913494,-1723.0961506912936],[319510.86202341504,-1622.342615849966],[319574.3621504167,-1479.2556630090148],[319598.91553285625,-1507.1957188887664],[319482.0752991745,-1853.4830781301353],[319424.3083182946,-874.973119525288],[319320.91374074016,-644.5676602992062],[318847.9647948425,226.72111005606712],[318658.4169157464,989.0401346929066],[316567.76460495684,2999.9040346896763],[314562.85392847005,3541.7717850915287],[312083.8089703787,4381.666798215181],[309688.2266975902,951.2434479881485]]] + } + }, + { + type: "Feature", + id: "3", + properties: { name: "Pontianak Timur", density: 9.196 }, + geometry: { + type: "Polygon", + coordinates: [[[319887.57044806925,-5373.344392278639],[319702.88422977563,-5132.534790727044],[319580.270434435,-4979.559484159208],[319416.78537397756,-4779.407060143594],[319288.3328264768,-4635.773757029033],[319063.0274988217,-4397.196101115128],[318712.6388119413,-4027.525809986318],[319240.45505877363,-3500.8371123406214],[319482.70326267194,-3416.1079811805625],[319930.7033710063,-3290.5899437818016],[320060.2158619128,-2885.3158597254237],[319668.47127330344,-2832.0761712812755],[319302.34583165945,-2724.1663001296456],[319016.246975861,-2582.2846226671395],[318611.86326987745,-2402.6633110638345],[318312.0934654712,-2349.9022867323624],[317831.7500457056,-2325.396742533832],[317450.6828969274,-2376.0793589098607],[316961.72475783527,-2448.1651844011494],[316290.7174679831,-2617.4144481542617],[315891.63306421525,-2646.1325691096436],[316108.6562515756,-3080.1789438243754],[316374.4062489303,-3648.9273296033716],[316666.3438568887,-4078.0756132950055],[316960.2915036416,-4459.3151686055135],[317511.1983193059,-4982.14799761562],[318003.96436076245,-5498.157720267835],[318525.46364961116,-6295.854170744091],[318997.8492128665,-6873.389132317587],[319200.2395574156,-6725.148423245205],[319464.4036415865,-6506.445073789114],[319929.8147521868,-6173.089029280636],[320230.3441586008,-5948.45374608942],[319892.69977100904,-5382.870277737669],[319887.57044806925,-5373.344392278639]]] + } + }, + { + type: "Feature", + id: "4", + properties: { name: "Pontianak Tenggara", density: 3.103 }, + geometry: { + type: "Polygon", + coordinates: [[[316509.95719540527,-5101.833566810722],[316277.42321839795,-5368.326560621595],[315586.95250728936,-6227.493567962928],[314650.4343267438,-7312.870467518172],[313943.0478521116,-8266.304411587676],[313570.5827409144,-8808.522535934284],[314482.8144881896,-9756.429398367298],[315386.15532470803,-10595.173154648382],[315969.86388160125,-10324.183934093831],[316202.0711808827,-9921.28120289028],[316389.8178299225,-9632.15192111897],[316955.59155603434,-8811.299556391281],[317370.6954695009,-8105.002669764531],[318021.28465803474,-6941.185008999439],[318253.2629668124,-6576.773915689321],[318236.68267524854,-6280.690804057879],[317914.4077884978,-5744.010290518615],[317403.09039107355,-5217.314926254428],[316771.0250557211,-4765.816074840871],[316509.95719540527,-5101.833566810722]]] + } + }, + { + type: "Feature", + id: "5", + properties: { name: "Pontianak Kota", density: 8.102 }, + geometry: { + type: "Polygon", + coordinates: [[[310276.47296142485,-3455.9797973638633],[309858.4304809589,-3797.2929687509313],[309527.70056152344,-4114.79357910133],[309256.67931494024,-4394.240588930203],[309517.11724853516,-4686.294799805153],[309900.76403808687,-5093.753967286088],[310421.994140625,-5638.796691895346],[310977.62023925874,-6427.256591796759],[311295.12091064546,-6863.819946288946],[311784.60089111235,-6451.0691528309835],[312297.8936767578,-5916.60974120989],[312922.31152343843,-5310.71270752023],[313407.04170880467,-4843.868031024118],[313851.00109863374,-4424.356750487466],[314247.8766479511,-4080.397766113165],[314713.5443115253,-3659.709350586054],[315263.87866211124,-3191.395935058943],[315803.6297607431,-2876.541137695778],[315533.75421142764,-2532.582153319032],[315086.40909403935,-2251.8851285779383],[314597.12731933594,-1876.4141235346906],[314187.02246093843,-2037.810302733793],[313546.7294311533,-2148.9354858405422],[312935.5408325214,-2270.64410400379],[312366.6854858408,-2413.519348145579],[311906.3095092783,-2564.3322143565165],[311385.0793457031,-2783.936767577892],[310773.8905639658,-3093.4998779299203],[310276.47296142485,-3455.9797973638633]]] + } + }, + { + type: "Feature", + id: "6", + properties: { name: "Pontianak Barat", density: 9.331 }, + geometry: { + type: "Polygon", + coordinates: [[[314496.5855712909,-1831.4348754876992],[314333.6083123619,-1673.1813620609464],[313976.42009798624,-1469.4517879342893],[313709.19039686024,-1196.9304095584666],[313412.8564708587,-1024.9508989329915],[313156.21012423374,-776.2420681805816],[312690.5425262293,-424.3455310544232],[312129.62473772746,-204.74092517967802],[311526.37353122514,-96.26154155412223],[310896.6639384739,-149.17831405519973],[310303.9960864708,-154.46999130456243],[309732.49494346976,70.42629182199016],[309351.49418146536,70.42629182199016],[309319.74411796685,-400.5329834310105],[309364.7233745931,-715.3877798067406],[309351.49418146536,-974.679965057876],[309232.4314433411,-1506.493528684834],[309176.8688322166,-1879.5567748110043],[309205.97305709217,-2040.952930937754],[308552.45091671497,-2472.2246268143645],[308147.6376070874,-3011.9757063165307],[308430.74233996496,-3734.289650943014],[308827.6181337144,-4363.999243696919],[309142.47293009236,-4490.9994976965245],[309479.5459254207,-4168.759302856284],[310007.24186643306,-3657.238962248084],[310429.9315185547,-3344.854614257114],[310773.8905639658,-3093.4998779299203],[311336.9246401787,-2797.156559649622],[311906.3095092783,-2564.3322143565165],[312525.43572998233,-2360.602661131881],[313125.56844345294,-2227.800214529503],[313970.063720705,-2077.4978637696477],[314456.89801025484,-1908.1641845697304],[314496.5855712909,-1831.4348754876992]]] + } + } + ] +}; \ No newline at end of file diff --git a/penduduk/pontianak.json b/penduduk/pontianak.json new file mode 100644 index 0000000..5ec190c --- /dev/null +++ b/penduduk/pontianak.json @@ -0,0 +1,8 @@ +{"type":"FeatureCollection", "features": [ +{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[315791.7496880172,-2872.6773100267],[315493.9173600795,-3043.9080895001625],[315326.6521934429,-3151.333180362999],[315140.4188381387,-3281.935194921576],[315066.9918184001,-3327.8058926928916],[314996.8467820659,-3371.6262979517323],[314888.67104393616,-3478.080758171731],[314812.70706351567,-3552.7994604061805],[314746.1257071411,-3618.2893480278017],[314655.6433510417,-3707.2884260803185],[314606.10591966007,-3756.013789919325],[314454.0137261031,-3905.612734831022],[314344.4320643814,-3996.3010035972147],[314259.6778418068,-4066.4424268491857],[314085.032268201,-4210.976689869447],[313840.1791924136,-4413.613711391907],[313536.192724674,-4712.359024276697],[313300.8322324334,-4943.661570138169],[312916.42216176353,-5321.443869765168],[312612.50988089014,-5620.11627486908],[312370.45105957426,-5854.688712254208],[312057.7659053877,-6157.703154576355],[311585.92455374077,-6614.9514189124275],[311333.4393242495,-6891.340090787351],[311349.90300833154,-6902.971926725351],[311371.5987480767,-6925.461611782668],[311404.1888970034,-6960.523379361852],[311421.3977593072,-6976.292544400771],[311452.8170708306,-7006.871645962508],[311495.7740410464,-7052.635806119659],[311529.00988089014,-7091.601138149959],[311545.2208183883,-7107.547366177889],[311564.00658499077,-7126.026492155595],[311582.9525688775,-7144.663271940026],[312306.1403130181,-7871.188052213602],[312689.2579888003,-8220.438845670635],[313474.832878937,-8889.931704557468],[313757.1209584046,-8461.458752544078],[314215.6677178042,-7765.450320278544],[314471.81653076597,-7473.440609211619],[314877.1271904595,-7011.386355436478],[315170.0992892701,-6667.707583206353],[315565.04540335014,-6204.405459439875],[315762.9765556948,-5956.206301724727],[315946.9456108697,-5783.346926725002],[316115.1479424136,-5571.442019498811],[316233.71287194826,-5370.136871324419],[316413.0633267751,-5142.274731615995],[316588.3382888399,-4973.07120414943],[316562.62481477764,-4944.194633692106],[316673.55813834723,-4826.780624282608],[316813.89236564003,-4699.78719729204],[316848.5410874747,-4658.158080699761],[316695.5555569697,-4485.049627727178],[316572.88390432764,-4348.467104947824],[316475.2670220034,-4225.068423306027],[316443.7366264956,-4173.700991666048],[316414.5740898745,-4126.191226040231],[316414.41985403467,-4125.940066372697],[316377.99205862265,-4066.594180141925],[316347.419976105,-4016.7879667644283],[316308.4733818667,-3943.1278715497774],[316293.5168999322,-3918.198245083262],[316145.0217217095,-3674.7195463533626],[316072.2159966128,-3553.555850065626],[316013.2322319634,-3448.2597685219316],[315999.5084160464,-3358.123232878157],[315964.6694878228,-3266.509829556244],[315898.449621683,-3104.193594283126],[315803.17076956015,-2870.648806607189],[315791.7496880172,-2872.6773100267]]]},"properties":{"Id":0,"Kecamatan":"Pontianak Selatan"}}, +{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[309688.2266975902,951.2434479881485],[310155.9051329456,933.8867466094162],[310357.96077316906,885.1327602118836],[310911.47021352034,552.8154289115046],[311332.6877226224,552.8154289115046],[311608.91327507235,474.49860561108653],[311890.9596725013,437.45686485974875],[312050.7683254536,378.71924738555026],[312269.31459587533,306.7524367839651],[312450.8191255536,254.36483200859948],[312672.1876238454,162.395481404139],[313016.67581282463,28.516046978937084],[313134.15104777087,-2.175681071345025],[313225.22203908674,-84.19626616407731],[313257.97629542183,-141.34679274705377],[313291.2401063731,-166.3159329688442],[313376.5098658232,-207.49275837285495],[313431.01414149813,-257.763692247132],[313546.372705549,-322.5867385597503],[313633.6853801729,-379.2076851350812],[313720.9980547987,-448.5286571102988],[313751.1606151238,-493.5079137362882],[313825.77326434944,-557.5372084609971],[313842.9749822486,-590.9609248882916],[313906.1013929201,-642.7457594489806],[313982.9360786751,-682.4207915609986],[314082.4196109753,-771.3209693624322],[314170.79062105156,-811.0085487379129],[314252.8116184268,-879.800352987857],[314304.67005547695,-920.5462678116619],[314354.9409893509,-995.1589170373882],[314394.6285687266,-1025.3214773623986],[314415.77314684074,-1067.811862995084],[314448.25415333174,-1096.6891320695122],[314465.0078761522,-1062.892385839008],[314488.82042377815,-976.6380466639421],[314504.16628780216,-895.1462170118866],[314526.3913322529,-814.712722812601],[314528.508003152,-781.9043238612267],[314538.71590561327,-811.1396428356384],[314529.03717087954,-854.4003021880817],[314516.8663132023,-909.9629133128674],[314499.40377827734,-994.6297493121147],[314481.94124335237,-1087.2341011882363],[314478.2370692771,-1117.3966615132467],[314594.12480105273,-1234.8718964638701],[314660.79993440304,-1331.7095901399553],[314775.1001630025,-1443.89314784007],[314882.5212111799,-1457.6515086905038],[314922.20879055746,-1552.3725314654948],[314969.83388580475,-1603.1726330650436],[315025.39649693016,-1670.3769341413918],[315056.08822498005,-1687.8394690665136],[315076.1965985298,-1709.535345791599],[315090.4841271052,-1741.285409290207],[315132.28837737907,-1795.2605172413932],[315201.0801816294,-1863.5231537660657],[315291.5124306837,-1928.5005853951407],[315341.3096287558,-2007.9859426922812],[315384.17221448105,-2064.0777215423386],[315482.59741132986,-2142.394544842755],[315635.5268838564,-2261.457282969197],[315734.48124843184,-2324.9574099686342],[315913.3399394825,-2362.5283184430227],[316045.6318707345,-2371.5241697682195],[316159.40293160826,-2368.349163418803],[316330.8532745093,-2329.7199194938694],[316472.67022481,-2284.2114951426065],[316654.17475448735,-2251.9322639187267],[316703.3873529108,-2262.515618417521],[316795.9917047871,-2247.698922118765],[316851.5543159116,-2209.0696781938295],[316871.6626894614,-2209.0696781938295],[316878.54186988715,-2186.8446337434707],[317038.8796905633,-2161.4445829436972],[317253.7217869144,-2122.286171293488],[317396.0679049399,-2096.3569527684413],[317413.00127214007,-2106.411139541964],[317452.15968379006,-2107.4694749925093],[317479.14723776374,-2085.773598267424],[317599.26831134036,-2081.011088742189],[317762.78113836516,-2053.494367043544],[317913.59393999074,-2046.6151866172168],[317940.5814939663,-2051.377696142452],[318033.18584584165,-2054.023534766595],[318059.1150643667,-2049.790192966633],[318157.54026121926,-2050.8485284171784],[318232.1529104421,-2053.494367043544],[318283.48217976745,-2054.023534766595],[318307.82389511634,-2058.2568765665583],[318322.1890349593,-2040.7555360091665],[318341.66240723897,-2032.7121865881272],[318345.895749039,-2017.8954902893693],[318331.92572110053,-2017.4721561082624],[318328.115713479,-2006.465467428361],[318339.5457363399,-2003.925462348383],[318338.27573379874,-1986.5687609696488],[318350.12909083907,-1980.6420824497],[318347.58908575866,-2011.5454775883154],[318349.7057566596,-2045.4122119902368],[318390.76917211805,-2067.848923528927],[318458.50264091976,-2073.775602048874],[318567.72285935935,-2088.592298349853],[318694.29977918137,-2123.729035290653],[318775.15660756174,-2147.859083549327],[318834.4233927615,-2173.259134349102],[318920.78356548306,-2213.899215630963],[319078.26388044376,-2282.056018609246],[319287.81429954246,-2395.9329130315673],[319316.17768960353,-2402.706259911509],[319344.1177454833,-2393.816242130475],[319358.0877734246,-2376.8828749306267],[319372.67629703414,-2165.073878233925],[319416.881835456,-2033.8234388107558],[319482.49863335583,-1976.6733245123742],[319482.0752991745,-1853.4830781301353],[319526.1020538965,-1800.9896398106011],[319567.58880353626,-1771.3562472108642],[319566.74213517644,-1749.3428698510597],[319533.72206913494,-1723.0961506912936],[319461.55289573595,-1713.1931217828806],[319438.0485444553,-1703.6227784114672],[319430.42852921505,-1689.2294162893722],[319439.74188117497,-1654.516013529681],[319510.86202341504,-1622.342615849966],[319551.5021046968,-1619.802610769988],[319596.37552777585,-1552.0691419705909],[319598.91553285625,-1507.1957188887664],[319574.3621504167,-1479.2556630090148],[319539.6487476565,-1486.8756782489472],[319491.38865113445,-1526.6690911708156],[319474.4552839352,-1552.0691419705909],[319455.0665784916,-1551.7728080433699],[319443.3190549966,-1534.6277737529672],[319438.2390448358,-1505.4177153343371],[319448.7165657934,-1489.2251829480938],[319468.71910579596,-1469.222642942992],[319496.97666231263,-1457.4751194494856],[319529.3617270831,-1426.6775578528159],[319541.53258475754,-1417.787540074005],[319544.1784233814,-1395.562495623646],[319534.6534043336,-1353.7582453470732],[319515.0741985068,-1345.291561747148],[319467.9782709824,-1359.0499225975818],[319431.4656979563,-1362.224928949221],[319412.4156598579,-1341.0582199471864],[319412.9448275808,-1319.3623432221011],[319426.21315114107,-1294.72437715229],[319443.10738790594,-1252.1580421479757],[319490.732483156,-1226.2288236229288],[319496.02416040655,-1207.1787855219864],[319485.44080590736,-1199.2412696473348],[319477.5032900302,-1136.7994780962235],[319479.61996093206,-1105.578582322889],[319468.2340353811,-986.1983435617276],[319424.3083182946,-874.973119525288],[319361.55382202286,-683.9377390399677],[319320.91374074016,-644.5676602992062],[319308.10788179655,-575.3525218703762],[319294.3495209459,-557.360819219979],[319273.1828119466,-508.67738851930153],[319237.72857437097,-458.935622370298],[319270.00780559704,-400.1980048938749],[319246.72442569584,-352.5729096437426],[319235.61190347,-326.11452339342213],[319272.6536442209,-311.8269948199377],[319277.94532147143,-293.3061244442688],[319243.54941934627,-251.50187416769586],[319213.38685902115,-237.2143455942114],[319144.59505476896,-227.68932654374112],[319075.80325051956,-181.12256674415403],[319061.6427221997,-150.78714496085922],[319037.17400659434,-139.8474841928546],[319015.605130123,-107.92455923596208],[318993.3800856732,-99.66954272659132],[318968.615036143,-74.26949192681604],[318951.470001854,-42.519428425986916],[318947.02499296423,-32.04190747135726],[318947.34249359835,6.058168728302917],[318937.320562887,30.81097922148001],[318908.9249167638,87.65583192452323],[318887.33487358317,127.34341130000394],[318847.9647948425,226.72111005606712],[318834.94726880826,297.84125229543497],[318819.07596017234,368.5543802912907],[318807.64221419767,413.4114834355205],[318790.8146805437,454.36906535210073],[318772.0821430776,558.8267742658936],[318737.79207449686,756.3121692369168],[318712.3920236975,780.1247168630944],[318690.4844798818,802.3497613134532],[318685.40446972195,840.132336878396],[318658.4169157464,989.0401346929066],[318654.2894074926,1004.9151664444325],[318634.6043681223,1023.6477039084311],[318586.0267709661,1019.0439447016688],[318531.0991611127,1066.9865405865203],[318553.6417061975,1102.2291110714832],[318559.3567176275,1131.121668855394],[318554.59420810174,1162.8717323562232],[318580.6292601712,1233.9918745978139],[318596.0544876987,1337.2941559066749],[318582.21676334646,1369.247145108282],[318611.7443224024,1421.6347498836476],[318635.23936939146,1493.7073940271766],[318661.47021352034,1520.6208645209626],[318668.4552274905,1556.8159369123096],[318632.8951563714,1595.55101438141],[318648.7701881202,1669.8461629724152],[318633.5301576406,1740.3313039423447],[318611.94011445995,1762.5563483927035],[318637.3401652593,1815.8964550722303],[318664.0102185998,1846.37651603196],[318682.42525542993,1908.6066404925186],[318684.33025924023,1980.3617840035477],[318675.91649241187,2014.8238320936216],[318654.64394986816,2063.401429250138],[318695.6015317822,2127.2190568842925],[318711.0003125807,2287.7685446503674],[316567.76460495684,2999.9040346896763],[315538.2158791926,3269.1445731717286],[314562.85392847005,3541.7717850915287],[313811.01242478564,3790.6922829337636],[312083.8089703787,4381.666798215181],[310636.4294089526,3571.8002895927457],[309688.2266975902,951.2434479881485]]]},"properties":{"Id":0,"Kecamatan":"Pontianak Utara"}}, +{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[319887.57044806925,-5373.344392278639],[319852.1480175494,-5334.047633417942],[319824.3302746851,-5279.321020009685],[319765.94275309215,-5207.270818364535],[319702.88422977563,-5132.534790727044],[319658.50971336546,-5076.48277000174],[319619.9739491157,-5025.101751000274],[319580.270434435,-4979.559484159208],[319542.9024206165,-4932.849466887184],[319498.52790420625,-4884.971699184203],[319465.83089211734,-4845.268184497927],[319416.78537397756,-4779.407060143594],[319352.5591002298,-4709.342034235556],[319288.3328264768,-4635.773757029033],[319225.2743031599,-4554.031226800181],[319187.90628934116,-4517.830963418014],[319145.8672737929,-4466.449944416539],[319063.0274988217,-4397.196101115128],[318970.88635908754,-4296.678494137728],[318712.6388119413,-4027.525809986318],[318700.9543592722,-4015.3479525993157],[318709.1286122945,-4000.167196985628],[318735.98687222344,-3974.4766874876964],[318748.6007874913,-3981.081929000221],[318860.6800702028,-3865.50016869716],[318901.807433543,-3845.790589901753],[319240.45505877363,-3500.8371123406214],[319266.1455682717,-3477.4821037046086],[319289.5005769076,-3471.6433515442072],[319331.5395924557,-3463.469098521879],[319351.39134979894,-3456.462595930516],[319371.24310713634,-3449.4560933391535],[319482.70326267194,-3416.1079811805625],[319520.35719185916,-3409.191953374463],[319930.7033710063,-3290.5899437818016],[319943.6860081592,-3268.9522151919746],[320015.48383422254,-3021.857923483452],[320060.2158619128,-2885.3158597254237],[319883.885546709,-2863.1286015203736],[319668.47127330344,-2832.0761712812755],[319652.3563173439,-2826.704519296623],[319561.58642752306,-2810.5798320879417],[319495.9512724161,-2782.734618262236],[319437.8048817517,-2773.211818269202],[319386.4238627501,-2753.3600609260684],[319352.5591002298,-2744.018057472783],[319302.34583165945,-2724.1663001296456],[319253.30031352554,-2703.146792361161],[319197.24829279474,-2679.2079085040614],[319158.7125285447,-2655.852899868049],[319074.63449745404,-2611.4783834579434],[319016.246975861,-2582.2846226671395],[318963.69820642885,-2558.9296140255133],[318900.63968311204,-2523.8971010743035],[318844.5876623867,-2490.0323385484376],[318807.21964856813,-2469.012830779956],[318734.81912179245,-2447.99332300586],[318611.86326987745,-2402.6633110638345],[318583.62701797124,-2397.4343755243854],[318516.91807503824,-2390.405046367276],[318504.7722867252,-2373.257295368376],[318433.53951038065,-2367.4185432079735],[318312.0934654712,-2349.9022867323624],[318232.6864361098,-2337.057031980595],[318170.79566322424,-2338.2247824115543],[318057.52387133683,-2327.7150285273115],[317964.74622543866,-2332.2209782429454],[317831.7500457056,-2325.396742533832],[317741.86880649073,-2329.042727579637],[317686.3608840788,-2317.3415121922267],[317647.97358792066,-2308.309207210856],[317505.6042941964,-2324.772986872912],[317450.6828969274,-2376.0793589098607],[317409.8116318156,-2413.058122584948],[317378.67162030103,-2415.004373303215],[317335.8541044656,-2411.111871866686],[317285.25158575136,-2411.111871866686],[317254.1115742368,-2418.8968747453605],[317228.81031488266,-2440.3056326631036],[317168.47654257156,-2451.9831369783014],[317139.28278177505,-2444.198134099631],[317104.72691741184,-2419.374652909264],[317087.420740484,-2422.4884900167626],[317058.12484471785,-2427.759593370711],[317034.18524291,-2455.8756384204476],[316961.72475783527,-2448.1651844011494],[316428.7982628549,-2576.067543195995],[316333.48672879336,-2588.4994824231076],[316290.7174679831,-2617.4144481542617],[316242.0455030631,-2600.426598820278],[315891.63306421525,-2646.1325691096436],[316008.4081073952,-2879.6826554753757],[316108.6562515756,-3080.1789438243754],[316099.98489745276,-3117.600883118676],[316159.4345105,-3231.040450875527],[316189.5124305546,-3242.160929183013],[316190.9886346372,-3291.250871420696],[316290.7174679831,-3481.5497677091553],[316374.4062489303,-3648.9273296033716],[316444.0134850881,-3719.8079814207367],[316545.5733060347,-3907.303035476732],[316558.55100204103,-3931.8164612599344],[316606.0100845777,-3959.3543193966816],[316644.93509897124,-4039.1505989016505],[316666.3438568887,-4078.0756132950055],[316681.9138626461,-4115.054376970092],[316715.00012487906,-4165.656895684263],[316755.87138999073,-4216.259414398428],[316796.74265510804,-4264.915682388709],[316960.2915036416,-4459.3151686055135],[317452.8107977186,-4958.79298897961],[317511.1983193059,-4982.14799761562],[317808.17965152155,-5293.137883236935],[317835.3917891925,-5281.669495876021],[318003.96436076245,-5498.157720267835],[318130.1060481742,-5630.249487280383],[318171.5591498216,-5724.218836670152],[318250.0367624292,-5855.174064717857],[318287.71731286065,-5890.871428284679],[318410.35862713464,-6071.669822687934],[318416.5135193256,-6096.893941284323],[318525.46364961116,-6295.854170744091],[318579.68996443006,-6371.771011489196],[318696.4650076103,-6517.739815465671],[318715.4221102912,-6536.677846952076],[318826.0334055243,-6682.970014070402],[318863.0121691994,-6747.196287818035],[318901.9371835927,-6786.121302211386],[318997.8492128665,-6873.389132317587],[319075.9838979524,-6815.516175584639],[319200.2395574156,-6725.148423245205],[319191.9285408274,-6699.123895043224],[319226.9610537845,-6681.607638562008],[319297.0260796923,-6629.058869129576],[319372.92985776067,-6568.725096818472],[319464.4036415865,-6506.445073789114],[319602.58744269,-6399.401284205985],[319661.3713138188,-6377.600065466999],[319929.8147521868,-6173.089029280636],[319974.32133015344,-6121.087431286495],[320003.54130222456,-6130.8191405916805],[320230.3441586008,-5948.45374608942],[320248.2236814376,-5940.501314505677],[319892.69977100904,-5382.870277737669],[319887.57044806925,-5373.344392278639]]]},"properties":{"Id":0,"Kecamatan":"Pontianak Timur"}}, +{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[316509.95719540527,-5101.833566810722],[316408.1359365364,-5203.782315435412],[316325.09491560137,-5300.663506526331],[316277.42321839795,-5368.326560621595],[316132.8703301034,-5610.529538348923],[315586.95250728936,-6227.493567962928],[315093.3197717309,-6783.407069222814],[314650.4343267438,-7312.870467518172],[314313.65685295156,-7710.390910327802],[314055.3070100423,-8097.146776349532],[313943.0478521116,-8266.304411587676],[313840.0154742847,-8421.621876669971],[313570.5827409144,-8808.522535934284],[313532.4561374881,-8860.509050278746],[313764.6634367695,-9082.566891445913],[314482.8144881896,-9756.429398367298],[314735.8516364164,-9990.009694709013],[315386.15532470803,-10595.173154648382],[315549.6609377029,-10756.07413279045],[315603.95862415945,-10800.010729939153],[315969.86388160125,-10324.183934093831],[316070.2870470217,-10131.32280160789],[316112.765529194,-10080.348623001111],[316116.5469964496,-10075.810862294282],[316137.4837201553,-10024.313580717127],[316174.390840571,-9967.415103409774],[316202.0711808827,-9921.28120289028],[316223.60033445846,-9882.836285790694],[316235.945734366,-9895.932656358724],[316248.20508140215,-9842.85357200713],[316265.9526893499,-9844.492162100709],[316258.9696581901,-9821.324418431366],[316286.1432427033,-9809.879784923392],[316389.8178299225,-9632.15192111897],[316654.18340597366,-9238.807034538575],[316735.68663022487,-9121.934486555845],[316955.59155603434,-8811.299556391281],[316992.49867644993,-8749.787689031953],[317037.0947802855,-8663.209735723693],[317061.6995272292,-8632.453802044038],[317135.5137680604,-8501.741083905486],[317370.6954695009,-8105.002669764531],[317656.4423947597,-7665.102797984467],[317804.04443023715,-7394.499066275981],[318021.28465803474,-6941.185008999439],[318148.9217828052,-6663.612707540501],[318253.2629668124,-6576.773915689321],[318377.3450655272,-6449.340610034038],[318368.0578102728,-6434.481001627012],[318328.6360094514,-6401.958423098472],[318236.68267524854,-6280.690804057879],[318229.65610871447,-6226.878449289301],[318202.7446667446,-6188.433532189729],[318058.17540597706,-5987.5423710395135],[318014.0167324725,-5894.597844288705],[317949.0082138875,-5824.744616427738],[317914.4077884978,-5744.010290518615],[317749.0946449697,-5555.630196730686],[317606.8484517013,-5417.2284951722295],[317403.09039107355,-5217.314926254428],[317160.8874133462,-5009.712373916721],[317003.2632532378,-4852.08821380847],[316876.39502680924,-4698.308545410153],[316771.0250557211,-4765.816074840871],[316705.52283150854,-4850.123247204937],[316595.7471319823,-4943.1257775002705],[316584.9825551945,-4963.117134392062],[316606.39071400976,-4977.715075073957],[316509.95719540527,-5101.833566810722]]]},"properties":{"Id":0,"Kecamatan":"Pontianak Tenggara"}}, +{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[310276.47296142485,-3455.9797973638633],[310115.07678222656,-3564.4591674809344],[310030.4100341797,-3651.7719116217922],[309858.4304809589,-3797.2929687509313],[309718.20098876953,-3942.8141479482874],[309527.70056152344,-4114.79357910133],[309408.63787841797,-4241.793823241489],[309318.6794433603,-4321.169067383977],[309256.67931494024,-4394.240588930203],[309308.096130372,-4450.815063477261],[309427.1588134775,-4575.169494627626],[309517.11724853516,-4686.294799805153],[309657.3467407236,-4823.878417967586],[309784.3470458975,-4961.462036132463],[309900.76403808687,-5093.753967286088],[309982.78485107515,-5167.837402344332],[310128.30603027437,-5329.233581543318],[310313.51483154483,-5530.317321778275],[310421.994140625,-5638.796691895346],[310514.59857177734,-5739.338562011602],[310612.494567872,-5850.463745115907],[310662.76544189546,-5895.442993162898],[310713.03637695406,-5951.005615234608],[310752.72393799014,-5993.339050291921],[310792.4114379892,-6043.609985352494],[310829.4533081064,-6083.297546385904],[310855.91162109375,-6120.339294434525],[310877.07849121094,-6175.901855469565],[310929.9950561542,-6255.277099609608],[310967.03692627046,-6345.235595703591],[310977.62023925874,-6427.256591796759],[310990.8494873047,-6485.465026855702],[311004.0785522461,-6551.611022949684],[311017.30780029483,-6599.236083983909],[311041.12036132906,-6633.631958008744],[311101.9745483408,-6689.194641112117],[311154.89141845703,-6739.46551513602],[311231.6207885761,-6813.5490722649265],[311295.12091064546,-6863.819946288946],[311340.10015869327,-6892.924194336752],[311522.6629638681,-6707.71551513765],[311670.8298950214,-6548.965209960006],[311784.60089111235,-6451.0691528309835],[311893.08026123233,-6324.068847656716],[311963.8046613168,-6246.005156220752],[312048.4717145385,-6169.275725068059],[312139.14343261905,-6078.005920408876],[312223.8102416992,-5995.984863281599],[312297.8936767578,-5916.60974120989],[312411.6647338886,-5805.484436034807],[312554.53997802734,-5670.546752930386],[312710.6444702158,-5522.379760743352],[312805.8948364258,-5416.546203613514],[312922.31152343843,-5310.71270752023],[313032.6743180966,-5200.19580923568],[313126.9781824285,-5107.2787843161495],[313210.70800781157,-5030.253723145346],[313292.7290649414,-4950.878601073637],[313407.04170880467,-4843.868031024118],[313546.7294311533,-4699.523986817105],[313655.20898437593,-4588.398681639577],[313761.0424194345,-4503.731872559176],[313851.00109863374,-4424.356750487466],[313962.12615966983,-4334.398193359375],[314070.605529787,-4239.1480102542555],[314192.31414795015,-4130.668640137068],[314247.8766479511,-4080.397766113165],[314335.1893920889,-4014.2517089850735],[314419.85614013765,-3937.5223999030422],[314536.2731323242,-3821.1055297851562],[314713.5443115253,-3659.709350586054],[314837.89862060733,-3530.063232422108],[314898.7530517578,-3487.729858398903],[314959.60723877046,-3408.3547363271937],[315036.3366699228,-3339.5629272459773],[315165.98266601656,-3260.187744140043],[315263.87866211124,-3191.395935058943],[315364.4206542978,-3135.8333740237867],[315480.8374023456,-3053.8123168940656],[315610.4836425772,-2977.0830078120343],[315705.7337036142,-2921.5203857427696],[315803.6297607431,-2876.541137695778],[315750.7131958008,-2791.8742675788235],[315660.75451660156,-2667.5198364258977],[315602.54602050874,-2606.6656494138297],[315533.75421142764,-2532.582153319032],[315475.2679967545,-2490.8043564147083],[315440.3429269055,-2480.4855857777875],[315380.2956542969,-2442.6235961909406],[315361.77471924014,-2432.0402832027758],[315335.31640625,-2463.7903442378156],[315315.76680293214,-2453.978527038824],[315306.2121582022,-2461.144531250582],[315282.8626119448,-2459.4511687088525],[315324.5345702879,-2412.6198250451125],[315334.4564651316,-2415.3979556019185],[315338.8220988652,-2404.6823091722326],[315328.90020402055,-2395.1572901209584],[315349.53774529416,-2369.36036352627],[315337.234595689,-2363.0103508270113],[315309.35759323835,-2397.780018719379],[315314.2157996511,-2401.110427027452],[315296.35638893116,-2424.922974653309],[315289.545646254,-2422.4905240247026],[315265.0032012258,-2453.101156009594],[315213.60778808687,-2413.519348145579],[315141.9717051638,-2345.1509401076473],[315152.6873515928,-2323.322771453066],[315126.49354920536,-2304.2727333528455],[315089.25347900484,-2291.810852050665],[315081.3158569336,-2281.2274169918383],[315092.1835903358,-2270.359641807154],[315103.4747531684,-2278.078930965392],[315107.7744140625,-2267.99829101644],[315086.40909403935,-2251.8851285779383],[315065.44091796875,-2233.6023559576133],[315059.818415856,-2241.1694821458077],[315080.8528329255,-2260.219520246028],[315073.3121928433,-2269.7445392948575],[315054.85754394624,-2254.769042967935],[314984.8088908363,-2194.338138482184],[314922.56561279483,-2140.9979858397273],[314926.4681491554,-2125.6786261638626],[314840.1124732327,-2057.2045107540907],[314845.8362426758,-2061.6228637704626],[314665.9193725586,-1921.3934326183517],[314607.7108764658,-1873.768310547457],[314597.12731933594,-1876.4141235346906],[314636.814880372,-1908.1641845697304],[314615.64825439546,-1905.518371582497],[314594.48162841983,-1900.2266845713602],[314581.25231933687,-1905.518371582497],[314557.4397583008,-1889.643371580867],[314533.6273803711,-1879.0599365244852],[314523.0438842783,-1871.1224365236703],[314525.68981933594,-1852.601562500582],[314496.5855712909,-1831.4348754876992],[314456.89801025484,-1908.1641845697304],[314414.5645141611,-1961.0809936517617],[314348.41864013765,-1984.893493651878],[314271.68927001953,-2016.6435546868015],[314187.02246093843,-2037.810302733793],[314078.54309082124,-2053.6853027354227],[313970.063720705,-2077.4978637696477],[313784.85498046875,-2103.9562988276593],[313716.06317138765,-2114.539611815824],[313639.33380126953,-2130.414672851679],[313546.7294311533,-2148.9354858405422],[313464.7085571289,-2167.456420897739],[313316.5416259784,-2188.6230468740687],[313247.74987793155,-2204.4981689463602],[313126.0411987314,-2228.310729980585],[313049.3118286133,-2246.831542969565],[312935.5408325214,-2270.64410400379],[312850.87402343843,-2294.4566650378983],[312692.12359619234,-2326.2066650388297],[312586.29016113374,-2352.665039062733],[312525.43572998233,-2360.602661131881],[312414.31066894624,-2400.290222167736],[312366.6854858408,-2413.519348145579],[312237.0392456064,-2453.206909178989],[312091.5183105478,-2503.4779052736703],[311906.3095092783,-2564.3322143565165],[311781.95520019624,-2617.248962401878],[311641.7256469736,-2670.1657714839093],[311498.8504028311,-2725.7283935555024],[311385.0793457031,-2783.936767577892],[311258.07910156343,-2842.14526367106],[311141.66210937407,-2881.832824706915],[311043.7661132822,-2926.8121337880148],[310951.16168212984,-2977.0830078120343],[310773.8905639658,-3093.4998779299203],[310660.119506835,-3162.2916870111367],[310559.57775879,-3244.312744140858],[310429.9315185547,-3344.854614257114],[310276.47296142485,-3455.9797973638633]]]},"properties":{"Id":0,"Kecamatan":"Pontianak Kota"}}, +{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[314496.5855712909,-1831.4348754876992],[314473.8377594892,-1765.7857139359694],[314444.73353461176,-1736.6814890607493],[314402.40011661407,-1728.7439731854247],[314333.6083123619,-1673.1813620609464],[314272.75402398873,-1638.785459933919],[314203.96221973654,-1596.4520419340115],[314153.69128586166,-1559.4103011834668],[314092.8369974848,-1551.472785310587],[314031.98270911165,-1511.7852059341967],[313976.42009798624,-1469.4517879342893],[313997.5868069865,-1421.8266926850192],[313971.1284207348,-1392.7224678097991],[313918.211648236,-1347.7432111840462],[313867.94071436115,-1321.2848249346716],[313849.41984398477,-1355.6807270592544],[313820.3156191092,-1334.514018059359],[313820.3156191092,-1278.9514069323195],[313775.3363624858,-1241.909666184336],[313709.19039686024,-1196.9304095584666],[313680.0861719847,-1239.263827558374],[313637.7527539851,-1210.159602683154],[313510.7524999855,-1122.8469280574936],[313412.8564708587,-1024.9508989329915],[313309.66876448225,-940.2840629332932],[313246.16863748245,-882.075613182853],[313214.41857398394,-818.575486180489],[313156.21012423374,-776.2420681805816],[313053.0224178573,-651.8876528069377],[312973.64725910686,-612.2000734304311],[312883.6887458572,-572.5124940564856],[312801.66774848104,-514.3040443060454],[312690.5425262293,-424.3455310544232],[312529.14637010545,-331.7411791794002],[312418.0211478537,-307.9286315535428],[312253.9791531032,-247.0743431795854],[312129.62473772746,-204.74092517967802],[312042.3120631045,-188.86589342914522],[311875.62422972824,-157.1158299279632],[311745.9781371029,-130.65744367870502],[311526.37353122514,-96.26154155412223],[311333.2273116,-88.32402567879763],[311174.4769940991,-106.84489605284762],[311042.18506284803,-130.65744367870502],[310896.6639384739,-149.17831405519973],[310801.4137479728,-175.63670030445792],[310724.6844278481,-202.09508655383252],[310618.85088284593,-188.86589342914522],[310534.1840468468,-172.99086167861242],[310457.4547267221,-157.1158299279632],[310378.07956797164,-167.6991844291333],[310303.9960864708,-154.46999130456243],[310192.8708642218,-112.13657330465503],[310076.4539647205,-64.51147805294022],[309957.3912265934,-40.698930429527536],[309872.7243905943,6.926164822187275],[309806.5784249678,20.155357946874574],[309732.49494346976,70.42629182199016],[309629.30723709334,128.63474157243036],[309584.32798046805,128.63474157243036],[309489.07778996695,152.44728919828776],[309409.7026312165,144.50977332307957],[309359.4316973407,157.73896644765045],[309351.49418146536,70.42629182199016],[309343.5566655928,-38.05309180356562],[309322.3899565926,-154.46999130456243],[309319.74411796685,-281.4702453041682],[309319.74411796685,-400.5329834310105],[309343.5566655928,-535.4707533059409],[309364.7233745931,-715.3877798067406],[309362.07753596734,-842.3880338063464],[309351.49418146536,-974.679965057876],[309322.3899565926,-1051.4092851823661],[309277.4106999673,-1159.8886688080383],[309253.5981523413,-1252.4930206830613],[309224.49392746575,-1310.7014704335015],[309203.32721846644,-1368.9099201839417],[309208.61889571603,-1400.6599836851237],[309216.5564115904,-1442.9934016850311],[309232.4314433411,-1506.493528684834],[309237.72312059347,-1562.0561398094287],[309211.26473434176,-1649.368814435089],[309187.4521867158,-1765.7857139359694],[309176.8688322166,-1879.5567748110043],[309190.0980253415,-1929.8277086861199],[309200.6813798407,-1977.45280393539],[309205.97305709217,-2040.952930937754],[309145.1187687153,-2059.4738013116876],[309052.51441684086,-2093.8697034363868],[308838.2014882155,-2199.703248436097],[308711.20123421587,-2289.661761687603],[308613.30520508904,-2400.786983939237],[308552.45091671497,-2472.2246268143645],[308412.22146958765,-2668.016685063136],[308250.825313461,-2877.0379364391556],[308147.6376070874,-3011.9757063165307],[308182.03350921255,-3083.413349191658],[308256.1169907134,-3279.205407440546],[308356.65885846317,-3538.4975926916813],[308430.74233996496,-3734.289650943014],[308507.47166008875,-3922.1441933190217],[308645.05526859034,-4107.352897069184],[308827.6181337144,-4363.999243696919],[308949.3267104672,-4546.562108821119],[308983.72261259146,-4514.812045322382],[309031.3477078406,-4456.603595571942],[309094.8478348404,-4408.978500320227],[309142.47293009236,-4490.9994976965245],[309252.53297139704,-4394.184753706562],[309308.0955825215,-4329.097123530693],[309379.23520107474,-4256.687154644518],[309479.5459254207,-4168.759302856284],[309570.03360639606,-4076.6841187049868],[309677.82659467123,-3978.690493005095],[309759.4043367142,-3898.7716525178403],[309836.73413979914,-3819.5086043535266],[309916.1092985496,-3743.308451952762],[310007.24186643306,-3657.238962248084],[310088.79366058577,-3585.7746910545975],[310164.27525960375,-3523.3199474809226],[310276.47296142485,-3455.9797973638633],[310359.6303931121,-3382.223241257365],[310429.9315185547,-3344.854614257114],[310535.3784826426,-3261.3940289586317],[310601.91067015193,-3211.494888325804],[310641.45226506423,-3177.5202555787982],[310773.8905639658,-3093.4998779299203],[310854.72350444365,-3040.4155513329897],[310936.8738400778,-2986.069437475526],[311087.68664170336,-2906.69427872519],[311258.07910156343,-2842.14526367106],[311336.9246401787,-2797.156559649622],[311460.7498878287,-2741.593948525144],[311581.4001291292,-2690.7938469237415],[311709.98788630776,-2636.8187389753293],[311821.1131085567,-2593.9561532492517],[311906.3095092783,-2564.3322143565165],[311986.6975354152,-2525.010773507296],[312105.3024638882,-2483.766410747543],[312237.0392456064,-2453.206909178989],[312366.6854858408,-2413.519348145579],[312423.85736329015,-2387.87197934452],[312525.43572998233,-2360.602661131881],[312586.29016113374,-2352.665039062733],[312694.23985481076,-2312.968091271934],[312751.3899691114,-2301.8555690470384],[312852.99017231166,-2284.3930341228843],[312935.5408325214,-2270.64410400379],[313003.98220338486,-2251.9642615312478],[313125.56844345294,-2227.800214529503],[313194.53486581706,-2213.043585868436],[313263.3202168038,-2198.6979779073736],[313354.17315057106,-2184.5830654097954],[313443.7728642933,-2165.418490619166],[313551.7230801927,-2147.955955692567],[313589.624866033,-2140.5861640019575],[313691.4233595934,-2122.555904893088],[313764.44850564376,-2106.6808731425554],[313821.5986199444,-2098.7433572672307],[313910.2342138821,-2084.191244830843],[313970.063720705,-2077.4978637696477],[314039.88030650746,-2057.732858581585],[314112.6408686973,-2048.472423392115],[314166.88056050986,-2039.2119882050902],[314239.6411226969,-2024.6598757687025],[314348.41864013765,-1984.893493651878],[314405.0060367584,-1955.8680715169758],[314456.89801025484,-1908.1641845697304],[314496.5855712909,-1831.4348754876992]]]},"properties":{"Id":0,"Kecamatan":"Pontianak Barat"}} +]} \ No newline at end of file diff --git a/penduduk/us-states.js b/penduduk/us-states.js new file mode 100644 index 0000000..7965ee4 --- /dev/null +++ b/penduduk/us-states.js @@ -0,0 +1,4386 @@ +var statesData = { + type: "FeatureCollection", + features: [ + { + type: "Feature", + id: "01", + properties: { name: "Alabama", density: 94.65 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-87.359296, 35.00118], + [-85.606675, 34.984749], + [-85.431413, 34.124869], + [-85.184951, 32.859696], + [-85.069935, 32.580372], + [-84.960397, 32.421541], + [-85.004212, 32.322956], + [-84.889196, 32.262709], + [-85.058981, 32.13674], + [-85.053504, 32.01077], + [-85.141136, 31.840985], + [-85.042551, 31.539753], + [-85.113751, 31.27686], + [-85.004212, 31.003013], + [-85.497137, 30.997536], + [-87.600282, 30.997536], + [-87.633143, 30.86609], + [-87.408589, 30.674397], + [-87.446927, 30.510088], + [-87.37025, 30.427934], + [-87.518128, 30.280057], + [-87.655051, 30.247195], + [-87.90699, 30.411504], + [-87.934375, 30.657966], + [-88.011052, 30.685351], + [-88.10416, 30.499135], + [-88.137022, 30.318396], + [-88.394438, 30.367688], + [-88.471115, 31.895754], + [-88.241084, 33.796253], + [-88.098683, 34.891641], + [-88.202745, 34.995703], + [-87.359296, 35.00118], + ], + ], + }, + }, + { + type: "Feature", + id: "02", + properties: { name: "Alaska", density: 1.264 }, + geometry: { + type: "MultiPolygon", + coordinates: [ + [ + [ + [-131.602021, 55.117982], + [-131.569159, 55.28229], + [-131.355558, 55.183705], + [-131.38842, 55.01392], + [-131.645836, 55.035827], + [-131.602021, 55.117982], + ], + ], + [ + [ + [-131.832052, 55.42469], + [-131.645836, 55.304197], + [-131.749898, 55.128935], + [-131.832052, 55.189182], + [-131.832052, 55.42469], + ], + ], + [ + [ + [-132.976733, 56.437924], + [-132.735747, 56.459832], + [-132.631685, 56.421493], + [-132.664547, 56.273616], + [-132.878148, 56.240754], + [-133.069841, 56.333862], + [-132.976733, 56.437924], + ], + ], + [ + [ + [-133.595627, 56.350293], + [-133.162949, 56.317431], + [-133.05341, 56.125739], + [-132.620732, 55.912138], + [-132.472854, 55.780691], + [-132.4619, 55.671152], + [-132.357838, 55.649245], + [-132.341408, 55.506844], + [-132.166146, 55.364444], + [-132.144238, 55.238474], + [-132.029222, 55.276813], + [-131.97993, 55.178228], + [-131.958022, 54.789365], + [-132.029222, 54.701734], + [-132.308546, 54.718165], + [-132.385223, 54.915335], + [-132.483808, 54.898904], + [-132.686455, 55.046781], + [-132.746701, 54.997489], + [-132.916486, 55.046781], + [-132.889102, 54.898904], + [-132.73027, 54.937242], + [-132.626209, 54.882473], + [-132.675501, 54.679826], + [-132.867194, 54.701734], + [-133.157472, 54.95915], + [-133.239626, 55.090597], + [-133.223195, 55.22752], + [-133.453227, 55.216566], + [-133.453227, 55.320628], + [-133.277964, 55.331582], + [-133.102702, 55.42469], + [-133.17938, 55.588998], + [-133.387503, 55.62186], + [-133.420365, 55.884753], + [-133.497042, 56.0162], + [-133.639442, 55.923092], + [-133.694212, 56.070969], + [-133.546335, 56.142169], + [-133.666827, 56.311955], + [-133.595627, 56.350293], + ], + ], + [ + [ + [-133.738027, 55.556137], + [-133.546335, 55.490413], + [-133.414888, 55.572568], + [-133.283441, 55.534229], + [-133.420365, 55.386352], + [-133.633966, 55.430167], + [-133.738027, 55.556137], + ], + ], + [ + [ + [-133.907813, 56.930849], + [-134.050213, 57.029434], + [-133.885905, 57.095157], + [-133.343688, 57.002049], + [-133.102702, 57.007526], + [-132.932917, 56.82131], + [-132.620732, 56.667956], + [-132.653593, 56.55294], + [-132.817901, 56.492694], + [-133.042456, 56.520078], + [-133.201287, 56.448878], + [-133.420365, 56.492694], + [-133.66135, 56.448878], + [-133.710643, 56.684386], + [-133.688735, 56.837741], + [-133.869474, 56.843218], + [-133.907813, 56.930849], + ], + ], + [ + [ + [-134.115936, 56.48174], + [-134.25286, 56.558417], + [-134.400737, 56.722725], + [-134.417168, 56.848695], + [-134.296675, 56.908941], + [-134.170706, 56.848695], + [-134.143321, 56.952757], + [-133.748981, 56.772017], + [-133.710643, 56.596755], + [-133.847566, 56.574848], + [-133.935197, 56.377678], + [-133.836612, 56.322908], + [-133.957105, 56.092877], + [-134.110459, 56.142169], + [-134.132367, 55.999769], + [-134.230952, 56.070969], + [-134.291198, 56.350293], + [-134.115936, 56.48174], + ], + ], + [ + [ + [-134.636246, 56.28457], + [-134.669107, 56.169554], + [-134.806031, 56.235277], + [-135.178463, 56.67891], + [-135.413971, 56.810356], + [-135.331817, 56.914418], + [-135.424925, 57.166357], + [-135.687818, 57.369004], + [-135.419448, 57.566174], + [-135.298955, 57.48402], + [-135.063447, 57.418296], + [-134.849846, 57.407343], + [-134.844369, 57.248511], + [-134.636246, 56.728202], + [-134.636246, 56.28457], + ], + ], + [ + [ + [-134.712923, 58.223407], + [-134.373353, 58.14673], + [-134.176183, 58.157683], + [-134.187137, 58.081006], + [-133.902336, 57.807159], + [-134.099505, 57.850975], + [-134.148798, 57.757867], + [-133.935197, 57.615466], + [-133.869474, 57.363527], + [-134.083075, 57.297804], + [-134.154275, 57.210173], + [-134.499322, 57.029434], + [-134.603384, 57.034911], + [-134.6472, 57.226604], + [-134.575999, 57.341619], + [-134.608861, 57.511404], + [-134.729354, 57.719528], + [-134.707446, 57.829067], + [-134.784123, 58.097437], + [-134.91557, 58.212453], + [-134.953908, 58.409623], + [-134.712923, 58.223407], + ], + ], + [ + [ + [-135.857603, 57.330665], + [-135.715203, 57.330665], + [-135.567326, 57.149926], + [-135.633049, 57.023957], + [-135.857603, 56.996572], + [-135.824742, 57.193742], + [-135.857603, 57.330665], + ], + ], + [ + [ + [-136.279328, 58.206976], + [-135.978096, 58.201499], + [-135.780926, 58.28913], + [-135.496125, 58.168637], + [-135.64948, 58.037191], + [-135.59471, 57.987898], + [-135.45231, 58.135776], + [-135.107263, 58.086483], + [-134.91557, 57.976944], + [-135.025108, 57.779775], + [-134.937477, 57.763344], + [-134.822462, 57.500451], + [-135.085355, 57.462112], + [-135.572802, 57.675713], + [-135.556372, 57.456635], + [-135.709726, 57.369004], + [-135.890465, 57.407343], + [-136.000004, 57.544266], + [-136.208128, 57.637374], + [-136.366959, 57.829067], + [-136.569606, 57.916698], + [-136.558652, 58.075529], + [-136.421728, 58.130299], + [-136.377913, 58.267222], + [-136.279328, 58.206976], + ], + ], + [ + [ + [-147.079854, 60.200582], + [-147.501579, 59.948643], + [-147.53444, 59.850058], + [-147.874011, 59.784335], + [-147.80281, 59.937689], + [-147.435855, 60.09652], + [-147.205824, 60.271782], + [-147.079854, 60.200582], + ], + ], + [ + [ + [-147.561825, 60.578491], + [-147.616594, 60.370367], + [-147.758995, 60.156767], + [-147.956165, 60.227967], + [-147.791856, 60.474429], + [-147.561825, 60.578491], + ], + ], + [ + [ + [-147.786379, 70.245291], + [-147.682318, 70.201475], + [-147.162008, 70.15766], + [-146.888161, 70.185044], + [-146.510252, 70.185044], + [-146.099482, 70.146706], + [-145.858496, 70.168614], + [-145.622988, 70.08646], + [-145.195787, 69.993352], + [-144.620708, 69.971444], + [-144.461877, 70.026213], + [-144.078491, 70.059075], + [-143.914183, 70.130275], + [-143.497935, 70.141229], + [-143.503412, 70.091936], + [-143.25695, 70.119321], + [-142.747594, 70.042644], + [-142.402547, 69.916674], + [-142.079408, 69.856428], + [-142.008207, 69.801659], + [-141.712453, 69.790705], + [-141.433129, 69.697597], + [-141.378359, 69.63735], + [-141.208574, 69.686643], + [-141.00045, 69.648304], + [-141.00045, 60.304644], + [-140.53491, 60.22249], + [-140.474664, 60.310121], + [-139.987216, 60.184151], + [-139.696939, 60.342983], + [-139.088998, 60.359413], + [-139.198537, 60.091043], + [-139.045183, 59.997935], + [-138.700135, 59.910304], + [-138.623458, 59.767904], + [-137.604747, 59.242118], + [-137.445916, 58.908024], + [-137.265177, 59.001132], + [-136.827022, 59.159963], + [-136.580559, 59.16544], + [-136.465544, 59.285933], + [-136.476498, 59.466672], + [-136.301236, 59.466672], + [-136.25742, 59.625503], + [-135.945234, 59.663842], + [-135.479694, 59.800766], + [-135.025108, 59.565257], + [-135.068924, 59.422857], + [-134.959385, 59.280456], + [-134.701969, 59.247595], + [-134.378829, 59.033994], + [-134.400737, 58.973748], + [-134.25286, 58.858732], + [-133.842089, 58.727285], + [-133.173903, 58.152206], + [-133.075318, 57.998852], + [-132.867194, 57.845498], + [-132.560485, 57.505928], + [-132.253777, 57.21565], + [-132.368792, 57.095157], + [-132.05113, 57.051341], + [-132.127807, 56.876079], + [-131.870391, 56.804879], + [-131.837529, 56.602232], + [-131.580113, 56.613186], + [-131.087188, 56.405062], + [-130.78048, 56.366724], + [-130.621648, 56.268139], + [-130.468294, 56.240754], + [-130.424478, 56.142169], + [-130.101339, 56.114785], + [-130.002754, 55.994292], + [-130.150631, 55.769737], + [-130.128724, 55.583521], + [-129.986323, 55.276813], + [-130.095862, 55.200136], + [-130.336847, 54.920812], + [-130.687372, 54.718165], + [-130.785957, 54.822227], + [-130.917403, 54.789365], + [-131.010511, 54.997489], + [-130.983126, 55.08512], + [-131.092665, 55.189182], + [-130.862634, 55.298721], + [-130.928357, 55.337059], + [-131.158389, 55.200136], + [-131.284358, 55.287767], + [-131.426759, 55.238474], + [-131.843006, 55.457552], + [-131.700606, 55.698537], + [-131.963499, 55.616383], + [-131.974453, 55.49589], + [-132.182576, 55.588998], + [-132.226392, 55.704014], + [-132.083991, 55.829984], + [-132.127807, 55.955953], + [-132.324977, 55.851892], + [-132.522147, 56.076446], + [-132.642639, 56.032631], + [-132.719317, 56.218847], + [-132.527624, 56.339339], + [-132.341408, 56.339339], + [-132.396177, 56.487217], + [-132.297592, 56.67891], + [-132.450946, 56.673433], + [-132.768609, 56.837741], + [-132.993164, 57.034911], + [-133.51895, 57.177311], + [-133.507996, 57.577128], + [-133.677781, 57.62642], + [-133.639442, 57.790728], + [-133.814705, 57.834544], + [-134.072121, 58.053622], + [-134.143321, 58.168637], + [-134.586953, 58.206976], + [-135.074401, 58.502731], + [-135.282525, 59.192825], + [-135.38111, 59.033994], + [-135.337294, 58.891593], + [-135.140124, 58.617746], + [-135.189417, 58.573931], + [-135.05797, 58.349376], + [-135.085355, 58.201499], + [-135.277048, 58.234361], + [-135.430402, 58.398669], + [-135.633049, 58.426053], + [-135.91785, 58.382238], + [-135.912373, 58.617746], + [-136.087635, 58.814916], + [-136.246466, 58.75467], + [-136.876314, 58.962794], + [-136.931084, 58.902547], + [-136.586036, 58.836824], + [-136.317666, 58.672516], + [-136.213604, 58.667039], + [-136.180743, 58.535592], + [-136.043819, 58.382238], + [-136.388867, 58.294607], + [-136.591513, 58.349376], + [-136.59699, 58.212453], + [-136.859883, 58.316515], + [-136.947514, 58.393192], + [-137.111823, 58.393192], + [-137.566409, 58.590362], + [-137.900502, 58.765624], + [-137.933364, 58.869686], + [-138.11958, 59.02304], + [-138.634412, 59.132579], + [-138.919213, 59.247595], + [-139.417615, 59.379041], + [-139.746231, 59.505011], + [-139.718846, 59.641934], + [-139.625738, 59.598119], + [-139.5162, 59.68575], + [-139.625738, 59.88292], + [-139.488815, 59.992458], + [-139.554538, 60.041751], + [-139.801, 59.833627], + [-140.315833, 59.696704], + [-140.92925, 59.745996], + [-141.444083, 59.871966], + [-141.46599, 59.970551], + [-141.706976, 59.948643], + [-141.964392, 60.019843], + [-142.539471, 60.085566], + [-142.873564, 60.091043], + [-143.623905, 60.036274], + [-143.892275, 59.997935], + [-144.231845, 60.140336], + [-144.65357, 60.206059], + [-144.785016, 60.29369], + [-144.834309, 60.441568], + [-145.124586, 60.430614], + [-145.223171, 60.299167], + [-145.738004, 60.474429], + [-145.820158, 60.551106], + [-146.351421, 60.408706], + [-146.608837, 60.238921], + [-146.718376, 60.397752], + [-146.608837, 60.485383], + [-146.455483, 60.463475], + [-145.951604, 60.578491], + [-146.017328, 60.666122], + [-146.252836, 60.622307], + [-146.345944, 60.737322], + [-146.565022, 60.753753], + [-146.784099, 61.044031], + [-146.866253, 60.972831], + [-147.172962, 60.934492], + [-147.271547, 60.972831], + [-147.375609, 60.879723], + [-147.758995, 60.912584], + [-147.775426, 60.808523], + [-148.032842, 60.781138], + [-148.153334, 60.819476], + [-148.065703, 61.005692], + [-148.175242, 61.000215], + [-148.350504, 60.803046], + [-148.109519, 60.737322], + [-148.087611, 60.594922], + [-147.939734, 60.441568], + [-148.027365, 60.277259], + [-148.219058, 60.332029], + [-148.273827, 60.249875], + [-148.087611, 60.217013], + [-147.983549, 59.997935], + [-148.251919, 59.95412], + [-148.399797, 59.997935], + [-148.635305, 59.937689], + [-148.755798, 59.986981], + [-149.067984, 59.981505], + [-149.05703, 60.063659], + [-149.204907, 60.008889], + [-149.287061, 59.904827], + [-149.418508, 59.997935], + [-149.582816, 59.866489], + [-149.511616, 59.806242], + [-149.741647, 59.729565], + [-149.949771, 59.718611], + [-150.031925, 59.61455], + [-150.25648, 59.521442], + [-150.409834, 59.554303], + [-150.579619, 59.444764], + [-150.716543, 59.450241], + [-151.001343, 59.225687], + [-151.308052, 59.209256], + [-151.406637, 59.280456], + [-151.592853, 59.159963], + [-151.976239, 59.253071], + [-151.888608, 59.422857], + [-151.636669, 59.483103], + [-151.47236, 59.472149], + [-151.423068, 59.537872], + [-151.127313, 59.669319], + [-151.116359, 59.778858], + [-151.505222, 59.63098], + [-151.828361, 59.718611], + [-151.8667, 59.778858], + [-151.702392, 60.030797], + [-151.423068, 60.211536], + [-151.379252, 60.359413], + [-151.297098, 60.386798], + [-151.264237, 60.545629], + [-151.406637, 60.720892], + [-151.06159, 60.786615], + [-150.404357, 61.038554], + [-150.245526, 60.939969], + [-150.042879, 60.912584], + [-149.741647, 61.016646], + [-150.075741, 61.15357], + [-150.207187, 61.257632], + [-150.47008, 61.246678], + [-150.656296, 61.29597], + [-150.711066, 61.252155], + [-151.023251, 61.180954], + [-151.165652, 61.044031], + [-151.477837, 61.011169], + [-151.800977, 60.852338], + [-151.833838, 60.748276], + [-152.080301, 60.693507], + [-152.13507, 60.578491], + [-152.310332, 60.507291], + [-152.392486, 60.304644], + [-152.732057, 60.173197], + [-152.567748, 60.069136], + [-152.704672, 59.915781], + [-153.022334, 59.888397], + [-153.049719, 59.691227], + [-153.345474, 59.620026], + [-153.438582, 59.702181], + [-153.586459, 59.548826], + [-153.761721, 59.543349], + [-153.72886, 59.433811], + [-154.117723, 59.368087], + [-154.1944, 59.066856], + [-153.750768, 59.050425], + [-153.400243, 58.968271], + [-153.301658, 58.869686], + [-153.444059, 58.710854], + [-153.679567, 58.612269], + [-153.898645, 58.606793], + [-153.920553, 58.519161], + [-154.062953, 58.4863], + [-153.99723, 58.376761], + [-154.145107, 58.212453], + [-154.46277, 58.059098], + [-154.643509, 58.059098], + [-154.818771, 58.004329], + [-154.988556, 58.015283], + [-155.120003, 57.955037], + [-155.081664, 57.872883], + [-155.328126, 57.829067], + [-155.377419, 57.708574], + [-155.547204, 57.785251], + [-155.73342, 57.549743], + [-156.045606, 57.566174], + [-156.023698, 57.440204], + [-156.209914, 57.473066], + [-156.34136, 57.418296], + [-156.34136, 57.248511], + [-156.549484, 56.985618], + [-156.883577, 56.952757], + [-157.157424, 56.832264], + [-157.20124, 56.766541], + [-157.376502, 56.859649], + [-157.672257, 56.607709], + [-157.754411, 56.67891], + [-157.918719, 56.657002], + [-157.957058, 56.514601], + [-158.126843, 56.459832], + [-158.32949, 56.48174], + [-158.488321, 56.339339], + [-158.208997, 56.295524], + [-158.510229, 55.977861], + [-159.375585, 55.873799], + [-159.616571, 55.594475], + [-159.676817, 55.654722], + [-159.643955, 55.829984], + [-159.813741, 55.857368], + [-160.027341, 55.791645], + [-160.060203, 55.720445], + [-160.394296, 55.605429], + [-160.536697, 55.473983], + [-160.580512, 55.567091], + [-160.668143, 55.457552], + [-160.865313, 55.528752], + [-161.232268, 55.358967], + [-161.506115, 55.364444], + [-161.467776, 55.49589], + [-161.588269, 55.62186], + [-161.697808, 55.517798], + [-161.686854, 55.408259], + [-162.053809, 55.074166], + [-162.179779, 55.15632], + [-162.218117, 55.03035], + [-162.470057, 55.052258], + [-162.508395, 55.249428], + [-162.661749, 55.293244], + [-162.716519, 55.222043], + [-162.579595, 55.134412], + [-162.645319, 54.997489], + [-162.847965, 54.926289], + [-163.00132, 55.079643], + [-163.187536, 55.090597], + [-163.220397, 55.03035], + [-163.034181, 54.942719], + [-163.373752, 54.800319], + [-163.14372, 54.76198], + [-163.138243, 54.696257], + [-163.329936, 54.74555], + [-163.587352, 54.614103], + [-164.085754, 54.61958], + [-164.332216, 54.531949], + [-164.354124, 54.466226], + [-164.638925, 54.389548], + [-164.847049, 54.416933], + [-164.918249, 54.603149], + [-164.710125, 54.663395], + [-164.551294, 54.88795], + [-164.34317, 54.893427], + [-163.894061, 55.041304], + [-163.532583, 55.046781], + [-163.39566, 54.904381], + [-163.291598, 55.008443], + [-163.313505, 55.128935], + [-163.105382, 55.183705], + [-162.880827, 55.183705], + [-162.579595, 55.446598], + [-162.245502, 55.682106], + [-161.807347, 55.89023], + [-161.292514, 55.983338], + [-161.078914, 55.939523], + [-160.87079, 55.999769], + [-160.816021, 55.912138], + [-160.931036, 55.813553], + [-160.805067, 55.736876], + [-160.766728, 55.857368], + [-160.509312, 55.868322], + [-160.438112, 55.791645], + [-160.27928, 55.76426], + [-160.273803, 55.857368], + [-160.536697, 55.939523], + [-160.558604, 55.994292], + [-160.383342, 56.251708], + [-160.147834, 56.399586], + [-159.830171, 56.541986], + [-159.326293, 56.667956], + [-158.959338, 56.848695], + [-158.784076, 56.782971], + [-158.641675, 56.810356], + [-158.701922, 56.925372], + [-158.658106, 57.034911], + [-158.378782, 57.264942], + [-157.995396, 57.41282], + [-157.688688, 57.609989], + [-157.705118, 57.719528], + [-157.458656, 58.497254], + [-157.07527, 58.705377], + [-157.119086, 58.869686], + [-158.039212, 58.634177], + [-158.32949, 58.661562], + [-158.40069, 58.760147], + [-158.564998, 58.803962], + [-158.619768, 58.913501], + [-158.767645, 58.864209], + [-158.860753, 58.694424], + [-158.701922, 58.480823], + [-158.893615, 58.387715], + [-159.0634, 58.420577], + [-159.392016, 58.760147], + [-159.616571, 58.929932], + [-159.731586, 58.929932], + [-159.808264, 58.803962], + [-159.906848, 58.782055], + [-160.054726, 58.886116], + [-160.235465, 58.902547], + [-160.317619, 59.072332], + [-160.854359, 58.88064], + [-161.33633, 58.743716], + [-161.374669, 58.667039], + [-161.752577, 58.552023], + [-161.938793, 58.656085], + [-161.769008, 58.776578], + [-161.829255, 59.061379], + [-161.955224, 59.36261], + [-161.703285, 59.48858], + [-161.911409, 59.740519], + [-162.092148, 59.88292], + [-162.234548, 60.091043], + [-162.448149, 60.178674], + [-162.502918, 59.997935], + [-162.760334, 59.959597], + [-163.171105, 59.844581], + [-163.66403, 59.795289], + [-163.9324, 59.806242], + [-164.162431, 59.866489], + [-164.189816, 60.02532], + [-164.386986, 60.074613], + [-164.699171, 60.29369], + [-164.962064, 60.337506], + [-165.268773, 60.578491], + [-165.060649, 60.68803], + [-165.016834, 60.890677], + [-165.175665, 60.846861], + [-165.197573, 60.972831], + [-165.120896, 61.076893], + [-165.323543, 61.170001], + [-165.34545, 61.071416], + [-165.591913, 61.109754], + [-165.624774, 61.279539], + [-165.816467, 61.301447], + [-165.920529, 61.416463], + [-165.915052, 61.558863], + [-166.106745, 61.49314], + [-166.139607, 61.630064], + [-165.904098, 61.662925], + [-166.095791, 61.81628], + [-165.756221, 61.827233], + [-165.756221, 62.013449], + [-165.674067, 62.139419], + [-165.044219, 62.539236], + [-164.912772, 62.659728], + [-164.819664, 62.637821], + [-164.874433, 62.807606], + [-164.633448, 63.097884], + [-164.425324, 63.212899], + [-164.036462, 63.262192], + [-163.73523, 63.212899], + [-163.313505, 63.037637], + [-163.039658, 63.059545], + [-162.661749, 63.22933], + [-162.272887, 63.486746], + [-162.075717, 63.514131], + [-162.026424, 63.448408], + [-161.555408, 63.448408], + [-161.13916, 63.503177], + [-160.766728, 63.771547], + [-160.766728, 63.837271], + [-160.952944, 64.08921], + [-160.974852, 64.237087], + [-161.26513, 64.395918], + [-161.374669, 64.532842], + [-161.078914, 64.494503], + [-160.79959, 64.609519], + [-160.783159, 64.719058], + [-161.144637, 64.921705], + [-161.413007, 64.762873], + [-161.664946, 64.790258], + [-161.900455, 64.702627], + [-162.168825, 64.680719], + [-162.234548, 64.620473], + [-162.541257, 64.532842], + [-162.634365, 64.384965], + [-162.787719, 64.324718], + [-162.858919, 64.49998], + [-163.045135, 64.538319], + [-163.176582, 64.401395], + [-163.253259, 64.467119], + [-163.598306, 64.565704], + [-164.304832, 64.560227], + [-164.80871, 64.450688], + [-165.000403, 64.434257], + [-165.411174, 64.49998], + [-166.188899, 64.576658], + [-166.391546, 64.636904], + [-166.484654, 64.735489], + [-166.413454, 64.872412], + [-166.692778, 64.987428], + [-166.638008, 65.113398], + [-166.462746, 65.179121], + [-166.517516, 65.337952], + [-166.796839, 65.337952], + [-167.026871, 65.381768], + [-167.47598, 65.414629], + [-167.711489, 65.496784], + [-168.072967, 65.578938], + [-168.105828, 65.682999], + [-167.541703, 65.819923], + [-166.829701, 66.049954], + [-166.3313, 66.186878], + [-166.046499, 66.110201], + [-165.756221, 66.09377], + [-165.690498, 66.203309], + [-165.86576, 66.21974], + [-165.88219, 66.312848], + [-165.186619, 66.466202], + [-164.403417, 66.581218], + [-163.981692, 66.592172], + [-163.751661, 66.553833], + [-163.872153, 66.389525], + [-163.828338, 66.274509], + [-163.915969, 66.192355], + [-163.768091, 66.060908], + [-163.494244, 66.082816], + [-163.149197, 66.060908], + [-162.749381, 66.088293], + [-162.634365, 66.039001], + [-162.371472, 66.028047], + [-162.14144, 66.077339], + [-161.840208, 66.02257], + [-161.549931, 66.241647], + [-161.341807, 66.252601], + [-161.199406, 66.208786], + [-161.128206, 66.334755], + [-161.528023, 66.395002], + [-161.911409, 66.345709], + [-161.87307, 66.510017], + [-162.174302, 66.68528], + [-162.502918, 66.740049], + [-162.601503, 66.89888], + [-162.344087, 66.937219], + [-162.015471, 66.778388], + [-162.075717, 66.652418], + [-161.916886, 66.553833], + [-161.571838, 66.438817], + [-161.489684, 66.55931], + [-161.884024, 66.718141], + [-161.714239, 67.002942], + [-161.851162, 67.052235], + [-162.240025, 66.991988], + [-162.639842, 67.008419], + [-162.700088, 67.057712], + [-162.902735, 67.008419], + [-163.740707, 67.128912], + [-163.757138, 67.254881], + [-164.009077, 67.534205], + [-164.211724, 67.638267], + [-164.534863, 67.725898], + [-165.192096, 67.966884], + [-165.493328, 68.059992], + [-165.794559, 68.081899], + [-166.243668, 68.246208], + [-166.681824, 68.339316], + [-166.703731, 68.372177], + [-166.375115, 68.42147], + [-166.227238, 68.574824], + [-166.216284, 68.881533], + [-165.329019, 68.859625], + [-164.255539, 68.930825], + [-163.976215, 68.985595], + [-163.532583, 69.138949], + [-163.110859, 69.374457], + [-163.023228, 69.609966], + [-162.842489, 69.812613], + [-162.470057, 69.982398], + [-162.311225, 70.108367], + [-161.851162, 70.311014], + [-161.779962, 70.256245], + [-161.396576, 70.239814], + [-160.837928, 70.343876], + [-160.487404, 70.453415], + [-159.649432, 70.792985], + [-159.33177, 70.809416], + [-159.298908, 70.760123], + [-158.975769, 70.798462], + [-158.658106, 70.787508], + [-158.033735, 70.831323], + [-157.420318, 70.979201], + [-156.812377, 71.285909], + [-156.565915, 71.351633], + [-156.522099, 71.296863], + [-155.585543, 71.170894], + [-155.508865, 71.083263], + [-155.832005, 70.968247], + [-155.979882, 70.96277], + [-155.974405, 70.809416], + [-155.503388, 70.858708], + [-155.476004, 70.940862], + [-155.262403, 71.017539], + [-155.191203, 70.973724], + [-155.032372, 71.148986], + [-154.566832, 70.990155], + [-154.643509, 70.869662], + [-154.353231, 70.8368], + [-154.183446, 70.7656], + [-153.931507, 70.880616], + [-153.487874, 70.886093], + [-153.235935, 70.924431], + [-152.589656, 70.886093], + [-152.26104, 70.842277], + [-152.419871, 70.606769], + [-151.817408, 70.546523], + [-151.773592, 70.486276], + [-151.187559, 70.382214], + [-151.182082, 70.431507], + [-150.760358, 70.49723], + [-150.355064, 70.491753], + [-150.349588, 70.436984], + [-150.114079, 70.431507], + [-149.867617, 70.508184], + [-149.462323, 70.519138], + [-149.177522, 70.486276], + [-148.78866, 70.404122], + [-148.607921, 70.420553], + [-148.350504, 70.305537], + [-148.202627, 70.349353], + [-147.961642, 70.316491], + [-147.786379, 70.245291], + ], + ], + [ + [ + [-152.94018, 58.026237], + [-152.945657, 57.982421], + [-153.290705, 58.048145], + [-153.044242, 58.305561], + [-152.819688, 58.327469], + [-152.666333, 58.562977], + [-152.496548, 58.354853], + [-152.354148, 58.426053], + [-152.080301, 58.311038], + [-152.080301, 58.152206], + [-152.480117, 58.130299], + [-152.655379, 58.059098], + [-152.94018, 58.026237], + ], + ], + [ + [ + [-153.958891, 57.538789], + [-153.67409, 57.670236], + [-153.931507, 57.69762], + [-153.936983, 57.812636], + [-153.723383, 57.889313], + [-153.570028, 57.834544], + [-153.548121, 57.719528], + [-153.46049, 57.796205], + [-153.455013, 57.96599], + [-153.268797, 57.889313], + [-153.235935, 57.998852], + [-153.071627, 57.933129], + [-152.874457, 57.933129], + [-152.721103, 57.993375], + [-152.469163, 57.889313], + [-152.469163, 57.599035], + [-152.151501, 57.620943], + [-152.359625, 57.42925], + [-152.74301, 57.505928], + [-152.60061, 57.379958], + [-152.710149, 57.275896], + [-152.907319, 57.325188], + [-152.912796, 57.128019], + [-153.214027, 57.073249], + [-153.312612, 56.991095], + [-153.498828, 57.067772], + [-153.695998, 56.859649], + [-153.849352, 56.837741], + [-154.013661, 56.744633], + [-154.073907, 56.969187], + [-154.303938, 56.848695], + [-154.314892, 56.919895], + [-154.523016, 56.991095], + [-154.539447, 57.193742], + [-154.742094, 57.275896], + [-154.627078, 57.511404], + [-154.227261, 57.659282], + [-153.980799, 57.648328], + [-153.958891, 57.538789], + ], + ], + [ + [ + [-154.53397, 56.602232], + [-154.742094, 56.399586], + [-154.807817, 56.432447], + [-154.53397, 56.602232], + ], + ], + [ + [ + [-155.634835, 55.923092], + [-155.476004, 55.912138], + [-155.530773, 55.704014], + [-155.793666, 55.731399], + [-155.837482, 55.802599], + [-155.634835, 55.923092], + ], + ], + [ + [ + [-159.890418, 55.28229], + [-159.950664, 55.068689], + [-160.257373, 54.893427], + [-160.109495, 55.161797], + [-160.005433, 55.134412], + [-159.890418, 55.28229], + ], + ], + [ + [ + [-160.520266, 55.358967], + [-160.33405, 55.358967], + [-160.339527, 55.249428], + [-160.525743, 55.128935], + [-160.690051, 55.211089], + [-160.794113, 55.134412], + [-160.854359, 55.320628], + [-160.79959, 55.380875], + [-160.520266, 55.358967], + ], + ], + [ + [ + [-162.256456, 54.981058], + [-162.234548, 54.893427], + [-162.349564, 54.838658], + [-162.437195, 54.931766], + [-162.256456, 54.981058], + ], + ], + [ + [ + [-162.415287, 63.634624], + [-162.563165, 63.536039], + [-162.612457, 63.62367], + [-162.415287, 63.634624], + ], + ], + [ + [ + [-162.80415, 54.488133], + [-162.590549, 54.449795], + [-162.612457, 54.367641], + [-162.782242, 54.373118], + [-162.80415, 54.488133], + ], + ], + [ + [ + [-165.548097, 54.29644], + [-165.476897, 54.181425], + [-165.630251, 54.132132], + [-165.685021, 54.252625], + [-165.548097, 54.29644], + ], + ], + [ + [ + [-165.73979, 54.15404], + [-166.046499, 54.044501], + [-166.112222, 54.121178], + [-165.980775, 54.219763], + [-165.73979, 54.15404], + ], + ], + [ + [ + [-166.364161, 60.359413], + [-166.13413, 60.397752], + [-166.084837, 60.326552], + [-165.88219, 60.342983], + [-165.685021, 60.277259], + [-165.646682, 59.992458], + [-165.750744, 59.89935], + [-166.00816, 59.844581], + [-166.062929, 59.745996], + [-166.440838, 59.855535], + [-166.6161, 59.850058], + [-166.994009, 59.992458], + [-167.125456, 59.992458], + [-167.344534, 60.074613], + [-167.421211, 60.206059], + [-167.311672, 60.238921], + [-166.93924, 60.206059], + [-166.763978, 60.310121], + [-166.577762, 60.321075], + [-166.495608, 60.392275], + [-166.364161, 60.359413], + ], + ], + [ + [ + [-166.375115, 54.01164], + [-166.210807, 53.934962], + [-166.5449, 53.748746], + [-166.539423, 53.715885], + [-166.117699, 53.852808], + [-166.112222, 53.776131], + [-166.282007, 53.683023], + [-166.555854, 53.622777], + [-166.583239, 53.529669], + [-166.878994, 53.431084], + [-167.13641, 53.425607], + [-167.306195, 53.332499], + [-167.623857, 53.250345], + [-167.793643, 53.337976], + [-167.459549, 53.442038], + [-167.355487, 53.425607], + [-167.103548, 53.513238], + [-167.163794, 53.611823], + [-167.021394, 53.715885], + [-166.807793, 53.666592], + [-166.785886, 53.732316], + [-167.015917, 53.754223], + [-167.141887, 53.825424], + [-167.032348, 53.945916], + [-166.643485, 54.017116], + [-166.561331, 53.880193], + [-166.375115, 54.01164], + ], + ], + [ + [ + [-168.790446, 53.157237], + [-168.40706, 53.34893], + [-168.385152, 53.431084], + [-168.237275, 53.524192], + [-168.007243, 53.568007], + [-167.886751, 53.518715], + [-167.842935, 53.387268], + [-168.270136, 53.244868], + [-168.500168, 53.036744], + [-168.686384, 52.965544], + [-168.790446, 53.157237], + ], + ], + [ + [ + [-169.74891, 52.894344], + [-169.705095, 52.795759], + [-169.962511, 52.790282], + [-169.989896, 52.856005], + [-169.74891, 52.894344], + ], + ], + [ + [ + [-170.148727, 57.221127], + [-170.28565, 57.128019], + [-170.313035, 57.221127], + [-170.148727, 57.221127], + ], + ], + [ + [ + [-170.669036, 52.697174], + [-170.603313, 52.604066], + [-170.789529, 52.538343], + [-170.816914, 52.636928], + [-170.669036, 52.697174], + ], + ], + [ + [ + [-171.742517, 63.716778], + [-170.94836, 63.5689], + [-170.488297, 63.69487], + [-170.280174, 63.683916], + [-170.093958, 63.612716], + [-170.044665, 63.492223], + [-169.644848, 63.4265], + [-169.518879, 63.366254], + [-168.99857, 63.338869], + [-168.686384, 63.295053], + [-168.856169, 63.147176], + [-169.108108, 63.180038], + [-169.376478, 63.152653], + [-169.513402, 63.08693], + [-169.639372, 62.939052], + [-169.831064, 63.075976], + [-170.055619, 63.169084], + [-170.263743, 63.180038], + [-170.362328, 63.2841], + [-170.866206, 63.415546], + [-171.101715, 63.421023], + [-171.463193, 63.306007], + [-171.73704, 63.366254], + [-171.852055, 63.486746], + [-171.742517, 63.716778], + ], + ], + [ + [ + [-172.432611, 52.390465], + [-172.41618, 52.275449], + [-172.607873, 52.253542], + [-172.569535, 52.352127], + [-172.432611, 52.390465], + ], + ], + [ + [ + [-173.626584, 52.14948], + [-173.495138, 52.105664], + [-173.122706, 52.111141], + [-173.106275, 52.07828], + [-173.549907, 52.028987], + [-173.626584, 52.14948], + ], + ], + [ + [ + [-174.322156, 52.280926], + [-174.327632, 52.379511], + [-174.185232, 52.41785], + [-173.982585, 52.319265], + [-174.059262, 52.226157], + [-174.179755, 52.231634], + [-174.141417, 52.127572], + [-174.333109, 52.116618], + [-174.738403, 52.007079], + [-174.968435, 52.039941], + [-174.902711, 52.116618], + [-174.656249, 52.105664], + [-174.322156, 52.280926], + ], + ], + [ + [ + [-176.469116, 51.853725], + [-176.288377, 51.870156], + [-176.288377, 51.744186], + [-176.518409, 51.760617], + [-176.80321, 51.61274], + [-176.912748, 51.80991], + [-176.792256, 51.815386], + [-176.775825, 51.963264], + [-176.627947, 51.968741], + [-176.627947, 51.859202], + [-176.469116, 51.853725], + ], + ], + [ + [ + [-177.153734, 51.946833], + [-177.044195, 51.897541], + [-177.120872, 51.727755], + [-177.274226, 51.678463], + [-177.279703, 51.782525], + [-177.153734, 51.946833], + ], + ], + [ + [ + [-178.123152, 51.919448], + [-177.953367, 51.913971], + [-177.800013, 51.793479], + [-177.964321, 51.651078], + [-178.123152, 51.919448], + ], + ], + [ + [ + [-187.107557, 52.992929], + [-187.293773, 52.927205], + [-187.304726, 52.823143], + [-188.90491, 52.762897], + [-188.642017, 52.927205], + [-188.642017, 53.003883], + [-187.107557, 52.992929], + ], + ], + ], + }, + }, + { + type: "Feature", + id: "04", + properties: { name: "Arizona", density: 57.05 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-109.042503, 37.000263], + [-109.04798, 31.331629], + [-111.074448, 31.331629], + [-112.246513, 31.704061], + [-114.815198, 32.492741], + [-114.72209, 32.717295], + [-114.524921, 32.755634], + [-114.470151, 32.843265], + [-114.524921, 33.029481], + [-114.661844, 33.034958], + [-114.727567, 33.40739], + [-114.524921, 33.54979], + [-114.497536, 33.697668], + [-114.535874, 33.933176], + [-114.415382, 34.108438], + [-114.256551, 34.174162], + [-114.136058, 34.305608], + [-114.333228, 34.448009], + [-114.470151, 34.710902], + [-114.634459, 34.87521], + [-114.634459, 35.00118], + [-114.574213, 35.138103], + [-114.596121, 35.324319], + [-114.678275, 35.516012], + [-114.738521, 36.102045], + [-114.371566, 36.140383], + [-114.251074, 36.01989], + [-114.152489, 36.025367], + [-114.048427, 36.195153], + [-114.048427, 37.000263], + [-110.499369, 37.00574], + [-109.042503, 37.000263], + ], + ], + }, + }, + { + type: "Feature", + id: "05", + properties: { name: "Arkansas", density: 56.43 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-94.473842, 36.501861], + [-90.152536, 36.496384], + [-90.064905, 36.304691], + [-90.218259, 36.184199], + [-90.377091, 35.997983], + [-89.730812, 35.997983], + [-89.763673, 35.811767], + [-89.911551, 35.756997], + [-89.944412, 35.603643], + [-90.130628, 35.439335], + [-90.114197, 35.198349], + [-90.212782, 35.023087], + [-90.311367, 34.995703], + [-90.251121, 34.908072], + [-90.409952, 34.831394], + [-90.481152, 34.661609], + [-90.585214, 34.617794], + [-90.568783, 34.420624], + [-90.749522, 34.365854], + [-90.744046, 34.300131], + [-90.952169, 34.135823], + [-90.891923, 34.026284], + [-91.072662, 33.867453], + [-91.231493, 33.560744], + [-91.056231, 33.429298], + [-91.143862, 33.347144], + [-91.089093, 33.13902], + [-91.16577, 33.002096], + [-93.608485, 33.018527], + [-94.041164, 33.018527], + [-94.041164, 33.54979], + [-94.183564, 33.593606], + [-94.380734, 33.544313], + [-94.484796, 33.637421], + [-94.430026, 35.395519], + [-94.616242, 36.501861], + [-94.473842, 36.501861], + ], + ], + }, + }, + { + type: "Feature", + id: "06", + properties: { name: "California", density: 241.7 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-123.233256, 42.006186], + [-122.378853, 42.011663], + [-121.037003, 41.995232], + [-120.001861, 41.995232], + [-119.996384, 40.264519], + [-120.001861, 38.999346], + [-118.71478, 38.101128], + [-117.498899, 37.21934], + [-116.540435, 36.501861], + [-115.85034, 35.970598], + [-114.634459, 35.00118], + [-114.634459, 34.87521], + [-114.470151, 34.710902], + [-114.333228, 34.448009], + [-114.136058, 34.305608], + [-114.256551, 34.174162], + [-114.415382, 34.108438], + [-114.535874, 33.933176], + [-114.497536, 33.697668], + [-114.524921, 33.54979], + [-114.727567, 33.40739], + [-114.661844, 33.034958], + [-114.524921, 33.029481], + [-114.470151, 32.843265], + [-114.524921, 32.755634], + [-114.72209, 32.717295], + [-116.04751, 32.624187], + [-117.126467, 32.536556], + [-117.24696, 32.668003], + [-117.252437, 32.876127], + [-117.329114, 33.122589], + [-117.471515, 33.297851], + [-117.7837, 33.538836], + [-118.183517, 33.763391], + [-118.260194, 33.703145], + [-118.413548, 33.741483], + [-118.391641, 33.840068], + [-118.566903, 34.042715], + [-118.802411, 33.998899], + [-119.218659, 34.146777], + [-119.278905, 34.26727], + [-119.558229, 34.415147], + [-119.875891, 34.40967], + [-120.138784, 34.475393], + [-120.472878, 34.448009], + [-120.64814, 34.579455], + [-120.609801, 34.858779], + [-120.670048, 34.902595], + [-120.631709, 35.099764], + [-120.894602, 35.247642], + [-120.905556, 35.450289], + [-121.004141, 35.461243], + [-121.168449, 35.636505], + [-121.283465, 35.674843], + [-121.332757, 35.784382], + [-121.716143, 36.195153], + [-121.896882, 36.315645], + [-121.935221, 36.638785], + [-121.858544, 36.6114], + [-121.787344, 36.803093], + [-121.929744, 36.978355], + [-122.105006, 36.956447], + [-122.335038, 37.115279], + [-122.417192, 37.241248], + [-122.400761, 37.361741], + [-122.515777, 37.520572], + [-122.515777, 37.783465], + [-122.329561, 37.783465], + [-122.406238, 38.15042], + [-122.488392, 38.112082], + [-122.504823, 37.931343], + [-122.701993, 37.893004], + [-122.937501, 38.029928], + [-122.97584, 38.265436], + [-123.129194, 38.451652], + [-123.331841, 38.566668], + [-123.44138, 38.698114], + [-123.737134, 38.95553], + [-123.687842, 39.032208], + [-123.824765, 39.366301], + [-123.764519, 39.552517], + [-123.85215, 39.831841], + [-124.109566, 40.105688], + [-124.361506, 40.259042], + [-124.410798, 40.439781], + [-124.158859, 40.877937], + [-124.109566, 41.025814], + [-124.158859, 41.14083], + [-124.065751, 41.442061], + [-124.147905, 41.715908], + [-124.257444, 41.781632], + [-124.213628, 42.000709], + [-123.233256, 42.006186], + ], + ], + }, + }, + { + type: "Feature", + id: "08", + properties: { name: "Colorado", density: 49.33 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-107.919731, 41.003906], + [-105.728954, 40.998429], + [-104.053011, 41.003906], + [-102.053927, 41.003906], + [-102.053927, 40.001626], + [-102.042974, 36.994786], + [-103.001438, 37.000263], + [-104.337812, 36.994786], + [-106.868158, 36.994786], + [-107.421329, 37.000263], + [-109.042503, 37.000263], + [-109.042503, 38.166851], + [-109.058934, 38.27639], + [-109.053457, 39.125316], + [-109.04798, 40.998429], + [-107.919731, 41.003906], + ], + ], + }, + }, + { + type: "Feature", + id: "09", + properties: { name: "Connecticut", density: 739.1 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-73.053528, 42.039048], + [-71.799309, 42.022617], + [-71.799309, 42.006186], + [-71.799309, 41.414677], + [-71.859555, 41.321569], + [-71.947186, 41.338], + [-72.385341, 41.261322], + [-72.905651, 41.28323], + [-73.130205, 41.146307], + [-73.371191, 41.102491], + [-73.655992, 40.987475], + [-73.727192, 41.102491], + [-73.48073, 41.21203], + [-73.55193, 41.294184], + [-73.486206, 42.050002], + [-73.053528, 42.039048], + ], + ], + }, + }, + { + type: "Feature", + id: "10", + properties: { name: "Delaware", density: 464.3 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-75.414089, 39.804456], + [-75.507197, 39.683964], + [-75.611259, 39.61824], + [-75.589352, 39.459409], + [-75.441474, 39.311532], + [-75.403136, 39.065069], + [-75.189535, 38.807653], + [-75.09095, 38.796699], + [-75.047134, 38.451652], + [-75.693413, 38.462606], + [-75.786521, 39.722302], + [-75.616736, 39.831841], + [-75.414089, 39.804456], + ], + ], + }, + }, + { + type: "Feature", + id: "11", + properties: { name: "District of Columbia", density: 10065 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-77.035264, 38.993869], + [-76.909294, 38.895284], + [-77.040741, 38.791222], + [-77.117418, 38.933623], + [-77.035264, 38.993869], + ], + ], + }, + }, + { + type: "Feature", + id: "12", + properties: { name: "Florida", density: 353.4 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-85.497137, 30.997536], + [-85.004212, 31.003013], + [-84.867289, 30.712735], + [-83.498053, 30.647012], + [-82.216449, 30.570335], + [-82.167157, 30.356734], + [-82.046664, 30.362211], + [-82.002849, 30.564858], + [-82.041187, 30.751074], + [-81.948079, 30.827751], + [-81.718048, 30.745597], + [-81.444201, 30.707258], + [-81.383954, 30.27458], + [-81.257985, 29.787132], + [-80.967707, 29.14633], + [-80.524075, 28.461713], + [-80.589798, 28.41242], + [-80.56789, 28.094758], + [-80.381674, 27.738757], + [-80.091397, 27.021277], + [-80.03115, 26.796723], + [-80.036627, 26.566691], + [-80.146166, 25.739673], + [-80.239274, 25.723243], + [-80.337859, 25.465826], + [-80.304997, 25.383672], + [-80.49669, 25.197456], + [-80.573367, 25.241272], + [-80.759583, 25.164595], + [-81.077246, 25.120779], + [-81.170354, 25.224841], + [-81.126538, 25.378195], + [-81.351093, 25.821827], + [-81.526355, 25.903982], + [-81.679709, 25.843735], + [-81.800202, 26.090198], + [-81.833064, 26.292844], + [-82.041187, 26.517399], + [-82.09048, 26.665276], + [-82.057618, 26.878877], + [-82.172634, 26.917216], + [-82.145249, 26.791246], + [-82.249311, 26.758384], + [-82.566974, 27.300601], + [-82.692943, 27.437525], + [-82.391711, 27.837342], + [-82.588881, 27.815434], + [-82.720328, 27.689464], + [-82.851774, 27.886634], + [-82.676512, 28.434328], + [-82.643651, 28.888914], + [-82.764143, 28.998453], + [-82.802482, 29.14633], + [-82.994175, 29.179192], + [-83.218729, 29.420177], + [-83.399469, 29.518762], + [-83.410422, 29.66664], + [-83.536392, 29.721409], + [-83.640454, 29.885717], + [-84.02384, 30.104795], + [-84.357933, 30.055502], + [-84.341502, 29.902148], + [-84.451041, 29.929533], + [-84.867289, 29.743317], + [-85.310921, 29.699501], + [-85.299967, 29.80904], + [-85.404029, 29.940487], + [-85.924338, 30.236241], + [-86.29677, 30.362211], + [-86.630863, 30.395073], + [-86.910187, 30.373165], + [-87.518128, 30.280057], + [-87.37025, 30.427934], + [-87.446927, 30.510088], + [-87.408589, 30.674397], + [-87.633143, 30.86609], + [-87.600282, 30.997536], + [-85.497137, 30.997536], + ], + ], + }, + }, + { + type: "Feature", + id: "13", + properties: { name: "Georgia", density: 169.5 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-83.109191, 35.00118], + [-83.322791, 34.787579], + [-83.339222, 34.683517], + [-83.005129, 34.469916], + [-82.901067, 34.486347], + [-82.747713, 34.26727], + [-82.714851, 34.152254], + [-82.55602, 33.94413], + [-82.325988, 33.81816], + [-82.194542, 33.631944], + [-81.926172, 33.462159], + [-81.937125, 33.347144], + [-81.761863, 33.160928], + [-81.493493, 33.007573], + [-81.42777, 32.843265], + [-81.416816, 32.629664], + [-81.279893, 32.558464], + [-81.121061, 32.290094], + [-81.115584, 32.120309], + [-80.885553, 32.032678], + [-81.132015, 31.693108], + [-81.175831, 31.517845], + [-81.279893, 31.364491], + [-81.290846, 31.20566], + [-81.400385, 31.13446], + [-81.444201, 30.707258], + [-81.718048, 30.745597], + [-81.948079, 30.827751], + [-82.041187, 30.751074], + [-82.002849, 30.564858], + [-82.046664, 30.362211], + [-82.167157, 30.356734], + [-82.216449, 30.570335], + [-83.498053, 30.647012], + [-84.867289, 30.712735], + [-85.004212, 31.003013], + [-85.113751, 31.27686], + [-85.042551, 31.539753], + [-85.141136, 31.840985], + [-85.053504, 32.01077], + [-85.058981, 32.13674], + [-84.889196, 32.262709], + [-85.004212, 32.322956], + [-84.960397, 32.421541], + [-85.069935, 32.580372], + [-85.184951, 32.859696], + [-85.431413, 34.124869], + [-85.606675, 34.984749], + [-84.319594, 34.990226], + [-83.618546, 34.984749], + [-83.109191, 35.00118], + ], + ], + }, + }, + { + type: "Feature", + id: "15", + properties: { name: "Hawaii", density: 214.1 }, + geometry: { + type: "MultiPolygon", + coordinates: [ + [ + [ + [-155.634835, 18.948267], + [-155.881297, 19.035898], + [-155.919636, 19.123529], + [-155.886774, 19.348084], + [-156.062036, 19.73147], + [-155.925113, 19.857439], + [-155.826528, 20.032702], + [-155.897728, 20.147717], + [-155.87582, 20.26821], + [-155.596496, 20.12581], + [-155.284311, 20.021748], + [-155.092618, 19.868393], + [-155.092618, 19.736947], + [-154.807817, 19.523346], + [-154.983079, 19.348084], + [-155.295265, 19.26593], + [-155.514342, 19.134483], + [-155.634835, 18.948267], + ], + ], + [ + [ + [-156.587823, 21.029505], + [-156.472807, 20.892581], + [-156.324929, 20.952827], + [-156.00179, 20.793996], + [-156.051082, 20.651596], + [-156.379699, 20.580396], + [-156.445422, 20.60778], + [-156.461853, 20.783042], + [-156.631638, 20.821381], + [-156.697361, 20.919966], + [-156.587823, 21.029505], + ], + ], + [ + [ + [-156.982162, 21.210244], + [-157.080747, 21.106182], + [-157.310779, 21.106182], + [-157.239579, 21.221198], + [-156.982162, 21.210244], + ], + ], + [ + [ + [-157.951581, 21.697691], + [-157.842042, 21.462183], + [-157.896811, 21.325259], + [-158.110412, 21.303352], + [-158.252813, 21.582676], + [-158.126843, 21.588153], + [-157.951581, 21.697691], + ], + ], + [ + [ + [-159.468693, 22.228955], + [-159.353678, 22.218001], + [-159.298908, 22.113939], + [-159.33177, 21.966061], + [-159.446786, 21.872953], + [-159.764448, 21.987969], + [-159.726109, 22.152277], + [-159.468693, 22.228955], + ], + ], + ], + }, + }, + { + type: "Feature", + id: "16", + properties: { name: "Idaho", density: 19.15 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-116.04751, 49.000239], + [-116.04751, 47.976051], + [-115.724371, 47.696727], + [-115.718894, 47.42288], + [-115.527201, 47.302388], + [-115.324554, 47.258572], + [-115.302646, 47.187372], + [-114.930214, 46.919002], + [-114.886399, 46.809463], + [-114.623506, 46.705401], + [-114.612552, 46.639678], + [-114.322274, 46.645155], + [-114.464674, 46.272723], + [-114.492059, 46.037214], + [-114.387997, 45.88386], + [-114.568736, 45.774321], + [-114.497536, 45.670259], + [-114.546828, 45.560721], + [-114.333228, 45.456659], + [-114.086765, 45.593582], + [-113.98818, 45.703121], + [-113.807441, 45.604536], + [-113.834826, 45.522382], + [-113.736241, 45.330689], + [-113.571933, 45.128042], + [-113.45144, 45.056842], + [-113.456917, 44.865149], + [-113.341901, 44.782995], + [-113.133778, 44.772041], + [-113.002331, 44.448902], + [-112.887315, 44.394132], + [-112.783254, 44.48724], + [-112.471068, 44.481763], + [-112.241036, 44.569394], + [-112.104113, 44.520102], + [-111.868605, 44.563917], + [-111.819312, 44.509148], + [-111.616665, 44.547487], + [-111.386634, 44.75561], + [-111.227803, 44.580348], + [-111.047063, 44.476286], + [-111.047063, 42.000709], + [-112.164359, 41.995232], + [-114.04295, 41.995232], + [-117.027882, 42.000709], + [-117.027882, 43.830007], + [-116.896436, 44.158624], + [-116.97859, 44.240778], + [-117.170283, 44.257209], + [-117.241483, 44.394132], + [-117.038836, 44.750133], + [-116.934774, 44.782995], + [-116.830713, 44.930872], + [-116.847143, 45.02398], + [-116.732128, 45.144473], + [-116.671881, 45.319735], + [-116.463758, 45.61549], + [-116.545912, 45.752413], + [-116.78142, 45.823614], + [-116.918344, 45.993399], + [-116.92382, 46.168661], + [-117.055267, 46.343923], + [-117.038836, 46.426077], + [-117.044313, 47.762451], + [-117.033359, 49.000239], + [-116.04751, 49.000239], + ], + ], + }, + }, + { + type: "Feature", + id: "17", + properties: { name: "Illinois", density: 231.5 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-90.639984, 42.510065], + [-88.788778, 42.493634], + [-87.802929, 42.493634], + [-87.83579, 42.301941], + [-87.682436, 42.077386], + [-87.523605, 41.710431], + [-87.529082, 39.34987], + [-87.63862, 39.169131], + [-87.512651, 38.95553], + [-87.49622, 38.780268], + [-87.62219, 38.637868], + [-87.655051, 38.506421], + [-87.83579, 38.292821], + [-87.950806, 38.27639], + [-87.923421, 38.15042], + [-88.000098, 38.101128], + [-88.060345, 37.865619], + [-88.027483, 37.799896], + [-88.15893, 37.657496], + [-88.065822, 37.482234], + [-88.476592, 37.389126], + [-88.514931, 37.285064], + [-88.421823, 37.153617], + [-88.547792, 37.071463], + [-88.914747, 37.224817], + [-89.029763, 37.213863], + [-89.183118, 37.038601], + [-89.133825, 36.983832], + [-89.292656, 36.994786], + [-89.517211, 37.279587], + [-89.435057, 37.34531], + [-89.517211, 37.537003], + [-89.517211, 37.690357], + [-89.84035, 37.903958], + [-89.949889, 37.88205], + [-90.059428, 38.013497], + [-90.355183, 38.216144], + [-90.349706, 38.374975], + [-90.179921, 38.632391], + [-90.207305, 38.725499], + [-90.10872, 38.845992], + [-90.251121, 38.917192], + [-90.470199, 38.961007], + [-90.585214, 38.867899], + [-90.661891, 38.928146], + [-90.727615, 39.256762], + [-91.061708, 39.470363], + [-91.368417, 39.727779], + [-91.494386, 40.034488], + [-91.50534, 40.237135], + [-91.417709, 40.379535], + [-91.401278, 40.560274], + [-91.121954, 40.669813], + [-91.09457, 40.823167], + [-90.963123, 40.921752], + [-90.946692, 41.097014], + [-91.111001, 41.239415], + [-91.045277, 41.414677], + [-90.656414, 41.463969], + [-90.344229, 41.589939], + [-90.311367, 41.743293], + [-90.179921, 41.809016], + [-90.141582, 42.000709], + [-90.168967, 42.126679], + [-90.393521, 42.225264], + [-90.420906, 42.329326], + [-90.639984, 42.510065], + ], + ], + }, + }, + { + type: "Feature", + id: "18", + properties: { name: "Indiana", density: 181.7 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-85.990061, 41.759724], + [-84.807042, 41.759724], + [-84.807042, 41.694001], + [-84.801565, 40.500028], + [-84.817996, 39.103408], + [-84.894673, 39.059592], + [-84.812519, 38.785745], + [-84.987781, 38.780268], + [-85.173997, 38.68716], + [-85.431413, 38.730976], + [-85.42046, 38.533806], + [-85.590245, 38.451652], + [-85.655968, 38.325682], + [-85.83123, 38.27639], + [-85.924338, 38.024451], + [-86.039354, 37.958727], + [-86.263908, 38.051835], + [-86.302247, 38.166851], + [-86.521325, 38.040881], + [-86.504894, 37.931343], + [-86.729448, 37.893004], + [-86.795172, 37.991589], + [-87.047111, 37.893004], + [-87.129265, 37.788942], + [-87.381204, 37.93682], + [-87.512651, 37.903958], + [-87.600282, 37.975158], + [-87.682436, 37.903958], + [-87.934375, 37.893004], + [-88.027483, 37.799896], + [-88.060345, 37.865619], + [-88.000098, 38.101128], + [-87.923421, 38.15042], + [-87.950806, 38.27639], + [-87.83579, 38.292821], + [-87.655051, 38.506421], + [-87.62219, 38.637868], + [-87.49622, 38.780268], + [-87.512651, 38.95553], + [-87.63862, 39.169131], + [-87.529082, 39.34987], + [-87.523605, 41.710431], + [-87.42502, 41.644708], + [-87.118311, 41.644708], + [-86.822556, 41.759724], + [-85.990061, 41.759724], + ], + ], + }, + }, + { + type: "Feature", + id: "19", + properties: { name: "Iowa", density: 54.81 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-91.368417, 43.501391], + [-91.215062, 43.501391], + [-91.204109, 43.353514], + [-91.056231, 43.254929], + [-91.176724, 43.134436], + [-91.143862, 42.909881], + [-91.067185, 42.75105], + [-90.711184, 42.636034], + [-90.639984, 42.510065], + [-90.420906, 42.329326], + [-90.393521, 42.225264], + [-90.168967, 42.126679], + [-90.141582, 42.000709], + [-90.179921, 41.809016], + [-90.311367, 41.743293], + [-90.344229, 41.589939], + [-90.656414, 41.463969], + [-91.045277, 41.414677], + [-91.111001, 41.239415], + [-90.946692, 41.097014], + [-90.963123, 40.921752], + [-91.09457, 40.823167], + [-91.121954, 40.669813], + [-91.401278, 40.560274], + [-91.417709, 40.379535], + [-91.527248, 40.412397], + [-91.729895, 40.615043], + [-91.833957, 40.609566], + [-93.257961, 40.582182], + [-94.632673, 40.571228], + [-95.7664, 40.587659], + [-95.881416, 40.719105], + [-95.826646, 40.976521], + [-95.925231, 41.201076], + [-95.919754, 41.453015], + [-96.095016, 41.540646], + [-96.122401, 41.67757], + [-96.062155, 41.798063], + [-96.127878, 41.973325], + [-96.264801, 42.039048], + [-96.44554, 42.488157], + [-96.631756, 42.707235], + [-96.544125, 42.855112], + [-96.511264, 43.052282], + [-96.434587, 43.123482], + [-96.560556, 43.222067], + [-96.527695, 43.397329], + [-96.582464, 43.479483], + [-96.451017, 43.501391], + [-91.368417, 43.501391], + ], + ], + }, + }, + { + type: "Feature", + id: "20", + properties: { name: "Kansas", density: 35.09 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-101.90605, 40.001626], + [-95.306337, 40.001626], + [-95.207752, 39.908518], + [-94.884612, 39.831841], + [-95.109167, 39.541563], + [-94.983197, 39.442978], + [-94.824366, 39.20747], + [-94.610765, 39.158177], + [-94.616242, 37.000263], + [-100.087706, 37.000263], + [-102.042974, 36.994786], + [-102.053927, 40.001626], + [-101.90605, 40.001626], + ], + ], + }, + }, + { + type: "Feature", + id: "21", + properties: { name: "Kentucky", density: 110 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-83.903347, 38.769315], + [-83.678792, 38.632391], + [-83.519961, 38.703591], + [-83.142052, 38.626914], + [-83.032514, 38.725499], + [-82.890113, 38.758361], + [-82.846298, 38.588575], + [-82.731282, 38.561191], + [-82.594358, 38.424267], + [-82.621743, 38.123036], + [-82.50125, 37.931343], + [-82.342419, 37.783465], + [-82.293127, 37.668449], + [-82.101434, 37.553434], + [-81.969987, 37.537003], + [-82.353373, 37.268633], + [-82.720328, 37.120755], + [-82.720328, 37.044078], + [-82.868205, 36.978355], + [-82.879159, 36.890724], + [-83.070852, 36.852385], + [-83.136575, 36.742847], + [-83.673316, 36.600446], + [-83.689746, 36.584015], + [-84.544149, 36.594969], + [-85.289013, 36.627831], + [-85.486183, 36.616877], + [-86.592525, 36.655216], + [-87.852221, 36.633308], + [-88.071299, 36.677123], + [-88.054868, 36.496384], + [-89.298133, 36.507338], + [-89.418626, 36.496384], + [-89.363857, 36.622354], + [-89.215979, 36.578538], + [-89.133825, 36.983832], + [-89.183118, 37.038601], + [-89.029763, 37.213863], + [-88.914747, 37.224817], + [-88.547792, 37.071463], + [-88.421823, 37.153617], + [-88.514931, 37.285064], + [-88.476592, 37.389126], + [-88.065822, 37.482234], + [-88.15893, 37.657496], + [-88.027483, 37.799896], + [-87.934375, 37.893004], + [-87.682436, 37.903958], + [-87.600282, 37.975158], + [-87.512651, 37.903958], + [-87.381204, 37.93682], + [-87.129265, 37.788942], + [-87.047111, 37.893004], + [-86.795172, 37.991589], + [-86.729448, 37.893004], + [-86.504894, 37.931343], + [-86.521325, 38.040881], + [-86.302247, 38.166851], + [-86.263908, 38.051835], + [-86.039354, 37.958727], + [-85.924338, 38.024451], + [-85.83123, 38.27639], + [-85.655968, 38.325682], + [-85.590245, 38.451652], + [-85.42046, 38.533806], + [-85.431413, 38.730976], + [-85.173997, 38.68716], + [-84.987781, 38.780268], + [-84.812519, 38.785745], + [-84.894673, 39.059592], + [-84.817996, 39.103408], + [-84.43461, 39.103408], + [-84.231963, 38.895284], + [-84.215533, 38.807653], + [-83.903347, 38.769315], + ], + ], + }, + }, + { + type: "Feature", + id: "22", + properties: { name: "Louisiana", density: 105 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-93.608485, 33.018527], + [-91.16577, 33.002096], + [-91.072662, 32.887081], + [-91.143862, 32.843265], + [-91.154816, 32.640618], + [-91.006939, 32.514649], + [-90.985031, 32.218894], + [-91.105524, 31.988862], + [-91.341032, 31.846462], + [-91.401278, 31.621907], + [-91.499863, 31.643815], + [-91.516294, 31.27686], + [-91.636787, 31.265906], + [-91.565587, 31.068736], + [-91.636787, 30.997536], + [-89.747242, 30.997536], + [-89.845827, 30.66892], + [-89.681519, 30.449842], + [-89.643181, 30.285534], + [-89.522688, 30.181472], + [-89.818443, 30.044549], + [-89.84035, 29.945964], + [-89.599365, 29.88024], + [-89.495303, 30.039072], + [-89.287179, 29.88024], + [-89.30361, 29.754271], + [-89.424103, 29.699501], + [-89.648657, 29.748794], + [-89.621273, 29.655686], + [-89.69795, 29.513285], + [-89.506257, 29.387316], + [-89.199548, 29.348977], + [-89.09001, 29.2011], + [-89.002379, 29.179192], + [-89.16121, 29.009407], + [-89.336472, 29.042268], + [-89.484349, 29.217531], + [-89.851304, 29.310638], + [-89.851304, 29.480424], + [-90.032043, 29.425654], + [-90.021089, 29.283254], + [-90.103244, 29.151807], + [-90.23469, 29.129899], + [-90.333275, 29.277777], + [-90.563307, 29.283254], + [-90.645461, 29.129899], + [-90.798815, 29.086084], + [-90.963123, 29.179192], + [-91.09457, 29.190146], + [-91.220539, 29.436608], + [-91.445094, 29.546147], + [-91.532725, 29.529716], + [-91.620356, 29.73784], + [-91.883249, 29.710455], + [-91.888726, 29.836425], + [-92.146142, 29.715932], + [-92.113281, 29.622824], + [-92.31045, 29.535193], + [-92.617159, 29.579009], + [-92.97316, 29.715932], + [-93.2251, 29.776178], + [-93.767317, 29.726886], + [-93.838517, 29.688547], + [-93.926148, 29.787132], + [-93.690639, 30.143133], + [-93.767317, 30.334826], + [-93.696116, 30.438888], + [-93.728978, 30.575812], + [-93.630393, 30.679874], + [-93.526331, 30.93729], + [-93.542762, 31.15089], + [-93.816609, 31.556184], + [-93.822086, 31.775262], + [-94.041164, 31.994339], + [-94.041164, 33.018527], + [-93.608485, 33.018527], + ], + ], + }, + }, + { + type: "Feature", + id: "23", + properties: { name: "Maine", density: 43.04 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-70.703921, 43.057759], + [-70.824413, 43.128959], + [-70.807983, 43.227544], + [-70.966814, 43.34256], + [-71.032537, 44.657025], + [-71.08183, 45.303304], + [-70.649151, 45.440228], + [-70.720352, 45.511428], + [-70.556043, 45.664782], + [-70.386258, 45.735983], + [-70.41912, 45.796229], + [-70.260289, 45.889337], + [-70.309581, 46.064599], + [-70.210996, 46.327492], + [-70.057642, 46.415123], + [-69.997395, 46.694447], + [-69.225147, 47.461219], + [-69.044408, 47.428357], + [-69.033454, 47.242141], + [-68.902007, 47.176418], + [-68.578868, 47.285957], + [-68.376221, 47.285957], + [-68.233821, 47.357157], + [-67.954497, 47.198326], + [-67.790188, 47.066879], + [-67.779235, 45.944106], + [-67.801142, 45.675736], + [-67.456095, 45.604536], + [-67.505388, 45.48952], + [-67.417757, 45.379982], + [-67.488957, 45.281397], + [-67.346556, 45.128042], + [-67.16034, 45.160904], + [-66.979601, 44.804903], + [-67.187725, 44.646072], + [-67.308218, 44.706318], + [-67.406803, 44.596779], + [-67.549203, 44.624164], + [-67.565634, 44.531056], + [-67.75185, 44.54201], + [-68.047605, 44.328409], + [-68.118805, 44.476286], + [-68.222867, 44.48724], + [-68.173574, 44.328409], + [-68.403606, 44.251732], + [-68.458375, 44.377701], + [-68.567914, 44.311978], + [-68.82533, 44.311978], + [-68.830807, 44.459856], + [-68.984161, 44.426994], + [-68.956777, 44.322932], + [-69.099177, 44.103854], + [-69.071793, 44.043608], + [-69.258008, 43.923115], + [-69.444224, 43.966931], + [-69.553763, 43.840961], + [-69.707118, 43.82453], + [-69.833087, 43.720469], + [-69.986442, 43.742376], + [-70.030257, 43.851915], + [-70.254812, 43.676653], + [-70.194565, 43.567114], + [-70.358873, 43.528776], + [-70.369827, 43.435668], + [-70.556043, 43.320652], + [-70.703921, 43.057759], + ], + ], + }, + }, + { + type: "Feature", + id: "24", + properties: { name: "Maryland", density: 596.3 }, + geometry: { + type: "MultiPolygon", + coordinates: [ + [ + [ + [-75.994645, 37.95325], + [-76.016553, 37.95325], + [-76.043938, 37.95325], + [-75.994645, 37.95325], + ], + ], + [ + [ + [-79.477979, 39.722302], + [-75.786521, 39.722302], + [-75.693413, 38.462606], + [-75.047134, 38.451652], + [-75.244304, 38.029928], + [-75.397659, 38.013497], + [-75.671506, 37.95325], + [-75.885106, 37.909435], + [-75.879629, 38.073743], + [-75.961783, 38.139466], + [-75.846768, 38.210667], + [-76.000122, 38.374975], + [-76.049415, 38.303775], + [-76.257538, 38.320205], + [-76.328738, 38.500944], + [-76.263015, 38.500944], + [-76.257538, 38.736453], + [-76.191815, 38.829561], + [-76.279446, 39.147223], + [-76.169907, 39.333439], + [-76.000122, 39.366301], + [-75.972737, 39.557994], + [-76.098707, 39.536086], + [-76.104184, 39.437501], + [-76.367077, 39.311532], + [-76.443754, 39.196516], + [-76.460185, 38.906238], + [-76.55877, 38.769315], + [-76.514954, 38.539283], + [-76.383508, 38.380452], + [-76.399939, 38.259959], + [-76.317785, 38.139466], + [-76.3616, 38.057312], + [-76.591632, 38.216144], + [-76.920248, 38.292821], + [-77.018833, 38.446175], + [-77.205049, 38.358544], + [-77.276249, 38.479037], + [-77.128372, 38.632391], + [-77.040741, 38.791222], + [-76.909294, 38.895284], + [-77.035264, 38.993869], + [-77.117418, 38.933623], + [-77.248864, 39.026731], + [-77.456988, 39.076023], + [-77.456988, 39.223901], + [-77.566527, 39.306055], + [-77.719881, 39.322485], + [-77.834897, 39.601809], + [-78.004682, 39.601809], + [-78.174467, 39.694917], + [-78.267575, 39.61824], + [-78.431884, 39.623717], + [-78.470222, 39.514178], + [-78.765977, 39.585379], + [-78.963147, 39.437501], + [-79.094593, 39.470363], + [-79.291763, 39.300578], + [-79.488933, 39.20747], + [-79.477979, 39.722302], + ], + ], + ], + }, + }, + { + type: "Feature", + id: "25", + properties: { name: "Massachusetts", density: 840.2 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-70.917521, 42.887974], + [-70.818936, 42.871543], + [-70.780598, 42.696281], + [-70.824413, 42.55388], + [-70.983245, 42.422434], + [-70.988722, 42.269079], + [-70.769644, 42.247172], + [-70.638197, 42.08834], + [-70.660105, 41.962371], + [-70.550566, 41.929509], + [-70.539613, 41.814493], + [-70.260289, 41.715908], + [-69.937149, 41.809016], + [-70.008349, 41.672093], + [-70.484843, 41.5516], + [-70.660105, 41.546123], + [-70.764167, 41.639231], + [-70.928475, 41.611847], + [-70.933952, 41.540646], + [-71.120168, 41.496831], + [-71.196845, 41.67757], + [-71.22423, 41.710431], + [-71.328292, 41.781632], + [-71.383061, 42.01714], + [-71.530939, 42.01714], + [-71.799309, 42.006186], + [-71.799309, 42.022617], + [-73.053528, 42.039048], + [-73.486206, 42.050002], + [-73.508114, 42.08834], + [-73.267129, 42.745573], + [-72.456542, 42.729142], + [-71.29543, 42.696281], + [-71.185891, 42.789389], + [-70.917521, 42.887974], + ], + ], + }, + }, + { + type: "Feature", + id: "26", + properties: { name: "Michigan", density: 173.9 }, + geometry: { + type: "MultiPolygon", + coordinates: [ + [ + [ + [-83.454238, 41.732339], + [-84.807042, 41.694001], + [-84.807042, 41.759724], + [-85.990061, 41.759724], + [-86.822556, 41.759724], + [-86.619909, 41.891171], + [-86.482986, 42.115725], + [-86.357016, 42.252649], + [-86.263908, 42.444341], + [-86.209139, 42.718189], + [-86.231047, 43.013943], + [-86.526801, 43.594499], + [-86.433693, 43.813577], + [-86.499417, 44.07647], + [-86.269385, 44.34484], + [-86.220093, 44.569394], + [-86.252954, 44.689887], + [-86.088646, 44.73918], + [-86.066738, 44.903488], + [-85.809322, 44.947303], + [-85.612152, 45.128042], + [-85.628583, 44.766564], + [-85.524521, 44.750133], + [-85.393075, 44.930872], + [-85.387598, 45.237581], + [-85.305444, 45.314258], + [-85.031597, 45.363551], + [-85.119228, 45.577151], + [-84.938489, 45.75789], + [-84.713934, 45.768844], + [-84.461995, 45.653829], + [-84.215533, 45.637398], + [-84.09504, 45.494997], + [-83.908824, 45.484043], + [-83.596638, 45.352597], + [-83.4871, 45.358074], + [-83.317314, 45.144473], + [-83.454238, 45.029457], + [-83.322791, 44.88158], + [-83.273499, 44.711795], + [-83.333745, 44.339363], + [-83.536392, 44.246255], + [-83.585684, 44.054562], + [-83.82667, 43.988839], + [-83.958116, 43.758807], + [-83.908824, 43.671176], + [-83.667839, 43.589022], + [-83.481623, 43.714992], + [-83.262545, 43.972408], + [-82.917498, 44.070993], + [-82.747713, 43.994316], + [-82.643651, 43.851915], + [-82.539589, 43.435668], + [-82.523158, 43.227544], + [-82.413619, 42.975605], + [-82.517681, 42.614127], + [-82.681989, 42.559357], + [-82.687466, 42.690804], + [-82.797005, 42.652465], + [-82.922975, 42.351234], + [-83.125621, 42.236218], + [-83.185868, 42.006186], + [-83.437807, 41.814493], + [-83.454238, 41.732339], + ], + ], + [ + [ + [-85.508091, 45.730506], + [-85.49166, 45.610013], + [-85.623106, 45.588105], + [-85.568337, 45.75789], + [-85.508091, 45.730506], + ], + ], + [ + [ + [-87.589328, 45.095181], + [-87.742682, 45.199243], + [-87.649574, 45.341643], + [-87.885083, 45.363551], + [-87.791975, 45.500474], + [-87.781021, 45.675736], + [-87.989145, 45.796229], + [-88.10416, 45.922199], + [-88.531362, 46.020784], + [-88.662808, 45.987922], + [-89.09001, 46.135799], + [-90.119674, 46.338446], + [-90.229213, 46.508231], + [-90.415429, 46.568478], + [-90.026566, 46.672539], + [-89.851304, 46.793032], + [-89.413149, 46.842325], + [-89.128348, 46.990202], + [-88.996902, 46.995679], + [-88.887363, 47.099741], + [-88.575177, 47.247618], + [-88.416346, 47.373588], + [-88.180837, 47.455742], + [-87.956283, 47.384542], + [-88.350623, 47.077833], + [-88.443731, 46.973771], + [-88.438254, 46.787555], + [-88.246561, 46.929956], + [-87.901513, 46.908048], + [-87.633143, 46.809463], + [-87.392158, 46.535616], + [-87.260711, 46.486323], + [-87.008772, 46.530139], + [-86.948526, 46.469893], + [-86.696587, 46.437031], + [-86.159846, 46.667063], + [-85.880522, 46.68897], + [-85.508091, 46.678016], + [-85.256151, 46.754694], + [-85.064458, 46.760171], + [-85.02612, 46.480847], + [-84.82895, 46.442508], + [-84.63178, 46.486323], + [-84.549626, 46.4206], + [-84.418179, 46.502754], + [-84.127902, 46.530139], + [-84.122425, 46.179615], + [-83.990978, 46.031737], + [-83.793808, 45.993399], + [-83.7719, 46.091984], + [-83.580208, 46.091984], + [-83.476146, 45.987922], + [-83.563777, 45.911245], + [-84.111471, 45.976968], + [-84.374364, 45.933153], + [-84.659165, 46.053645], + [-84.741319, 45.944106], + [-84.70298, 45.850998], + [-84.82895, 45.872906], + [-85.015166, 46.00983], + [-85.338305, 46.091984], + [-85.502614, 46.097461], + [-85.661445, 45.966014], + [-85.924338, 45.933153], + [-86.209139, 45.960537], + [-86.324155, 45.905768], + [-86.351539, 45.796229], + [-86.663725, 45.703121], + [-86.647294, 45.834568], + [-86.784218, 45.861952], + [-86.838987, 45.725029], + [-87.069019, 45.719552], + [-87.17308, 45.659305], + [-87.326435, 45.423797], + [-87.611236, 45.122565], + [-87.589328, 45.095181], + ], + ], + [ + [ + [-88.805209, 47.976051], + [-89.057148, 47.850082], + [-89.188594, 47.833651], + [-89.177641, 47.937713], + [-88.547792, 48.173221], + [-88.668285, 48.008913], + [-88.805209, 47.976051], + ], + ], + ], + }, + }, + { + type: "Feature", + id: "27", + properties: { name: "Minnesota", density: 67.14 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-92.014696, 46.705401], + [-92.091373, 46.749217], + [-92.29402, 46.667063], + [-92.29402, 46.075553], + [-92.354266, 46.015307], + [-92.639067, 45.933153], + [-92.869098, 45.719552], + [-92.885529, 45.577151], + [-92.770513, 45.566198], + [-92.644544, 45.440228], + [-92.75956, 45.286874], + [-92.737652, 45.117088], + [-92.808852, 44.750133], + [-92.545959, 44.569394], + [-92.337835, 44.552964], + [-92.233773, 44.443425], + [-91.927065, 44.333886], + [-91.877772, 44.202439], + [-91.592971, 44.032654], + [-91.43414, 43.994316], + [-91.242447, 43.775238], + [-91.269832, 43.616407], + [-91.215062, 43.501391], + [-91.368417, 43.501391], + [-96.451017, 43.501391], + [-96.451017, 45.297827], + [-96.681049, 45.412843], + [-96.856311, 45.604536], + [-96.582464, 45.818137], + [-96.560556, 45.933153], + [-96.598895, 46.332969], + [-96.719387, 46.437031], + [-96.801542, 46.656109], + [-96.785111, 46.924479], + [-96.823449, 46.968294], + [-96.856311, 47.609096], + [-97.053481, 47.948667], + [-97.130158, 48.140359], + [-97.16302, 48.545653], + [-97.097296, 48.682577], + [-97.228743, 49.000239], + [-95.152983, 49.000239], + [-95.152983, 49.383625], + [-94.955813, 49.372671], + [-94.824366, 49.295994], + [-94.69292, 48.775685], + [-94.588858, 48.715438], + [-94.260241, 48.699007], + [-94.221903, 48.649715], + [-93.838517, 48.627807], + [-93.794701, 48.518268], + [-93.466085, 48.545653], + [-93.466085, 48.589469], + [-93.208669, 48.644238], + [-92.984114, 48.62233], + [-92.726698, 48.540176], + [-92.655498, 48.436114], + [-92.50762, 48.447068], + [-92.370697, 48.222514], + [-92.304974, 48.315622], + [-92.053034, 48.359437], + [-92.009219, 48.266329], + [-91.713464, 48.200606], + [-91.713464, 48.112975], + [-91.565587, 48.041775], + [-91.264355, 48.080113], + [-91.083616, 48.178698], + [-90.837154, 48.238944], + [-90.749522, 48.091067], + [-90.579737, 48.123929], + [-90.377091, 48.091067], + [-90.141582, 48.112975], + [-89.873212, 47.987005], + [-89.615796, 48.008913], + [-89.637704, 47.954144], + [-89.971797, 47.828174], + [-90.437337, 47.729589], + [-90.738569, 47.625527], + [-91.171247, 47.368111], + [-91.357463, 47.20928], + [-91.642264, 47.028541], + [-92.091373, 46.787555], + [-92.014696, 46.705401], + ], + ], + }, + }, + { + type: "Feature", + id: "28", + properties: { name: "Mississippi", density: 63.5 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-88.471115, 34.995703], + [-88.202745, 34.995703], + [-88.098683, 34.891641], + [-88.241084, 33.796253], + [-88.471115, 31.895754], + [-88.394438, 30.367688], + [-88.503977, 30.323872], + [-88.744962, 30.34578], + [-88.843547, 30.411504], + [-89.084533, 30.367688], + [-89.418626, 30.252672], + [-89.522688, 30.181472], + [-89.643181, 30.285534], + [-89.681519, 30.449842], + [-89.845827, 30.66892], + [-89.747242, 30.997536], + [-91.636787, 30.997536], + [-91.565587, 31.068736], + [-91.636787, 31.265906], + [-91.516294, 31.27686], + [-91.499863, 31.643815], + [-91.401278, 31.621907], + [-91.341032, 31.846462], + [-91.105524, 31.988862], + [-90.985031, 32.218894], + [-91.006939, 32.514649], + [-91.154816, 32.640618], + [-91.143862, 32.843265], + [-91.072662, 32.887081], + [-91.16577, 33.002096], + [-91.089093, 33.13902], + [-91.143862, 33.347144], + [-91.056231, 33.429298], + [-91.231493, 33.560744], + [-91.072662, 33.867453], + [-90.891923, 34.026284], + [-90.952169, 34.135823], + [-90.744046, 34.300131], + [-90.749522, 34.365854], + [-90.568783, 34.420624], + [-90.585214, 34.617794], + [-90.481152, 34.661609], + [-90.409952, 34.831394], + [-90.251121, 34.908072], + [-90.311367, 34.995703], + [-88.471115, 34.995703], + ], + ], + }, + }, + { + type: "Feature", + id: "29", + properties: { name: "Missouri", density: 87.26 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-91.833957, 40.609566], + [-91.729895, 40.615043], + [-91.527248, 40.412397], + [-91.417709, 40.379535], + [-91.50534, 40.237135], + [-91.494386, 40.034488], + [-91.368417, 39.727779], + [-91.061708, 39.470363], + [-90.727615, 39.256762], + [-90.661891, 38.928146], + [-90.585214, 38.867899], + [-90.470199, 38.961007], + [-90.251121, 38.917192], + [-90.10872, 38.845992], + [-90.207305, 38.725499], + [-90.179921, 38.632391], + [-90.349706, 38.374975], + [-90.355183, 38.216144], + [-90.059428, 38.013497], + [-89.949889, 37.88205], + [-89.84035, 37.903958], + [-89.517211, 37.690357], + [-89.517211, 37.537003], + [-89.435057, 37.34531], + [-89.517211, 37.279587], + [-89.292656, 36.994786], + [-89.133825, 36.983832], + [-89.215979, 36.578538], + [-89.363857, 36.622354], + [-89.418626, 36.496384], + [-89.484349, 36.496384], + [-89.539119, 36.496384], + [-89.533642, 36.249922], + [-89.730812, 35.997983], + [-90.377091, 35.997983], + [-90.218259, 36.184199], + [-90.064905, 36.304691], + [-90.152536, 36.496384], + [-94.473842, 36.501861], + [-94.616242, 36.501861], + [-94.616242, 37.000263], + [-94.610765, 39.158177], + [-94.824366, 39.20747], + [-94.983197, 39.442978], + [-95.109167, 39.541563], + [-94.884612, 39.831841], + [-95.207752, 39.908518], + [-95.306337, 40.001626], + [-95.552799, 40.264519], + [-95.7664, 40.587659], + [-94.632673, 40.571228], + [-93.257961, 40.582182], + [-91.833957, 40.609566], + ], + ], + }, + }, + { + type: "Feature", + id: "30", + properties: { name: "Montana", density: 6.858 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-104.047534, 49.000239], + [-104.042057, 47.861036], + [-104.047534, 45.944106], + [-104.042057, 44.996596], + [-104.058488, 44.996596], + [-105.91517, 45.002073], + [-109.080842, 45.002073], + [-111.05254, 45.002073], + [-111.047063, 44.476286], + [-111.227803, 44.580348], + [-111.386634, 44.75561], + [-111.616665, 44.547487], + [-111.819312, 44.509148], + [-111.868605, 44.563917], + [-112.104113, 44.520102], + [-112.241036, 44.569394], + [-112.471068, 44.481763], + [-112.783254, 44.48724], + [-112.887315, 44.394132], + [-113.002331, 44.448902], + [-113.133778, 44.772041], + [-113.341901, 44.782995], + [-113.456917, 44.865149], + [-113.45144, 45.056842], + [-113.571933, 45.128042], + [-113.736241, 45.330689], + [-113.834826, 45.522382], + [-113.807441, 45.604536], + [-113.98818, 45.703121], + [-114.086765, 45.593582], + [-114.333228, 45.456659], + [-114.546828, 45.560721], + [-114.497536, 45.670259], + [-114.568736, 45.774321], + [-114.387997, 45.88386], + [-114.492059, 46.037214], + [-114.464674, 46.272723], + [-114.322274, 46.645155], + [-114.612552, 46.639678], + [-114.623506, 46.705401], + [-114.886399, 46.809463], + [-114.930214, 46.919002], + [-115.302646, 47.187372], + [-115.324554, 47.258572], + [-115.527201, 47.302388], + [-115.718894, 47.42288], + [-115.724371, 47.696727], + [-116.04751, 47.976051], + [-116.04751, 49.000239], + [-111.50165, 48.994762], + [-109.453274, 49.000239], + [-104.047534, 49.000239], + ], + ], + }, + }, + { + type: "Feature", + id: "31", + properties: { name: "Nebraska", density: 23.97 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-103.324578, 43.002989], + [-101.626726, 42.997512], + [-98.499393, 42.997512], + [-98.466531, 42.94822], + [-97.951699, 42.767481], + [-97.831206, 42.866066], + [-97.688806, 42.844158], + [-97.217789, 42.844158], + [-96.692003, 42.657942], + [-96.626279, 42.515542], + [-96.44554, 42.488157], + [-96.264801, 42.039048], + [-96.127878, 41.973325], + [-96.062155, 41.798063], + [-96.122401, 41.67757], + [-96.095016, 41.540646], + [-95.919754, 41.453015], + [-95.925231, 41.201076], + [-95.826646, 40.976521], + [-95.881416, 40.719105], + [-95.7664, 40.587659], + [-95.552799, 40.264519], + [-95.306337, 40.001626], + [-101.90605, 40.001626], + [-102.053927, 40.001626], + [-102.053927, 41.003906], + [-104.053011, 41.003906], + [-104.053011, 43.002989], + [-103.324578, 43.002989], + ], + ], + }, + }, + { + type: "Feature", + id: "32", + properties: { name: "Nevada", density: 24.8 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-117.027882, 42.000709], + [-114.04295, 41.995232], + [-114.048427, 37.000263], + [-114.048427, 36.195153], + [-114.152489, 36.025367], + [-114.251074, 36.01989], + [-114.371566, 36.140383], + [-114.738521, 36.102045], + [-114.678275, 35.516012], + [-114.596121, 35.324319], + [-114.574213, 35.138103], + [-114.634459, 35.00118], + [-115.85034, 35.970598], + [-116.540435, 36.501861], + [-117.498899, 37.21934], + [-118.71478, 38.101128], + [-120.001861, 38.999346], + [-119.996384, 40.264519], + [-120.001861, 41.995232], + [-118.698349, 41.989755], + [-117.027882, 42.000709], + ], + ], + }, + }, + { + type: "Feature", + id: "33", + properties: { name: "New Hampshire", density: 147 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-71.08183, 45.303304], + [-71.032537, 44.657025], + [-70.966814, 43.34256], + [-70.807983, 43.227544], + [-70.824413, 43.128959], + [-70.703921, 43.057759], + [-70.818936, 42.871543], + [-70.917521, 42.887974], + [-71.185891, 42.789389], + [-71.29543, 42.696281], + [-72.456542, 42.729142], + [-72.544173, 42.80582], + [-72.533219, 42.953697], + [-72.445588, 43.008466], + [-72.456542, 43.150867], + [-72.379864, 43.572591], + [-72.204602, 43.769761], + [-72.116971, 43.994316], + [-72.02934, 44.07647], + [-72.034817, 44.322932], + [-71.700724, 44.41604], + [-71.536416, 44.585825], + [-71.629524, 44.750133], + [-71.4926, 44.914442], + [-71.503554, 45.013027], + [-71.361154, 45.270443], + [-71.131122, 45.243058], + [-71.08183, 45.303304], + ], + ], + }, + }, + { + type: "Feature", + id: "34", + properties: { name: "New Jersey", density: 1189 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-74.236547, 41.14083], + [-73.902454, 40.998429], + [-74.022947, 40.708151], + [-74.187255, 40.642428], + [-74.274886, 40.489074], + [-74.001039, 40.412397], + [-73.979131, 40.297381], + [-74.099624, 39.760641], + [-74.411809, 39.360824], + [-74.614456, 39.245808], + [-74.795195, 38.993869], + [-74.888303, 39.158177], + [-75.178581, 39.240331], + [-75.534582, 39.459409], + [-75.55649, 39.607286], + [-75.561967, 39.629194], + [-75.507197, 39.683964], + [-75.414089, 39.804456], + [-75.145719, 39.88661], + [-75.129289, 39.963288], + [-74.82258, 40.127596], + [-74.773287, 40.215227], + [-75.058088, 40.417874], + [-75.069042, 40.543843], + [-75.195012, 40.576705], + [-75.205966, 40.691721], + [-75.052611, 40.866983], + [-75.134765, 40.971045], + [-74.882826, 41.179168], + [-74.828057, 41.288707], + [-74.69661, 41.359907], + [-74.236547, 41.14083], + ], + ], + }, + }, + { + type: "Feature", + id: "35", + properties: { name: "New Mexico", density: 17.16 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-107.421329, 37.000263], + [-106.868158, 36.994786], + [-104.337812, 36.994786], + [-103.001438, 37.000263], + [-103.001438, 36.501861], + [-103.039777, 36.501861], + [-103.045254, 34.01533], + [-103.067161, 33.002096], + [-103.067161, 31.999816], + [-106.616219, 31.999816], + [-106.643603, 31.901231], + [-106.528588, 31.786216], + [-108.210008, 31.786216], + [-108.210008, 31.331629], + [-109.04798, 31.331629], + [-109.042503, 37.000263], + [-107.421329, 37.000263], + ], + ], + }, + }, + { + type: "Feature", + id: "36", + properties: { name: "New York", density: 412.3 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-73.343806, 45.013027], + [-73.332852, 44.804903], + [-73.387622, 44.618687], + [-73.294514, 44.437948], + [-73.321898, 44.246255], + [-73.436914, 44.043608], + [-73.349283, 43.769761], + [-73.404052, 43.687607], + [-73.245221, 43.523299], + [-73.278083, 42.833204], + [-73.267129, 42.745573], + [-73.508114, 42.08834], + [-73.486206, 42.050002], + [-73.55193, 41.294184], + [-73.48073, 41.21203], + [-73.727192, 41.102491], + [-73.655992, 40.987475], + [-73.22879, 40.905321], + [-73.141159, 40.965568], + [-72.774204, 40.965568], + [-72.587988, 40.998429], + [-72.28128, 41.157261], + [-72.259372, 41.042245], + [-72.100541, 40.992952], + [-72.467496, 40.845075], + [-73.239744, 40.625997], + [-73.562884, 40.582182], + [-73.776484, 40.593136], + [-73.935316, 40.543843], + [-74.022947, 40.708151], + [-73.902454, 40.998429], + [-74.236547, 41.14083], + [-74.69661, 41.359907], + [-74.740426, 41.431108], + [-74.89378, 41.436584], + [-75.074519, 41.60637], + [-75.052611, 41.754247], + [-75.173104, 41.869263], + [-75.249781, 41.863786], + [-75.35932, 42.000709], + [-79.76278, 42.000709], + [-79.76278, 42.252649], + [-79.76278, 42.269079], + [-79.149363, 42.55388], + [-79.050778, 42.690804], + [-78.853608, 42.783912], + [-78.930285, 42.953697], + [-79.012439, 42.986559], + [-79.072686, 43.260406], + [-78.486653, 43.375421], + [-77.966344, 43.369944], + [-77.75822, 43.34256], + [-77.533665, 43.233021], + [-77.391265, 43.276836], + [-76.958587, 43.271359], + [-76.695693, 43.34256], + [-76.41637, 43.523299], + [-76.235631, 43.528776], + [-76.230154, 43.802623], + [-76.137046, 43.961454], + [-76.3616, 44.070993], + [-76.312308, 44.196962], + [-75.912491, 44.366748], + [-75.764614, 44.514625], + [-75.282643, 44.848718], + [-74.828057, 45.018503], + [-74.148916, 44.991119], + [-73.343806, 45.013027], + ], + ], + }, + }, + { + type: "Feature", + id: "37", + properties: { name: "North Carolina", density: 198.2 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-80.978661, 36.562108], + [-80.294043, 36.545677], + [-79.510841, 36.5402], + [-75.868676, 36.551154], + [-75.75366, 36.151337], + [-76.032984, 36.189676], + [-76.071322, 36.140383], + [-76.410893, 36.080137], + [-76.460185, 36.025367], + [-76.68474, 36.008937], + [-76.673786, 35.937736], + [-76.399939, 35.987029], + [-76.3616, 35.943213], + [-76.060368, 35.992506], + [-75.961783, 35.899398], + [-75.781044, 35.937736], + [-75.715321, 35.696751], + [-75.775568, 35.581735], + [-75.89606, 35.570781], + [-76.147999, 35.324319], + [-76.482093, 35.313365], + [-76.536862, 35.14358], + [-76.394462, 34.973795], + [-76.279446, 34.940933], + [-76.493047, 34.661609], + [-76.673786, 34.694471], + [-76.991448, 34.667086], + [-77.210526, 34.60684], + [-77.555573, 34.415147], + [-77.82942, 34.163208], + [-77.971821, 33.845545], + [-78.179944, 33.916745], + [-78.541422, 33.851022], + [-79.675149, 34.80401], + [-80.797922, 34.820441], + [-80.781491, 34.935456], + [-80.934845, 35.105241], + [-81.038907, 35.044995], + [-81.044384, 35.149057], + [-82.276696, 35.198349], + [-82.550543, 35.160011], + [-82.764143, 35.066903], + [-83.109191, 35.00118], + [-83.618546, 34.984749], + [-84.319594, 34.990226], + [-84.29221, 35.225734], + [-84.09504, 35.247642], + [-84.018363, 35.41195], + [-83.7719, 35.559827], + [-83.498053, 35.565304], + [-83.251591, 35.718659], + [-82.994175, 35.773428], + [-82.775097, 35.997983], + [-82.638174, 36.063706], + [-82.610789, 35.965121], + [-82.216449, 36.156814], + [-82.03571, 36.118475], + [-81.909741, 36.304691], + [-81.723525, 36.353984], + [-81.679709, 36.589492], + [-80.978661, 36.562108], + ], + ], + }, + }, + { + type: "Feature", + id: "38", + properties: { name: "North Dakota", density: 9.916 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-97.228743, 49.000239], + [-97.097296, 48.682577], + [-97.16302, 48.545653], + [-97.130158, 48.140359], + [-97.053481, 47.948667], + [-96.856311, 47.609096], + [-96.823449, 46.968294], + [-96.785111, 46.924479], + [-96.801542, 46.656109], + [-96.719387, 46.437031], + [-96.598895, 46.332969], + [-96.560556, 45.933153], + [-104.047534, 45.944106], + [-104.042057, 47.861036], + [-104.047534, 49.000239], + [-97.228743, 49.000239], + ], + ], + }, + }, + { + type: "Feature", + id: "39", + properties: { name: "Ohio", density: 281.9 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-80.518598, 41.978802], + [-80.518598, 40.636951], + [-80.666475, 40.582182], + [-80.595275, 40.472643], + [-80.600752, 40.319289], + [-80.737675, 40.078303], + [-80.830783, 39.711348], + [-81.219646, 39.388209], + [-81.345616, 39.344393], + [-81.455155, 39.410117], + [-81.57017, 39.267716], + [-81.685186, 39.273193], + [-81.811156, 39.0815], + [-81.783771, 38.966484], + [-81.887833, 38.873376], + [-82.03571, 39.026731], + [-82.221926, 38.785745], + [-82.172634, 38.632391], + [-82.293127, 38.577622], + [-82.331465, 38.446175], + [-82.594358, 38.424267], + [-82.731282, 38.561191], + [-82.846298, 38.588575], + [-82.890113, 38.758361], + [-83.032514, 38.725499], + [-83.142052, 38.626914], + [-83.519961, 38.703591], + [-83.678792, 38.632391], + [-83.903347, 38.769315], + [-84.215533, 38.807653], + [-84.231963, 38.895284], + [-84.43461, 39.103408], + [-84.817996, 39.103408], + [-84.801565, 40.500028], + [-84.807042, 41.694001], + [-83.454238, 41.732339], + [-83.065375, 41.595416], + [-82.933929, 41.513262], + [-82.835344, 41.589939], + [-82.616266, 41.431108], + [-82.479343, 41.381815], + [-82.013803, 41.513262], + [-81.739956, 41.485877], + [-81.444201, 41.672093], + [-81.011523, 41.852832], + [-80.518598, 41.978802], + [-80.518598, 41.978802], + ], + ], + }, + }, + { + type: "Feature", + id: "40", + properties: { name: "Oklahoma", density: 55.22 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-100.087706, 37.000263], + [-94.616242, 37.000263], + [-94.616242, 36.501861], + [-94.430026, 35.395519], + [-94.484796, 33.637421], + [-94.868182, 33.74696], + [-94.966767, 33.861976], + [-95.224183, 33.960561], + [-95.289906, 33.87293], + [-95.547322, 33.878407], + [-95.602092, 33.933176], + [-95.8376, 33.834591], + [-95.936185, 33.889361], + [-96.149786, 33.840068], + [-96.346956, 33.686714], + [-96.423633, 33.774345], + [-96.631756, 33.845545], + [-96.850834, 33.845545], + [-96.922034, 33.960561], + [-97.173974, 33.736006], + [-97.256128, 33.861976], + [-97.371143, 33.823637], + [-97.458774, 33.905791], + [-97.694283, 33.982469], + [-97.869545, 33.851022], + [-97.946222, 33.987946], + [-98.088623, 34.004376], + [-98.170777, 34.113915], + [-98.36247, 34.157731], + [-98.488439, 34.064623], + [-98.570593, 34.146777], + [-98.767763, 34.135823], + [-98.986841, 34.223454], + [-99.189488, 34.2125], + [-99.260688, 34.404193], + [-99.57835, 34.415147], + [-99.698843, 34.382285], + [-99.923398, 34.573978], + [-100.000075, 34.563024], + [-100.000075, 36.501861], + [-101.812942, 36.501861], + [-103.001438, 36.501861], + [-103.001438, 37.000263], + [-102.042974, 36.994786], + [-100.087706, 37.000263], + ], + ], + }, + }, + { + type: "Feature", + id: "41", + properties: { name: "Oregon", density: 40.33 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-123.211348, 46.174138], + [-123.11824, 46.185092], + [-122.904639, 46.08103], + [-122.811531, 45.960537], + [-122.762239, 45.659305], + [-122.247407, 45.549767], + [-121.809251, 45.708598], + [-121.535404, 45.725029], + [-121.217742, 45.670259], + [-121.18488, 45.604536], + [-120.637186, 45.746937], + [-120.505739, 45.697644], + [-120.209985, 45.725029], + [-119.963522, 45.823614], + [-119.525367, 45.911245], + [-119.125551, 45.933153], + [-118.988627, 45.998876], + [-116.918344, 45.993399], + [-116.78142, 45.823614], + [-116.545912, 45.752413], + [-116.463758, 45.61549], + [-116.671881, 45.319735], + [-116.732128, 45.144473], + [-116.847143, 45.02398], + [-116.830713, 44.930872], + [-116.934774, 44.782995], + [-117.038836, 44.750133], + [-117.241483, 44.394132], + [-117.170283, 44.257209], + [-116.97859, 44.240778], + [-116.896436, 44.158624], + [-117.027882, 43.830007], + [-117.027882, 42.000709], + [-118.698349, 41.989755], + [-120.001861, 41.995232], + [-121.037003, 41.995232], + [-122.378853, 42.011663], + [-123.233256, 42.006186], + [-124.213628, 42.000709], + [-124.356029, 42.115725], + [-124.432706, 42.438865], + [-124.416275, 42.663419], + [-124.553198, 42.838681], + [-124.454613, 43.002989], + [-124.383413, 43.271359], + [-124.235536, 43.55616], + [-124.169813, 43.8081], + [-124.060274, 44.657025], + [-124.076705, 44.772041], + [-123.97812, 45.144473], + [-123.939781, 45.659305], + [-123.994551, 45.944106], + [-123.945258, 46.113892], + [-123.545441, 46.261769], + [-123.370179, 46.146753], + [-123.211348, 46.174138], + ], + ], + }, + }, + { + type: "Feature", + id: "42", + properties: { name: "Pennsylvania", density: 284.3 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-79.76278, 42.252649], + [-79.76278, 42.000709], + [-75.35932, 42.000709], + [-75.249781, 41.863786], + [-75.173104, 41.869263], + [-75.052611, 41.754247], + [-75.074519, 41.60637], + [-74.89378, 41.436584], + [-74.740426, 41.431108], + [-74.69661, 41.359907], + [-74.828057, 41.288707], + [-74.882826, 41.179168], + [-75.134765, 40.971045], + [-75.052611, 40.866983], + [-75.205966, 40.691721], + [-75.195012, 40.576705], + [-75.069042, 40.543843], + [-75.058088, 40.417874], + [-74.773287, 40.215227], + [-74.82258, 40.127596], + [-75.129289, 39.963288], + [-75.145719, 39.88661], + [-75.414089, 39.804456], + [-75.616736, 39.831841], + [-75.786521, 39.722302], + [-79.477979, 39.722302], + [-80.518598, 39.722302], + [-80.518598, 40.636951], + [-80.518598, 41.978802], + [-80.518598, 41.978802], + [-80.332382, 42.033571], + [-79.76278, 42.269079], + [-79.76278, 42.252649], + ], + ], + }, + }, + { + type: "Feature", + id: "44", + properties: { name: "Rhode Island", density: 1006 }, + geometry: { + type: "MultiPolygon", + coordinates: [ + [ + [ + [-71.196845, 41.67757], + [-71.120168, 41.496831], + [-71.317338, 41.474923], + [-71.196845, 41.67757], + ], + ], + [ + [ + [-71.530939, 42.01714], + [-71.383061, 42.01714], + [-71.328292, 41.781632], + [-71.22423, 41.710431], + [-71.344723, 41.726862], + [-71.448785, 41.578985], + [-71.481646, 41.370861], + [-71.859555, 41.321569], + [-71.799309, 41.414677], + [-71.799309, 42.006186], + [-71.530939, 42.01714], + ], + ], + ], + }, + }, + { + type: "Feature", + id: "45", + properties: { name: "South Carolina", density: 155.4 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-82.764143, 35.066903], + [-82.550543, 35.160011], + [-82.276696, 35.198349], + [-81.044384, 35.149057], + [-81.038907, 35.044995], + [-80.934845, 35.105241], + [-80.781491, 34.935456], + [-80.797922, 34.820441], + [-79.675149, 34.80401], + [-78.541422, 33.851022], + [-78.716684, 33.80173], + [-78.935762, 33.637421], + [-79.149363, 33.380005], + [-79.187701, 33.171881], + [-79.357487, 33.007573], + [-79.582041, 33.007573], + [-79.631334, 32.887081], + [-79.866842, 32.755634], + [-79.998289, 32.613234], + [-80.206412, 32.552987], + [-80.430967, 32.399633], + [-80.452875, 32.328433], + [-80.660998, 32.246279], + [-80.885553, 32.032678], + [-81.115584, 32.120309], + [-81.121061, 32.290094], + [-81.279893, 32.558464], + [-81.416816, 32.629664], + [-81.42777, 32.843265], + [-81.493493, 33.007573], + [-81.761863, 33.160928], + [-81.937125, 33.347144], + [-81.926172, 33.462159], + [-82.194542, 33.631944], + [-82.325988, 33.81816], + [-82.55602, 33.94413], + [-82.714851, 34.152254], + [-82.747713, 34.26727], + [-82.901067, 34.486347], + [-83.005129, 34.469916], + [-83.339222, 34.683517], + [-83.322791, 34.787579], + [-83.109191, 35.00118], + [-82.764143, 35.066903], + ], + ], + }, + }, + { + type: "Feature", + id: "46", + properties: { name: "South Dakota", density: 98.07 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-104.047534, 45.944106], + [-96.560556, 45.933153], + [-96.582464, 45.818137], + [-96.856311, 45.604536], + [-96.681049, 45.412843], + [-96.451017, 45.297827], + [-96.451017, 43.501391], + [-96.582464, 43.479483], + [-96.527695, 43.397329], + [-96.560556, 43.222067], + [-96.434587, 43.123482], + [-96.511264, 43.052282], + [-96.544125, 42.855112], + [-96.631756, 42.707235], + [-96.44554, 42.488157], + [-96.626279, 42.515542], + [-96.692003, 42.657942], + [-97.217789, 42.844158], + [-97.688806, 42.844158], + [-97.831206, 42.866066], + [-97.951699, 42.767481], + [-98.466531, 42.94822], + [-98.499393, 42.997512], + [-101.626726, 42.997512], + [-103.324578, 43.002989], + [-104.053011, 43.002989], + [-104.058488, 44.996596], + [-104.042057, 44.996596], + [-104.047534, 45.944106], + ], + ], + }, + }, + { + type: "Feature", + id: "47", + properties: { name: "Tennessee", density: 88.08 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-88.054868, 36.496384], + [-88.071299, 36.677123], + [-87.852221, 36.633308], + [-86.592525, 36.655216], + [-85.486183, 36.616877], + [-85.289013, 36.627831], + [-84.544149, 36.594969], + [-83.689746, 36.584015], + [-83.673316, 36.600446], + [-81.679709, 36.589492], + [-81.723525, 36.353984], + [-81.909741, 36.304691], + [-82.03571, 36.118475], + [-82.216449, 36.156814], + [-82.610789, 35.965121], + [-82.638174, 36.063706], + [-82.775097, 35.997983], + [-82.994175, 35.773428], + [-83.251591, 35.718659], + [-83.498053, 35.565304], + [-83.7719, 35.559827], + [-84.018363, 35.41195], + [-84.09504, 35.247642], + [-84.29221, 35.225734], + [-84.319594, 34.990226], + [-85.606675, 34.984749], + [-87.359296, 35.00118], + [-88.202745, 34.995703], + [-88.471115, 34.995703], + [-90.311367, 34.995703], + [-90.212782, 35.023087], + [-90.114197, 35.198349], + [-90.130628, 35.439335], + [-89.944412, 35.603643], + [-89.911551, 35.756997], + [-89.763673, 35.811767], + [-89.730812, 35.997983], + [-89.533642, 36.249922], + [-89.539119, 36.496384], + [-89.484349, 36.496384], + [-89.418626, 36.496384], + [-89.298133, 36.507338], + [-88.054868, 36.496384], + ], + ], + }, + }, + { + type: "Feature", + id: "48", + properties: { name: "Texas", density: 98.07 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-101.812942, 36.501861], + [-100.000075, 36.501861], + [-100.000075, 34.563024], + [-99.923398, 34.573978], + [-99.698843, 34.382285], + [-99.57835, 34.415147], + [-99.260688, 34.404193], + [-99.189488, 34.2125], + [-98.986841, 34.223454], + [-98.767763, 34.135823], + [-98.570593, 34.146777], + [-98.488439, 34.064623], + [-98.36247, 34.157731], + [-98.170777, 34.113915], + [-98.088623, 34.004376], + [-97.946222, 33.987946], + [-97.869545, 33.851022], + [-97.694283, 33.982469], + [-97.458774, 33.905791], + [-97.371143, 33.823637], + [-97.256128, 33.861976], + [-97.173974, 33.736006], + [-96.922034, 33.960561], + [-96.850834, 33.845545], + [-96.631756, 33.845545], + [-96.423633, 33.774345], + [-96.346956, 33.686714], + [-96.149786, 33.840068], + [-95.936185, 33.889361], + [-95.8376, 33.834591], + [-95.602092, 33.933176], + [-95.547322, 33.878407], + [-95.289906, 33.87293], + [-95.224183, 33.960561], + [-94.966767, 33.861976], + [-94.868182, 33.74696], + [-94.484796, 33.637421], + [-94.380734, 33.544313], + [-94.183564, 33.593606], + [-94.041164, 33.54979], + [-94.041164, 33.018527], + [-94.041164, 31.994339], + [-93.822086, 31.775262], + [-93.816609, 31.556184], + [-93.542762, 31.15089], + [-93.526331, 30.93729], + [-93.630393, 30.679874], + [-93.728978, 30.575812], + [-93.696116, 30.438888], + [-93.767317, 30.334826], + [-93.690639, 30.143133], + [-93.926148, 29.787132], + [-93.838517, 29.688547], + [-94.002825, 29.68307], + [-94.523134, 29.546147], + [-94.70935, 29.622824], + [-94.742212, 29.787132], + [-94.873659, 29.672117], + [-94.966767, 29.699501], + [-95.016059, 29.557101], + [-94.911997, 29.496854], + [-94.895566, 29.310638], + [-95.081782, 29.113469], + [-95.383014, 28.867006], + [-95.985477, 28.604113], + [-96.045724, 28.647929], + [-96.226463, 28.582205], + [-96.23194, 28.642452], + [-96.478402, 28.598636], + [-96.593418, 28.724606], + [-96.664618, 28.697221], + [-96.401725, 28.439805], + [-96.593418, 28.357651], + [-96.774157, 28.406943], + [-96.801542, 28.226204], + [-97.026096, 28.039988], + [-97.256128, 27.694941], + [-97.404005, 27.333463], + [-97.513544, 27.360848], + [-97.540929, 27.229401], + [-97.425913, 27.262263], + [-97.480682, 26.99937], + [-97.557359, 26.988416], + [-97.562836, 26.840538], + [-97.469728, 26.758384], + [-97.442344, 26.457153], + [-97.332805, 26.353091], + [-97.30542, 26.161398], + [-97.217789, 25.991613], + [-97.524498, 25.887551], + [-97.650467, 26.018997], + [-97.885976, 26.06829], + [-98.198161, 26.057336], + [-98.466531, 26.221644], + [-98.669178, 26.238075], + [-98.822533, 26.369522], + [-99.030656, 26.413337], + [-99.173057, 26.539307], + [-99.266165, 26.840538], + [-99.446904, 27.021277], + [-99.424996, 27.174632], + [-99.50715, 27.33894], + [-99.479765, 27.48134], + [-99.605735, 27.640172], + [-99.709797, 27.656603], + [-99.879582, 27.799003], + [-99.934351, 27.979742], + [-100.082229, 28.14405], + [-100.29583, 28.280974], + [-100.399891, 28.582205], + [-100.498476, 28.66436], + [-100.629923, 28.905345], + [-100.673738, 29.102515], + [-100.799708, 29.244915], + [-101.013309, 29.370885], + [-101.062601, 29.458516], + [-101.259771, 29.535193], + [-101.413125, 29.754271], + [-101.851281, 29.803563], + [-102.114174, 29.792609], + [-102.338728, 29.869286], + [-102.388021, 29.765225], + [-102.629006, 29.732363], + [-102.809745, 29.524239], + [-102.919284, 29.190146], + [-102.97953, 29.184669], + [-103.116454, 28.987499], + [-103.280762, 28.982022], + [-103.527224, 29.135376], + [-104.146119, 29.381839], + [-104.266611, 29.513285], + [-104.507597, 29.639255], + [-104.677382, 29.924056], + [-104.688336, 30.181472], + [-104.858121, 30.389596], + [-104.896459, 30.570335], + [-105.005998, 30.685351], + [-105.394861, 30.855136], + [-105.602985, 31.085167], + [-105.77277, 31.167321], + [-105.953509, 31.364491], + [-106.205448, 31.468553], + [-106.38071, 31.731446], + [-106.528588, 31.786216], + [-106.643603, 31.901231], + [-106.616219, 31.999816], + [-103.067161, 31.999816], + [-103.067161, 33.002096], + [-103.045254, 34.01533], + [-103.039777, 36.501861], + [-103.001438, 36.501861], + [-101.812942, 36.501861], + ], + ], + }, + }, + { + type: "Feature", + id: "49", + properties: { name: "Utah", density: 34.3 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-112.164359, 41.995232], + [-111.047063, 42.000709], + [-111.047063, 40.998429], + [-109.04798, 40.998429], + [-109.053457, 39.125316], + [-109.058934, 38.27639], + [-109.042503, 38.166851], + [-109.042503, 37.000263], + [-110.499369, 37.00574], + [-114.048427, 37.000263], + [-114.04295, 41.995232], + [-112.164359, 41.995232], + ], + ], + }, + }, + { + type: "Feature", + id: "50", + properties: { name: "Vermont", density: 67.73 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-71.503554, 45.013027], + [-71.4926, 44.914442], + [-71.629524, 44.750133], + [-71.536416, 44.585825], + [-71.700724, 44.41604], + [-72.034817, 44.322932], + [-72.02934, 44.07647], + [-72.116971, 43.994316], + [-72.204602, 43.769761], + [-72.379864, 43.572591], + [-72.456542, 43.150867], + [-72.445588, 43.008466], + [-72.533219, 42.953697], + [-72.544173, 42.80582], + [-72.456542, 42.729142], + [-73.267129, 42.745573], + [-73.278083, 42.833204], + [-73.245221, 43.523299], + [-73.404052, 43.687607], + [-73.349283, 43.769761], + [-73.436914, 44.043608], + [-73.321898, 44.246255], + [-73.294514, 44.437948], + [-73.387622, 44.618687], + [-73.332852, 44.804903], + [-73.343806, 45.013027], + [-72.308664, 45.002073], + [-71.503554, 45.013027], + ], + ], + }, + }, + { + type: "Feature", + id: "51", + properties: { name: "Virginia", density: 204.5 }, + geometry: { + type: "MultiPolygon", + coordinates: [ + [ + [ + [-75.397659, 38.013497], + [-75.244304, 38.029928], + [-75.375751, 37.860142], + [-75.512674, 37.799896], + [-75.594828, 37.569865], + [-75.802952, 37.197433], + [-75.972737, 37.120755], + [-76.027507, 37.257679], + [-75.939876, 37.564388], + [-75.671506, 37.95325], + [-75.397659, 38.013497], + ], + ], + [ + [ + [-76.016553, 37.95325], + [-75.994645, 37.95325], + [-76.043938, 37.95325], + [-76.016553, 37.95325], + ], + ], + [ + [ + [-78.349729, 39.464886], + [-77.82942, 39.130793], + [-77.719881, 39.322485], + [-77.566527, 39.306055], + [-77.456988, 39.223901], + [-77.456988, 39.076023], + [-77.248864, 39.026731], + [-77.117418, 38.933623], + [-77.040741, 38.791222], + [-77.128372, 38.632391], + [-77.248864, 38.588575], + [-77.325542, 38.446175], + [-77.281726, 38.342113], + [-77.013356, 38.374975], + [-76.964064, 38.216144], + [-76.613539, 38.15042], + [-76.514954, 38.024451], + [-76.235631, 37.887527], + [-76.3616, 37.608203], + [-76.246584, 37.389126], + [-76.383508, 37.285064], + [-76.399939, 37.159094], + [-76.273969, 37.082417], + [-76.410893, 36.961924], + [-76.619016, 37.120755], + [-76.668309, 37.065986], + [-76.48757, 36.95097], + [-75.994645, 36.923586], + [-75.868676, 36.551154], + [-79.510841, 36.5402], + [-80.294043, 36.545677], + [-80.978661, 36.562108], + [-81.679709, 36.589492], + [-83.673316, 36.600446], + [-83.136575, 36.742847], + [-83.070852, 36.852385], + [-82.879159, 36.890724], + [-82.868205, 36.978355], + [-82.720328, 37.044078], + [-82.720328, 37.120755], + [-82.353373, 37.268633], + [-81.969987, 37.537003], + [-81.986418, 37.454849], + [-81.849494, 37.285064], + [-81.679709, 37.20291], + [-81.55374, 37.208387], + [-81.362047, 37.339833], + [-81.225123, 37.235771], + [-80.967707, 37.290541], + [-80.513121, 37.482234], + [-80.474782, 37.421987], + [-80.29952, 37.509618], + [-80.294043, 37.690357], + [-80.184505, 37.849189], + [-79.998289, 37.997066], + [-79.921611, 38.177805], + [-79.724442, 38.364021], + [-79.647764, 38.594052], + [-79.477979, 38.457129], + [-79.313671, 38.413313], + [-79.209609, 38.495467], + [-78.996008, 38.851469], + [-78.870039, 38.763838], + [-78.404499, 39.169131], + [-78.349729, 39.464886], + ], + ], + ], + }, + }, + { + type: "Feature", + id: "53", + properties: { name: "Washington", density: 102.6 }, + geometry: { + type: "MultiPolygon", + coordinates: [ + [ + [ + [-117.033359, 49.000239], + [-117.044313, 47.762451], + [-117.038836, 46.426077], + [-117.055267, 46.343923], + [-116.92382, 46.168661], + [-116.918344, 45.993399], + [-118.988627, 45.998876], + [-119.125551, 45.933153], + [-119.525367, 45.911245], + [-119.963522, 45.823614], + [-120.209985, 45.725029], + [-120.505739, 45.697644], + [-120.637186, 45.746937], + [-121.18488, 45.604536], + [-121.217742, 45.670259], + [-121.535404, 45.725029], + [-121.809251, 45.708598], + [-122.247407, 45.549767], + [-122.762239, 45.659305], + [-122.811531, 45.960537], + [-122.904639, 46.08103], + [-123.11824, 46.185092], + [-123.211348, 46.174138], + [-123.370179, 46.146753], + [-123.545441, 46.261769], + [-123.72618, 46.300108], + [-123.874058, 46.239861], + [-124.065751, 46.327492], + [-124.027412, 46.464416], + [-123.895966, 46.535616], + [-124.098612, 46.74374], + [-124.235536, 47.285957], + [-124.31769, 47.357157], + [-124.427229, 47.740543], + [-124.624399, 47.88842], + [-124.706553, 48.184175], + [-124.597014, 48.381345], + [-124.394367, 48.288237], + [-123.983597, 48.162267], + [-123.704273, 48.167744], + [-123.424949, 48.118452], + [-123.162056, 48.167744], + [-123.036086, 48.080113], + [-122.800578, 48.08559], + [-122.636269, 47.866512], + [-122.515777, 47.882943], + [-122.493869, 47.587189], + [-122.422669, 47.318818], + [-122.324084, 47.346203], + [-122.422669, 47.576235], + [-122.395284, 47.800789], + [-122.230976, 48.030821], + [-122.362422, 48.123929], + [-122.373376, 48.288237], + [-122.471961, 48.468976], + [-122.422669, 48.600422], + [-122.488392, 48.753777], + [-122.647223, 48.775685], + [-122.795101, 48.8907], + [-122.756762, 49.000239], + [-117.033359, 49.000239], + ], + ], + [ + [ + [-122.718423, 48.310145], + [-122.586977, 48.35396], + [-122.608885, 48.151313], + [-122.767716, 48.227991], + [-122.718423, 48.310145], + ], + ], + [ + [ + [-123.025132, 48.583992], + [-122.915593, 48.715438], + [-122.767716, 48.556607], + [-122.811531, 48.419683], + [-123.041563, 48.458022], + [-123.025132, 48.583992], + ], + ], + ], + }, + }, + { + type: "Feature", + id: "54", + properties: { name: "West Virginia", density: 77.06 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-80.518598, 40.636951], + [-80.518598, 39.722302], + [-79.477979, 39.722302], + [-79.488933, 39.20747], + [-79.291763, 39.300578], + [-79.094593, 39.470363], + [-78.963147, 39.437501], + [-78.765977, 39.585379], + [-78.470222, 39.514178], + [-78.431884, 39.623717], + [-78.267575, 39.61824], + [-78.174467, 39.694917], + [-78.004682, 39.601809], + [-77.834897, 39.601809], + [-77.719881, 39.322485], + [-77.82942, 39.130793], + [-78.349729, 39.464886], + [-78.404499, 39.169131], + [-78.870039, 38.763838], + [-78.996008, 38.851469], + [-79.209609, 38.495467], + [-79.313671, 38.413313], + [-79.477979, 38.457129], + [-79.647764, 38.594052], + [-79.724442, 38.364021], + [-79.921611, 38.177805], + [-79.998289, 37.997066], + [-80.184505, 37.849189], + [-80.294043, 37.690357], + [-80.29952, 37.509618], + [-80.474782, 37.421987], + [-80.513121, 37.482234], + [-80.967707, 37.290541], + [-81.225123, 37.235771], + [-81.362047, 37.339833], + [-81.55374, 37.208387], + [-81.679709, 37.20291], + [-81.849494, 37.285064], + [-81.986418, 37.454849], + [-81.969987, 37.537003], + [-82.101434, 37.553434], + [-82.293127, 37.668449], + [-82.342419, 37.783465], + [-82.50125, 37.931343], + [-82.621743, 38.123036], + [-82.594358, 38.424267], + [-82.331465, 38.446175], + [-82.293127, 38.577622], + [-82.172634, 38.632391], + [-82.221926, 38.785745], + [-82.03571, 39.026731], + [-81.887833, 38.873376], + [-81.783771, 38.966484], + [-81.811156, 39.0815], + [-81.685186, 39.273193], + [-81.57017, 39.267716], + [-81.455155, 39.410117], + [-81.345616, 39.344393], + [-81.219646, 39.388209], + [-80.830783, 39.711348], + [-80.737675, 40.078303], + [-80.600752, 40.319289], + [-80.595275, 40.472643], + [-80.666475, 40.582182], + [-80.518598, 40.636951], + ], + ], + }, + }, + { + type: "Feature", + id: "55", + properties: { name: "Wisconsin", density: 105.2 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-90.415429, 46.568478], + [-90.229213, 46.508231], + [-90.119674, 46.338446], + [-89.09001, 46.135799], + [-88.662808, 45.987922], + [-88.531362, 46.020784], + [-88.10416, 45.922199], + [-87.989145, 45.796229], + [-87.781021, 45.675736], + [-87.791975, 45.500474], + [-87.885083, 45.363551], + [-87.649574, 45.341643], + [-87.742682, 45.199243], + [-87.589328, 45.095181], + [-87.627666, 44.974688], + [-87.819359, 44.95278], + [-87.983668, 44.722749], + [-88.043914, 44.563917], + [-87.928898, 44.536533], + [-87.775544, 44.640595], + [-87.611236, 44.837764], + [-87.403112, 44.914442], + [-87.238804, 45.166381], + [-87.03068, 45.22115], + [-87.047111, 45.089704], + [-87.189511, 44.969211], + [-87.468835, 44.552964], + [-87.545512, 44.322932], + [-87.540035, 44.158624], + [-87.644097, 44.103854], + [-87.737205, 43.8793], + [-87.704344, 43.687607], + [-87.791975, 43.561637], + [-87.912467, 43.249452], + [-87.885083, 43.002989], + [-87.76459, 42.783912], + [-87.802929, 42.493634], + [-88.788778, 42.493634], + [-90.639984, 42.510065], + [-90.711184, 42.636034], + [-91.067185, 42.75105], + [-91.143862, 42.909881], + [-91.176724, 43.134436], + [-91.056231, 43.254929], + [-91.204109, 43.353514], + [-91.215062, 43.501391], + [-91.269832, 43.616407], + [-91.242447, 43.775238], + [-91.43414, 43.994316], + [-91.592971, 44.032654], + [-91.877772, 44.202439], + [-91.927065, 44.333886], + [-92.233773, 44.443425], + [-92.337835, 44.552964], + [-92.545959, 44.569394], + [-92.808852, 44.750133], + [-92.737652, 45.117088], + [-92.75956, 45.286874], + [-92.644544, 45.440228], + [-92.770513, 45.566198], + [-92.885529, 45.577151], + [-92.869098, 45.719552], + [-92.639067, 45.933153], + [-92.354266, 46.015307], + [-92.29402, 46.075553], + [-92.29402, 46.667063], + [-92.091373, 46.749217], + [-92.014696, 46.705401], + [-91.790141, 46.694447], + [-91.09457, 46.864232], + [-90.837154, 46.95734], + [-90.749522, 46.88614], + [-90.886446, 46.754694], + [-90.55783, 46.584908], + [-90.415429, 46.568478], + ], + ], + }, + }, + { + type: "Feature", + id: "56", + properties: { name: "Wyoming", density: 5.851 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-109.080842, 45.002073], + [-105.91517, 45.002073], + [-104.058488, 44.996596], + [-104.053011, 43.002989], + [-104.053011, 41.003906], + [-105.728954, 40.998429], + [-107.919731, 41.003906], + [-109.04798, 40.998429], + [-111.047063, 40.998429], + [-111.047063, 42.000709], + [-111.047063, 44.476286], + [-111.05254, 45.002073], + [-109.080842, 45.002073], + ], + ], + }, + }, + { + type: "Feature", + id: "72", + properties: { name: "Puerto Rico", density: 1082 }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [-66.448338, 17.984326], + [-66.771478, 18.006234], + [-66.924832, 17.929556], + [-66.985078, 17.973372], + [-67.209633, 17.956941], + [-67.154863, 18.19245], + [-67.269879, 18.362235], + [-67.094617, 18.515589], + [-66.957694, 18.488204], + [-66.409999, 18.488204], + [-65.840398, 18.433435], + [-65.632274, 18.367712], + [-65.626797, 18.203403], + [-65.730859, 18.186973], + [-65.834921, 18.017187], + [-66.234737, 17.929556], + [-66.448338, 17.984326], + ], + ], + }, + }, + ], +}; diff --git a/spbu/index.php b/spbu/index.php new file mode 100644 index 0000000..0038805 --- /dev/null +++ b/spbu/index.php @@ -0,0 +1,750 @@ +query("INSERT INTO spbu (nama_spbu, nomor_wa, buka_24_jam, latitude, longitude) + VALUES ('$nama','$wa','$buka','$lat','$lng')"); + exit("success"); +} + +// HANDLE DELETE +if(isset($_POST['delete_id'])){ + $id = intval($_POST['delete_id']); + $conn->query("DELETE FROM spbu WHERE id = $id"); + exit("deleted"); +} + +// HANDLE MOVE (update lat/lng) +if(isset($_POST['move_id'])){ + $id = intval($_POST['move_id']); + $lat = $_POST['move_lat']; + $lng = $_POST['move_lng']; + $conn->query("UPDATE spbu SET latitude='$lat', longitude='$lng' WHERE id=$id"); + exit("moved"); +} + +// HANDLE GET DATA +if(isset($_GET['get'])){ + $result = $conn->query("SELECT * FROM spbu"); + $data = []; + while($row = $result->fetch_assoc()){ + $data[] = $row; + } + echo json_encode($data); + exit; +} +?> + + + + + + +SPBU Map — Pontianak + + + + + + + + + + + +
+ + + +
+

Keterangan

+
Buka 24 Jam
+
Tidak 24 Jam
+
+ +
+
+ Klik peta untuk tambah SPBU +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/spbu/spbu.sql b/spbu/spbu.sql new file mode 100644 index 0000000..ca53d47 --- /dev/null +++ b/spbu/spbu.sql @@ -0,0 +1,21 @@ + +CREATE DATABASE IF NOT EXISTS spbu + CHARACTER SET utf8mb4 + COLLATE utf8mb4_unicode_ci; + +USE spbu; + +CREATE TABLE IF NOT EXISTS spbu ( + id INT(11) NOT NULL AUTO_INCREMENT, + nama_spbu VARCHAR(255) NOT NULL, + nomor_wa VARCHAR(20) NOT NULL, + buka_24_jam TINYINT(1) NOT NULL DEFAULT 0, + latitude DECIMAL(10,7) NOT NULL, + longitude DECIMAL(10,7) NOT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Data contoh +INSERT INTO spbu (nama_spbu, nomor_wa, buka_24_jam, latitude, longitude) VALUES + ('SPBU Pertamina Sungai Raya', '6281234567890', 1, -0.0553800, 109.3494700), + ('SPBU Pertamina Ahmad Yani', '6289876543210', 0, -0.0621000, 109.3420000); diff --git a/webgis-poverty-pontianak.zip b/webgis-poverty-pontianak.zip new file mode 100644 index 0000000000000000000000000000000000000000..83ce69f2dae7942d41a95733a803527573ba2581 GIT binary patch literal 68238 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�nEfSy zO-h74KukF0w94{(P!xO9iEKjilXmfJQEaDRf0@VoBh1#M7;&_I&79M*m5&0oUMY7> ztV_Z|xk*2uVhI8V>%8%4UJL6l{&O7Mn(&%rVF8U~#h}z=K>+R{6ploJpimH~))VXP z7KuF93MNzIKA?&r`b&3D7#{Mym%T*NIYQ#sL($#q!pB$70Z0xEcculX`-T9{1e1^2 z29Rv8!ENH?G(`1IcP{QBjDE=+BZvCr;x^kNAhHE!NUj=RxStDK-zw#B(z42iv`9rA zH{Ldrp`_FmSbm-~5pS%G1dOP7o-G7pTc|r`0?KBHW!zv0$MDwj{cj&;Rh1n<8||t^ zUj=kf_%?zU2Y8&%#(dEi`{bxaS=I+2@?CDYx!+LH&FYmS};tvB4HM zzUbRX#*8_X&b2U!*Qzl!)HHlOI++|S)5J&xT;o}Q{q}`snYZQdl>iWdaCE-YCIQjR zjqpkyq%kM4)8w3+$5IbjAdHe{IN;4WAonnDLy{uI04Q%T3GwX2D>o`^BL)WOd*C-d zjMDqSW$@;;wuF?@mV`yS{3b8(e_tLNY9ViANn(fzHi8t>Mw&C2#+yw3Z$5}+UKSCg zW1R!Z7`LCo#@X_ijphXqNw3hTt*e|eJBkv;-cE^@mdW0?GKseDGND*KL6rS&KlcA; z1EkldGF)EIcwc|5iObz`W;*BE!e!h^sNE+R5YaS7V)sF%sH!QYD%V56niH6wq%#jE z(K%l|hZP_UisBBk)`oDZ`y^V<3UwK=z~fZG0O9N8I}RvK^vs?D7BeTP;`mt^Qzo#| zH~#h}(7gOnPh8qkF>668t~T0tQ<32NjRdABPSOQDw0W=QYH?$=Z0Cp(GqEc4(e(lh zdw>lY%$Pu@cVCQ^5jX8=&26;0L5XKA&C?0o{LInkocDo-FV#f&{ZRMwA?R54w8`8|bxff|^$b;Ooyqp6gIgJW;28vaC-HZ$*EjCXD^A2DCmEvrw&gKrq zS5ArpSi_sBIeQz1cUj&M3Ko2ookULPpYTw79w86*b?E`P;(f_~>28Af=b6**gUyG5;c z=UJ?g;6MIW=KHHp%S~BWtW6>&F(^mTEe8CrGn-=BiPiLh#k1Z0gkX7pz!Z0ja(wI7 z*~f<|@nKgI86o%r@pYMy`W>Wv(V=gz-y7scKiZ?L0W)FNXIWn@JVP(+nzG3S>x2bq zsc48tpjMpe2*0<=Ih&^MS*){7bSR2^4GfBagG4{=` zR{UBP&L1Yv{h@uR{S$D-eQa7N`5+)3vt<)oN$v{%Tl-1@J*ZXlI8m8*`mK@Pwb%=sEYC`?SuL-Q=i*H}w|M zA?(rdQfMi86>IeTYG&58?MJF!fCe})o-W6}nuS&obIkH$Zb>}#KT;^Y>tIhmAbO?X zxIs8(Aq-mmMk@4a$l15hTM}mY!C8y%Pb5bhp8$pERbQpDj(bQq9mIot?OcL;tFghC za;0ckP%Ja%kD$WfP!izWYvunarR< z3AI$T0~=!%$iZD3DL&10Qzbj%(wXY^es8S_P(sw&IRtfGn;vynXI0^R%QnUCt*;u~ zQfA+iY_P&XSY~Ytn!<&FCGg0YRIR?`2p2+TemthOZP(l;4>vi~d)^o)Q9sKn>?P^& zJ*a24z=c(RJhw7q_$P8YC>To`GC*4OZzzXBpUIG#=RYWti&%ChKb$_>TDyJ3g>hex z&-at&7MrXYTjD{}GH+?n4bOF6S=5$WdG6)&z6EnY@BdFth2EKb<&eEK9X1DqiisWWv5o>yAu1 zs}fy}cVqh(9(}t<6Iu+j?3?1ao#&J#>3EKX#Q$;&IdA4Zh+lw}j!T5d@_a6LCO?EV zv4*pH1WA9&2u26Eyk?&O`YS0Z7Qfw4IiVD%T}$dNuiRhA(v+*T$Cd8ak8G`5WwrmX zYt)RciD9>JBR_tZE|^Pu>q89xMqOf;rDs^D0Vm1I6sTL5T5K*6iXy z>M|{0yA;w6;f|R>*+LO1-fEV}h1-txQ})~$D^9X4mF#2pe9B9gJ+4*}-0FY-AipJ^ z9+I&>zf`r{psEC-KQH5)(w1si6Y#76+ERq^D>YHYY|~;-+MzI|tnRhi3Xo!E704rg zw${MC(E{CZ5iw=JI76KND`wD)R>eJiz2mAr6U;b@Qp>8&wqb~#mGf!DZreZ^r--Yy z1Yx)FNvmSl?1$I7FpZ6zw?+VTd!u9Z4+s3pT0ohrpv4N(vdN#svG&n^Pj>Ufh4F>Y zehocy+I25xYXo6S{tuZM;k->BajL9cx3tor_a^Nu+xS79Y`3sub^FNy6p@Ai9#R6{ z)-oGY3J@Ih$$62Fs4m8!7p?l9lJq)0PT@(%oI;wwNURC7TK4f?7rk}WNn+Yk-~gbn zYULu;^Hot|CF6K?Iv08l?J*jM%h!9KdIUzbGRKk`XM_2u<4YNC;BptAVKpWcouYOs zzFPjFeZhBagJXzQTJg$jf{Nv>R%NK$eKnp6e0c?u1%yrzcc z(bB@E-g%GD6*KLxAeW_kx@J-K1bsrC*{{l?F-<<=13aIy#rOR^tmvdYwcPXy3~Tb} zP2qwJDnI3MkL@|~q#pn8Py23x<>{U8HP^O>u6kIPwg<5*pL>i2u4qIvHrafOhk7<| zV5wm`Kk>@d+<*N&#q;}4`TfSRQ3m9xLy#Bp|wM$CN{jV=t z*IT>ip4D_B?d`3dpT0l6P9tuQS094^@<2FS-ihFQ{El_XtO)L@bni#=)G`Cf`65x@ zY|3Sp`M(;EawZeYHn}sJa>92R^7=%h&K*4!jyHd6>fMX0e(X0{z&Ua%p#B*a1dr?W z|7x;&x!&yL-0sRVRyv+bvUf#Nd{kRSa#@h0`-7YUH+#^I7aj+(f7K=jNnJxnT1i+7r(gq?Uy85^2# za0)NtIS8s>FID#Zh@x=^j?;CL)4Ze31->VX#*}=sbK|M_kBl~1&^cm(dPQ&@4bIh@ zQQHjmHpti%SYBGpKw1m-`gKWhZ7c04{udlK8b)$ql2Ua7+kusUJtoTdmu`N)`m`kK zA5zR));Ok3Ucrc$j)ph#GrF*-OBe6(D6v(B9rjH-K-}M-8*uiE1HG6vt+0V%*bSSP zhnPj`nCK}tTo4SUd^Fg%Oy_Q)Y{WaDn!iJ8;ku%MGwJI3O z?O-=PT|=)e^`N@?0(1W-UU7L^)U3SR(#8UJX0j$1-&s9cd;YG3G2eudu(7e`nk9 z)qGJW(eKxDw9Y%c>;;-`T`KGquy_^I>u0(u>{~sr7F%DE;oafA6%HT2m{A89><6@) z8Ei+qfiU$TJj$G``rc`scb#yrsz5jEps_)`-0bYQW1Vv_FFIPgU=x{aPk^Xp$_cef&8(r| z18J}vrSDUqr|;TmLiHr1Jabas{xbT>NVw7p&0n zjp1Jps2*{xK%m-%W1h_6bVj(?0NcsGSAXdfCqAP%Lqt#iMurGw87*4J(`Tmuhs!X2 zs0@UNA9i^%64icAQz+EqPznflm_2wyl6*ZHL1xGVyNV_4x@kTAU&qjFi?K z!)EB!v72h%W04m$L#WGOVYR=0+@ozgh|Dq0B98#gtc;xi=0$^kRimsFqckeT^PNL; zVs6j4#x6wgrcvxeVzQrwp(i9Ozs}5}@4A03ke+4dPGGP;IECA(R}Zv$+60MmrS-H^{if12pm6b zG$Dy|<4H3vKss7m{J`5vLp~53;5F^F7NTolr)2p?b)FySry+5>@?q+mRD7LT=+ne* zvE4q%8>KtMY$or-!59n+SRyFSP{ITx1?U2tGunA1Q^NG#ACuqCA{E3XA{$G(w1?WR zpo0uRLS(w1dOEecyItF!)6*L*AH;LaE+c_l$b!&izwD`-P+6Nmm$YB0>J%AdBAB}O$v4h1zw@b=?#X|K`}i_ccd7hji1`?q@_xBi2dI=H zci4K3=)csih(au(NG5kvK9UGSh^au|2Z9MBUYG%Wr&TIT3k>b3syJaCgK7#4)!B@x zA*@bQAq){@1@iKDT%Jmrt14nPVaQ82#4*@rx5o8r2H}|4=-om0_=nbZ7<9$ong;mr z7=18%;?pmcn|c>}IAXxG*%R-*2O)M6a5|Y!4mZvw^4PqO`p5wWXvgi{`BdMb`hG)u zyij*f-LMYWugWkfSeV&dO7<%8NKrPj}9epw7B{$4d(Lp?j$3U%d(#2^X&Ahu((6)z% z)+foUswZN{G{g+P{yMPhOV_@Po`~4k|Ndi$u)j%bc@ldQ|K@o}ZW(4t1BVdD$3$fO zEYc%2+^45jMDwSlsb7>k5~2Xhvd2M9(<;68_m!f_E!A!h_cqSYKOVRgj%@H8(<+MB z`JSYQ;MRHvef_|-5uV!q;Z;f6% z@zRCYNAbyp>Lnir(ajJuSQf+C&w!HL5ECd5qZNk1l6hg+a{2}mFRw@ZQihS6*(H!x zn%?k=&rE{&%xK4;^vE3A2-bcAJbu$bb1rZ5Ce-D-bXj>ni?Vh;#M+M>!*9>OlD-J? zzA)h58fD5E`A1ls$%O~M^mx$DANbCJl_5Sck4sWeb*j&cX@?`6mo$FgqPP#sGS5xN zi_Vc-X_bJ@YNIiVxq#@PXCw`P|5@l;l0BqcI6{(BA5%#TD19zEfuOn-{35kFx=`OjHkJBxluiTt@{vY2B}Ps zG+Q+pNCk2zzwwwlmzlSFHxIZXH6?BYryNjZR@H|-&~S47fluOb4suyc)Bf|M zllGcnqwuh>Zr%KW_i0$aGxPx35CmiKd0_NnDVHNV z`2ki$2Q$Aj0Vn4Z<4{;xJI(?7$Esry#+K2O<>>5)VA}*=>B$t}aan+uKs1=obXQ;; z7LnSCwV@s*9X>=jOkAqDFPo_3&nJa~@Q^?6zhqWTQ)<8$wMezt7PPuEiC~&I1dFn( z--RMg0q#pRo!bAMMhb^lUMj?JTNhw!g!Wv^%TfTIxD2|`*g~NAX>8;Ha4LZ_9%AZ6 zeP-D4A(!6KhHk>c=D4M$#^?T}YLd^T{;TljTp%~1@vJsw@Lb^6wS3rx%`I`>?ZU%- zW{+pP*Ca%B$?mT393Iu?DBR`#Gq}*5rxCW*4mgfH9)S5(9IOSy3f}TSdF$UU|ylL-jAc`L!xSAogsW3I5xqJD6pJpwe+x zVu3D9SwSs8!Z)uX$P#_(x4cBQL>?nwN-#GjoFX(d46-k3e%cq*C$(ju4Hj-muZTL9 z4z_H9-SE4jcw)w?xGPgS*1JxIt)>oOO=?XH?!;sSbIMfJz6);f^FyU2zvtF0$k;TW z%{f2&!{ly)&o(l%y2Mm+ba8KY9HoXZUmRPdlFs6?=yN))YcWzWC8(5V`?7wj=bg-3 z|0K1|kywr1>5&{7!qxxS)$`NwwD4GFe6}Q!`5M&q%RTp{C)>mR3n4SUOWM9xlwupMu&-leRB`r}@rGgXbkG;C<0htksUobbHl1ebaxKH~{!xF}roIi`d? zchB+JAaC2oW{$0EuicWV47DcmG?;OLx0+t>zybLDd~9zi-fR<|7i6z&O&(B{^51lc zzD&XC+Q0Larukf(3ex1=c&q8jrry3;(F_7oQ$csCFk4XZsA}5p3%8y*tDi!BFGftI z%I)L+?ydJjws;v@_@l8xq;O(MX=}#GH=bY$y|Ow*T@*M`6ugG6k8Hi9gzm0=OYK1Cq0{Zn}GKr{v@R`c^Xc zaG_=ifq?u{{*!No`oFUk*c&_j7nbK1?F$FocJ%MMGNT-Eix3%8OIPcaM*SfL_Z59! zXp@`54I-&>Y?=Ki9EET^+9=JRb${^pUaLR>i4Pv%z#fqqVs6b?27_XVYS@#_nY}%a z@-JT(0@vY+-6$Fb16Fz7kB>uM>V=5EYN$MA`w3lFgkX?{0=|o+h=@Hf1pMFkW4!yl zX${A0r3(&}DGl>x5~wb63?QB_{GNBe57T^-T-+g2D!{l&Y0yX~8~_>Lflci@Bv=9h z=LkGjBh254w$j3{vK4O;;cBkf8<4r&@ub{{i(=FCQ_R@r&Jk$eG1TIJt0f;vjBoo? zwXp_pR?*BWl0^vkxw%f0HV^^@FF^ltdb-Hs4HDmdKfDNn;>xOK?zj1Wg7@5clHE<@ ze}C=xf1&rxSmQi+#>o1AP%>SR+StG$zF3R!@j{4MZ9=H4q z(~sD`7067Q&VF1y9f6||R)mZU-4fnt6Tq!)k72e^{BlhE!GC)@A>o)P@;&5c&Jj9h zNoMq?8Zg6$vr4Mx;>mVGev=Shd4pkhowAg(Sbym}d>uNf*;@h+S7ZxvQs7Ft}2 z|K+=^mS?|?dU#d)Yw&N;P3hJNCJb!}jyAFMUFCM}gXI zRd#h1S)SVqyrO-c+7u^^2Q%VD+-?taixEV8%WQv>$2ha8d_{_-zMy6EG{hioN?qUq@dKqPD zd5l>mO)6sTR_*Z~Y4bFyq+yHp z1vxOe6I^w%S2wpbSXtia#xrtFRf3&B=gGsHl+D<|1}cdKCl>Q;AY5{@cB9Jppe65ZmH+4QW?fTyB_ zXX9wd5zB_&2BsXp&kF!X%hrFs;o-hSkTS*JGGBSUXE44W5i8_(s6NpujobI#nD1lk zt@yM#g`O!1%xO1MQF_=9Ia?e9wI(xLzr8L-c2f1 z6_c)dOr3?0E~WUc=?`<-?-I_Bbi;wcnBul;YqU(?QgxN$P^aU)+HqMo=NE4muZ=WH zuWCu08g>F3jmtO}*p@Yd#Q}T2C3=%05Reu?0FZ#2EPp8G3*aXpkDk(gL+kmyV&z@u z>ODj#KzmA2IQ2yq`67Aj*I2W+myl-m1Y`+KXh!!3T1{DW_Ro=I_U*M+Jb-S|^4%?~ zglkulT{AN#@+|{puOuNDml~f{EJ7_S@jz*++(v9##?+h){?Qj+g_}8WH^sriCNkpt z_n%{ifddGDHQQoF>JQtD8@tQT+mPmt$uV2_Of*<8(c&ol1p)zLF>Rb1{V3Xr>A{&> z#;QX`gntRUqVf|6JmH0zK@6lYVqCq%fV%EVM*cYxH6sT4xBy?myj#5)zq&z)X;U9bmG3MmocSp*r#MrQOmGr!U&Kf zhqsF^#ARmg!`C`8vDR@Fp)X~HbW)E|teSs?gVfg$D#aFZk}p~js#3BMG*#x(aiZOF z$qQQ{DQIz-BZEQZf?{J-vMI}9f`o&)XBmo`=5E+E#ohZ-fg>@tS!*9iN*a;14b^i$p zy&tbk8CYtA7z?HXSXF(}h#8hpf%h#lZ4`<)PSxr`YD*G}Gr)L`xiY3JZ67R>zOrLF z9cmna!>iE+^zl~=!G3^;RV)it6S8VDrzQ{ULwD!^JraNkBP)S=*6j)*w8-T{?|B2i z?zEX8;3u#6S~_SqVCVHkTAY;2h&ocIZY6y3d-G|#MR;GVRVDH0%2aQg!I#cL|7AJ4 z2}gSei`8}ZaZc*sp^*%6f#*T1ey^IS@~woH({Q@{k*=%gExk?yZB?;#5>fI{wHlvX z7RPu%woLT>vsYdMRHM0w@+vWlzYRXklB@Vyg>u_M1U9H6VJQv2YR* zHU?ON0Zk~um=Xs1@)uiMIP&KAc2pbe{mTy>(FevJNVgYu`6WMP335)>s~3{#C}NC3 z9yP@xgGE3k_6HR_%2|T;-IRmTZ6y{sUHDuU43CHYT`2gU`ht(#RSK+x&kPMJ*)#|) zvH30C0xY|vVz*IAi_E0dkcu-lVI=>)x#gYMZ|>XzT}PTX-Flt)ubpuAR{2G2g6Su_ zR{hr0fqvwuXtOzy%0}D6(4hR($5pO;r8d)Y|Cv}pzjS7%JD{heYy$2tzdZutN``wr zq4IbR7kloaat*Y|30A4i4S&x^&CO@nigwX)$bs4}I@RI+GYLhMPB*Q$@S+bOVbMeC zmk6l!90CAqXK1XN4r;&=l1+zT8FAjhMff^8R`7vXI;4@ty>K{$CZr;ls?^=`d%%Y1 zoO(+61to%XGLpgywbr*=qDerrDns!c&u$3k2Q(B3@!MX4W2vbJ`for`d{*tpjn}Mo z001yAvIWi}FjL9v@x>OypMP{u%OR1B4n0ouvTaW7q$rEsd97lxn?0+|&VP}Zjiz>s zS8cmV z*L=pRzsbhjar||ae_U25KZh36@eJ(1 za&wug;R`vLwRCwHe024Xf05Re7we^SK% znFag*5|5pX9n9_i3r)PmC+|wymg?~Z6QR*Q*0}mO`J02mhAjPf5PM20vm!AmdV(Ef zjR?A7ZR-rt`VUN%&lo-R%CZB4bY;$AV<-2e+si+5t=3P7FXAa8P^?2zQGm5C7NPCd2Me?&vl2 zDZ`$Rg`Fjjx<)R4Qi$&}#PbQmJ8XJ`!HM3V^!I!4hd?$VL{CJ<-mjU@qjMpj&D%a$ zM?FyUr;GkLiJ*s+(rTTC85NO0ofSEihXk<98(h=8_aMPY>2k4q@x~)%93-sk&;vN$ zPSv#I0|I)*u3A%f_ur8600n@(snV);_)+jA8VPAWhL(&azDx`YMPws^%u+k_D7d2V zFHSHL9!_B%jDcJ`26%X01)P5dp%PTwj%)H}qOQFKlKs+Ry`sBnIE(-+Yli9b}z=lpG?s3|A$DW7PRn zQS}6u3%33W(S};n%LTH2@juMEAuH7vAx!eZ#urRz?%dayzxtgDq2)(Ip8vAC$FE9x`@OjD8(A12R?9;N5)RAiA2HBCi9#4!$+uryZDla%YbBI z(L@XF7f(clCJ$75$sxhgEjOIxh7zEHxxyGJ)HM{zFmLr>>s4U%C{)T4;|3D2@xn6s z0(b6kIk}#Rt>I~-h3G{sr~+hxQy6C<2stKKy45H@U_#aQy;s*d(SNFW3=N-uO=$*Q zsk3ItGCHYPjf2DwyK(DXoi+ksUgH@c=Vz?ZgDF}z$)Lr5@+Gib&W}?f*2pZzF12)< z^kXw+&JN<)RiLX*i{jybX=qpdqETXE8?c?@T>&p5ZwIQ?`4t3%hFwQe)=9{KD1^=5 z$;B&9dOv%xA~t(ePg*gBq1)0d;DYB4%I-DsM|>|EW}fpmVP6R>YpX4zo}Qa;w`K5e*sc{Z5n#12Co9GmHAJL`i#z&}T}=ar{t zcv21_F0>Dxu=y1ENq2_Fk9SMzB8*v-B;bYzff89Hs~?Ahe}y9hkjuK_W>R$xiJ~lP zuTadz@_M64|Gm(ET64#@a?|DV8b?h*t!p&1om@&2S3Ou#It ziXI~AnQTf72>sodo`I=NX`E&7VlGk-(8_7-28}8e8r~e!6 zTIbVd#&14Z4YRq{^$Z7PB!#^d(dq7nZi7K1HnzW)X)qf?fGu&Y}qGG{_oUKI$8-!%lh$8Ls{^zL6m z0D_}`$t)}wtzTUwdkcc1eAJGLg(zbzHPXtxK=v;$n8}1v;RNoz{Ys2wu{zAw;0meN}i4()B z?yDY~!rV=$@mM0H*sVZLzz8@E((pXJs2I~#8k5LTBQE4wL z)YD$#l)QtZO+c2N*n<-^;(g!Cq38+`#VDO`axKv5DG+^lTK;>1QYRi%6VnL&>>a7Z zFB&x>2Tt3SrIWTey~Tl4YL5o%P${r0>Wd+Y_d*`7l@bvvB|#D=&!uI?+S;VroE`$iW@r#av2y)A(2e~4!Q3ANIjgkUHb0+;eJN)Mo z^%bg=zgic@@|NT>jsI23yaj1z5Gd>|&`(fcoWB4}mPLpz~czo@GfJmrQM%xwB2b!@^xraarn3 zK4Z1oH&M&UhLr8^(N?~{ECbnZ49SZyVz=;o-}f`%O4~_sFzARClL+<~&_QfaNV}Wm z#%1-rD18S!jHzpE+NC}l=_U-SBDilEw+F2K>e@C&u-Y;f5A*uULl@qnYsazj4_(&t zp8j&d?<4>34_%kQS6`#JOj$odzb(!;b>ME$wxJ%*)e@$fm~Fe5G%}Sn$UP(Uok^?u zVlyz{sTiX)Q>MXB-IAkpwv6>0YAo~f$8lkA>^l0o&j4ft{^@2w7}e=DoT5TdQ;8fg z+OqV6IopWe9G_ep=6ZR-re})_nh)QzGU~~th+?Y@ij3@rWE33zm2ui~p`DOrR(`C@ zNj-I$@#Ibnm1j-8@=)V6)oa~x7G8U@4YvTa!sk_ZeQGJ(XAoW%kQqEnIBq}g8@7=5 zFa{}x_b+K$Blae8mN#75oT;SOLQQ8M36)1NxqX+qbM@~ghMk=(1Fifs|9rY1#iYF- z>c)?>oZFHL6x+$H5bKCYYuJ1~Ov9c;afVs;x0kogLtW?t)ZNT+l4lICrHj9N@`72y zWyPvm1)sk*km6hM6R2a0ONe1{6pd#}joCi&dJWB`$0;YiwZZ~KK?(&ed~w2e4}**w z%^K93?G>uS>|LpeCDk${&mXLr@D3_=UI8^Zvq`}u!%32UTzP~@O9+BMyl~#DhzEO; zhy;8A)IDHi=CJ}hS5vM*iBW5Z^~vIXQr%_&@8+HV1^=#o0LI#GbdBkcSiUX}a(;g9H1pKstJQJ{|>BD@ZP zf3X2*XIby38ZC2a9jDv&*U&XQl3H?BR3Hxe&|gOCvuQA=FFRiky}cjDFSmDu_Xj&- zH4ikpufLv;qjr>(QLcDtgA8>pvIm%LDs7jubT10hn4iU^R9nLgQ@cTR>7Nf_F@&9j z444E#_e$OrQg7^vQ|ne9mRMA;N0K)0>~h8*J#ILzT>FLY^={>|=f*cXsIyY@C84Gk+{*Hrv{xM+mme?N8x3Y?6FJv z3rg0!V&kq!TgoyY2~`&y1y}(`t#j(7Rg2nJ{EM$_^^c`uchSr*$%;o=K0B&v_hpj8 zh(3I25V`sEOk1nIM%ZLD5;f1Z={D&iF2$OY%8@Ys?x%& z6LaL>6M><434TV#$t*%sMXIhp_md(|-F!{Aqy+Lvl(qSxdp=UfTI8tYjUfXN21bF( zH4GY-^~Rg1dGkg*Wyr{pW!%a9*1HDehgqs50|jl=Lr>UVFH^lTPJFv$g|6dAX08Me zxhBp;<}KN*`W6J-j^)7wS*c3NA@WbEUqXTcx*Bryl;Bt5Dz;Zn$+Sj7SCVTvChTU) zDf~w|*)$AqYFt2?G>WO!j2CNRZrG&*pGGvSCQEHb>vZP4q1EW~jc34E!&V7}Snb3y zpBR>0sRy^#oqgIgEOT3bU~m+oqtkIg8uYqD(hE0RxREXmf}ItPz;oT0?)_TsSZcf& z6zZE})4vpC_@g2*MYf6ft75WTCN!ykG$e#O=~T@2pCg%&qq?w_qT^Dz(BYV5F48MK z0SarK;o^R&S}$PX`Okc9ITCh7?H5+4d@(tn2&tSpfH^= zU+4a1*B(L*oLmqSr9c1GqI0sTFq?auV3OOhO^U=S7g<^?)2nZPyNhk@$m?0{$UFlqQZhWc3o#e{wtw%c3D$YV_H`BxoEnac0~ly=r}Q9s}Qr@N)4 zQ(BM)k?!v9MnZO%6a?vR>26j)I;BGz=@5`^P*VE0-g`ga2Y&C@x<7a<@z49Y=QU@} z%$%8>vr1+x!qU9yZfo68FdvNn-bmk#S^d?=N!#&>3#RE-WFs$A_IXMA7oihoaNHq? zAeSrY!KqS)FdPu| zm?dcVrlq$~Fdz_qYiJfLpRcD}PI5K-L0e1s#Y}~vNYT5thr08m$B)P$rwxtSlYL6j zfdsH~O1K13jEG2+sNLK15p3^}2km+;n6rnF$g(PrO7M=6L@ar|& z2^r!UPdt{4k{C#!pYvCL!#rK}On6&{yu+Hco6GUlD(KC_S5$>d9TTb1xXAj5+Y+-i zFa-_fO|%+5#@*Y-+fTp*x?kT#j7W~67;!wChv(9?_Ldk&4Gx$JIHc`*DY5m{92w41 za2Wxq6Gxzc_Du?|J^Rjc1!ZB{K~c=JF>vB0L4Oor`3WrS@QOK75pRRor`}Ayw#?nv zrLd;dV`Z?M(^;QR+XY}FG_e^#8=C!uu@AyRtp`euV*uy8DurLK&NunL6e8) zP%N5H!;xn7|v@O-t0nABbd2ec+h?V#-E(Z_1;7&j!GDm!fs);ju+9Eta zY&{9f;IopB?q1JI!l~9Sj+&$hsNY+FRB+L!K_S>=<67;vg>M$B?Bqe%mK^BJX zRc}QWMRG8{%K61CQi#81PFM?1Eg;*JaXK`+V+)}=1bJtPx|8#BvJMlOSJ9BPs^GLP zi?xwY2tI&PUQmCeA%MHgPRxq~zVeCU&>9`S!@Cr{tzP8IFifk*7Ej>%{rZhHC^>DR zP#xHOu3qFWI20_~R(&OmPv%RG;#Bok=2FAqC4Z{lriGR{Maa#6b4!-d&oj9Bk!H z=rM*>Q*athq&7RfF^7nqyXisg^b$Pk$7VQe<$~Zu>@fzUS&k*ey{=>{^UUIN=$)dq zpra){5TaQvifD^n7&&{q8*4@D@`zi9yGq>I9r)6esHDy;7(5)365bRX`dKi-HCiFtO=~ z+4(d>5`9h4;Qn?dapnB&Kl{mnx^YF3C@t>+zsO2vl#Jk9;^-HSvBUB=1CVZ9WvW>Wem3-*n z7rBH*7K>iiFm%%h*B~so&_LiMHJN?(LPW>Yx|8}+AEw)#iYp|tt}x7t%=q#7>yyh$ zW)ZoTXwQWfIQxqmiMr{yVm9JaJ^V`aj;CD3EaAixv(SPF*m@{I$@NZ8yLs27JGW!N zl!1hCh(V4~*NcekZ*E)`4c5Jz4mnyg`6AFeK*r_n{$I7QVTRxc8mf3FhuH&;JwNpf z1|gzRpBQbo%rlG~xTKIrZl!OaBVx|JP%-%?&Vx@wUg}ibSTdsOl|CcL1j02(6L?f~ zu+9luqgr%%#*)}>h7l@t{-&mF9Mof)tq@;myC66Oe!XyTCC_4qOuE27h0WP%S>zxjwq*ofjupIlJ)Q+$!w1Lr`q9USO zm%;`WX^m?c{CQxZJ!)cAk&2~tjI%!A%)`7aI6R@`o5;ae_4Ojt;-Wp2jWp2fOvEc+ z^2$An7CkCPD}fRLgXp)@@x21>TVL;G$zXlxz2tWqw;__J^;BD{`CmK7Mi)Q zjkIak!LpK1E=hviVazJ*s11F#0sX#>f1F4IC9lhyE!^JO(Icm_M&RZQ*{9JEm>gBM z$+&_W!NHiIrbbUIm$5?HB#KX0st?d}#VNiLw(}FLf%R7<@{YU^Re0}9Cu5Bt~Pb_o~zTMZI>x;}m;fx`Fiwf2RcA?%r#$J6K@MQjr; z0btvLV%7}(3y;hKG#|rgk6y)3iO4<@?9#2)jg)Rkw~-3jf|=5k7@&H_E~}ZVl^T1Y zMr9bS=%Xq2C~4C}mdW;om;uZN!a`-hNm*e^h&;ROfV%4e$|RrFK(!rVD4*C09`XZE z#sMI|oHKdVJMcHKFDU!Der*ZB@Oji~NH}T;8@*6hvZkDj3%YfLRPCoc^!&-U_<&wx zn;0=VAE+;ekJP3`Sn;zMc;m~0Qn;xjmHO#YB5B3CO{9s0kY`Bu2X8l@-R_Ujd(E2o zu?uB9Xnis+-Jd&EV$Wiw#rT-X89#};bCwHvp-VyY!^uKmL+dq2Z-X;7(c}P9em-q^ z#(wm5d}s3#ck|6aX6-slXH~}gORNqbKRUNi)Ucg&)WBsyFO~A|pG@*adIrGJGB8zn zsm0sninSYr^))C=0%xUk?c2y*Ln#TZ%089gwx6$$gdr%FJb!Yy*}O^NEzikLu08Tn z2+fq!{9bk-6?L$*mwq*2t1Y3L+)a&sc?7hTuSZQa%jM+g5hn|#u*6eebRMiHaf{Yz5F6zpkz`z@t(7I5`4BxnIuQ!hW*JzS04FTj*3 ziU@77Y+>$DP4tes5!czn8{Smv2ZnUQH@B&*J$o(xOxZ{}d*_7!h1>^wv6wcR;tHjt zWup|ScM#Q^zF|8Kl{^IsDDEB|aOa-Gnmk*)KG8ez?)DAFx=Kxn8f!c#sW#;uB`WHd z1)=6;L=UMDyr+Vzj6!N+MJLca-&as>fg`8DG{=1U9*34GEr3IQX<^_4AU3JW4Tqf( z72sZ31n3rUQkn4FOEF!Ao63Q0K*YxM7w!-CYD7xNUV9K^4OQaQy**;iAsGLO_;wTR z+Ul_iL;cQ?v8tWUYdc*R+ik6I|3X>PIYD*$qCR75QjJ=ZY+93izKDj6DVN?hgnU}^ zhePt*LyUbSkzi-rluLg7{+6Sv=95WbGwxcIC*V0P6-@$BbM1n1{b~DC<+&6>`3A)z zQ@Jt=KqeoUmI%PC-)3KXb7z zCbktDxKtTZLGQ|;4X)#V8*jeuYhxnK?pF7aS7Sv&a>?DrA$G3i8TvNpL+w{iNKG2S5QeoV@NYrd4_UZ%(qs&~;q znNb8Ya~!MptLMH&+e4AkEPbz>rM^uU$>FPgdJ*k`%iMtns4yap- zZ3HjoM;1!xfm&-kN*amqZm>m7$i0kTjAj+NytCUHMM-hjJk?=`Zvmc_s`jnUaW)wE za-QgeCN}9xV^&(!VW9V+yt0~!Bc8t=Hj~erM4mhn;o)SPeY=U?GA$tqixqpo8dN*H z7l;ruNU@8bhu%-T^?5YrO|eKxVb*|-KB5EziqJ}ur5o%V_YtNMHfU6Js@$aaZKO$KZfAnc+xsfx zBP2?OD`e^N5Z&~$co#;?Lg&0GM`|Tb(;8SwJ85eBVKjHY{g54ECSY*cnMXcD4tLr5U<^g z+%a>Urp)dYOuL-|5->HG#>3_MvfWDCM@w{?J+6j(Lh2Bw;_b6N8XY*tmTOWF0nM{@ zx>WOYdyze0YakC6CYRoO=Rv6pmA(>>YsG}ZPS&#k1_JP~UF3R^5Q_<~*D?|bX|uO? zZBa-I%@zU`VvFLTRE zSm0BP2iiD?Sl%dCqPfl#CFef34wBrt-{_JN)vKqlLj$~N!B%>`d)g{-Dlf({?h-9j zL8kpVr&RI8`g-1~)Kl}Z$5eVs74-1iTa8=zuM<&8`o@(|-7jT0r;4)m7Iy<8u2P#@ zOm!C{nLMTShSg7n3Fb652hK7CwKDC@zf_)L8=yV^pgUmWboX8^Afpw8T;X+amEgK& zG9nX3)qQh{&3A-w8q_hK*I50up)X{6DqZ(Ory6|R;C8I$f}|NO&nvU_4MfDCPFs&i zNf(bYaoTffy;#7!(N;;uEUfY|E2S`gy5%$b)RA@DL#l#{%6d}bc3p2g3kni9jSoG87%k>>SD zD-)Cp+dNSAKP^@dxG>$yf*-{a(B}z4dx&J*2|&JEn%H@8%%jc#?#S(a6jUaXgMg2U ziA@Mvc|z`2tc(@H6h_sEj%R0)I>BYDY`o3F|74w$n>n(2iW?YJSkywxGBl2c<+(F^DJzuo#z7LA9c&hz72B6j^q^uD z6q={s1o|SO=94o*?DAaqOR8Q!0F{<#1c-anH&)2$lV72~uQ;!5rqrZ|exOC#LKJ1x z>2pm?$P8n3nq&l1q;NiY?mb<+-A>%OCMH$7^S*3Ofv#ITCHa z+`RD(DZtS5ZeCA&6a60CD^ltKw{DCV^0Nng`jJ{-H{t2VkfR$1*?zAgJ0 zm_4jId%0R-93GyJrTmOKkJ}!$5SdssGjDCHV4LwXlQB+>KWwG-b8iR}Y6q8L*PY9i z?!Ti*5M3-@P&ykfAq)?z7l+Q|{ydS^vl!^Ydxi#5-!cK#mbQWEJQ4VG7a5U@LN zd)9^xb$j6LakPNjxAX0Q?9xF~G7mhfZYXezZ%|3`TA~TRTIw+xMRO}f7CQgnJlr&~ zHF(eE5EbePk7WjiOnS|{u^Vg86Z{8WNuT`+OwIWEJE8Tm`_EfyB@*ma>|bNPsgb2n zyu7q)|LwwY^V;hx7pN(NZ)DiW*$*tLg+FqJXu-*%3g4@ODInp(O~cZSj!>L9T{FBt;pF{jBYWWG8`u4$1v_h=;Cy_YlV`Q zvN5Px$}rrj9>UB%BZ%WctYHGY9p7^IW^J@^#}AIts1b{NoV$l zE+w7`{wQ_4j5+k;+|*RF=fR3swpH1C-A7LKQRHVVHIpp(x*e9_TC4$NV=aMD7e^zG z(QOHRCTl?WGmd>ALlHJ?oQSxwUh1c0uE&aAItPaOx*kZn2Bss(cjC@#jUQP|Ki8`o zOeKIy+h7H`8~qVeBVn$)9b*oyNg8AP*af2rmr1wQNO1!=<1dq))d&-&HEgvDWw?<1 z2E%b_1Wzag^KeuIaNP8U?QDgTCcv>T{n7$oE~C?Io-a`^?N0BYH0qurHI5p$L7lAw z4cfU()dM@#PID_VP|S3!{LoQ^D7$VdvAdL&BI=;`qV_8;iOA|6s|0KjpyR4Sqr%c& zG$r~Q_4;R)%wr*R@LZU1kq&)uP~cZ}1cK{~x1#98G+<70cn^}t)bcjboMmQdoXtsw zh6RX6s3Me%F8iw00TyWmB0FMW1CTmL3nsrEaBXVDsZ$B5pgli2*Q7|A4A{>51EteKmi}0B? z;G{Vn?AT*eMgOU~LvsUnu3-bcYGEa_4y7O_yEUryLa-=lMMPhp#Rg_&ucb zs?4q0pn3o-5*0nvXEVYooX|d>!)5U?mD&oLZFf0LA9-rX>@1sXbW<2bSwpn(5Des(l|_>^SNiH7thiunWc%oj82Brtv(AZ6 zFeT80+_++Aj2yBRVkSBhW+)IOGVWd1E)fDz?+hq_W3z-}GDo7zi$JT=!@l4%rpU8` zvMI~e{F$$B0d^Q-_&0~e>~X-0>JqSQ`6oi&>z60nb*qGDqPe-miuNsqLg3Pe3{h#z z%#?PSyWHrT(uW0j?PbtIa6a1thNYk9tFb(R#sbZN}}j@BoKo}y~a^yKi#X3BV99_F`^V4-%Kl2^z? z*Gm>r`LOaIRloSXEk=D$XT%HgXXsYfe&Z2-qqR|y5pSZ&YaQJc`j+865GOvk?^7W3iVU$tiloXQ&?GQVqp?u>w8;*h|{}d?9kv%T>YE0d|nPKO3$BT*6 zo*OfplWlGNGgTb1@m8|_7sLbJLe`DPeLHwOD$Q5Vn+Xn@wT?fIe)0Tz#+@nKnm?F# zXLKT^h%pc|Mpz@oNR9TCaH4)bd?L^)ir0q}F-ypoMxGumyqNg#%n{=iw?I6{xew!B z$Y9F?bKU{FUy%-hvEXa`vQs{CYb|I0$FGs=^2J#RdB|YVcQh7^Sji@U-ld;y)yx`0 zavg@Oo*}t<-?_EdD%9{HzgkX1qgJOXeu+|?Mnf&4FY1j#Ilv=+ft#B~vl1k6SNSo4 z=^)42bZeTW1o=qiyx&D{(a9%jddGUb6s$t$ptZ$56}38LUl%7AE&!Oo4bq%5GfG>2 zym}{<)Rc^U`Uf0K*<$J^LP<|24t}=q&)|{QtKe;HfN zCu{UWwbR{p#0~ILcFm88|f4BE#K&OWX9* z9?<`OG~k~v=0COfe+q5=%;tZlG&RZ!sIP^w-d{1{kKmt)s7z;xQ2=+bu;UbKiv=np z{KfCygXAh+^NT0?rk__F4s~O9taC`YGJfKNAt1JjFCeU>S@*zeZY@^|tmJm2WOZpl zWm$k}C?MgIV=CFUET{03eV66mB`b-mLe1d>6V7hau;9A_qb^}!S}R5>f}Az?$t)({ zX@+dQ!FlhQkKF@G$^K~21xc1-Gfi>5Jps0&tkG(z6+f1F}b8GU;J8VYI$9tw*29-`K_@^=Um5YXDl+TyvBh4X*hIsG@I{vq1N z(^1ethWR5)yTpPXaU&|H~&+-^s51VpLj&wJ&4+-kd|fo0gsLUJG`lp znWKY)g&FW?z#_;IrhodzKlWllD@hMPTxb{p3X1LrpbNoofX^MRZ2ri7{$Yj8R1q;k z3|oi1?z>N|Zw>M9S&pEe8uq(R&v4JMI}vq~-@}YdO&owA6Nf+c)=H}`RV|2)f)L+) zat~MQ+w?a$GiM7EpvBJ`@V=e@h#DEmu0H`0R0GoM*?$1XL9R>rrNcrR@LzU9xPRoR z|0xu(+{509Y*79N>jdc)Aaju2|I7vcSmHD`B~ciNygHDMD0mN9>#IWbmq=64b33EI z*V@e4jh7hGQBtv>pm=_G2MhFn`40Xbu14@lwFJ`0pCHwneuTed{Y$vH#dC|l^D-6U zi_{c|m+3*?0M`$egE{^Z{->VykAw5VsZO6jM8AN{7k;$+1Lt3&K~9j9o`2N4{*#+C z-n08oL`3j6aA%OciM5f9sfoFX^&k7VFy|Q;3?z&QLB>~Adnd*8av3yQIZkT)S@jvs7B7x^3V-#S)m@?FFsgiH3nv_2L68}9#~ zS5e=y_)f%9;x}Xvz`_~u$L@6ToQo0+k@b7fx*w%$eS7~5^!I)w86NIl2vJo85-EN} z?o0oXZGZ1T51W++ry$6B2=d2C6Qr1j50mXJvx$l2oe#DB)fkLO#`#b{7aLHz$d`(&{G zBh&sx{Jt9fPxpZQ+lufX@cpvny!RZY)>jSmci?|55dVUHznCTW4|L>^zoY-65c*Fn zzhCE&{|B~8++VYQRXp=2{QDOo{WN_qKi`l23Fm(5^wAIYgdG2Z^Sku$PiXh^iuZ$Ut*`sZAJTr7oc$LO9x{FU So@HZ&DuXOS`cJ?A_x}LoM0H~T literal 0 HcmV?d00001 diff --git a/webgis-poverty-pontianak/README.md b/webgis-poverty-pontianak/README.md new file mode 100644 index 0000000..5ba2575 --- /dev/null +++ b/webgis-poverty-pontianak/README.md @@ -0,0 +1,84 @@ +# WebGIS Pemetaan Kemiskinan Kota Pontianak + +Aplikasi WebGIS sederhana berbasis Leaflet.js untuk memetakan data kemiskinan, sebaran penduduk miskin, log bantuan, dan rumah ibadah di Kota Pontianak. + +> [!WARNING] +> **DISCLAIMER — DATA DUMMY / BUKAN DATA NYATA** +> +> Seluruh data yang ditampilkan dalam aplikasi ini, termasuk namun tidak terbatas pada: +> - Data nama, lokasi, dan kategori **penduduk miskin** +> - **Foto rumah** dan **Foto Kartu Keluarga (KK)** yang diunggah +> - Data **rumah ibadah** beserta radius jangkauannya +> - **Log bantuan** yang tercatat di sistem +> +> adalah **data fiktif / dummy** yang dibuat semata-mata untuk keperluan **demonstrasi, pengembangan, dan pengujian sistem** ini. +> Data tersebut **tidak mewakili kondisi, identitas, atau situasi nyata** dari individu maupun lokasi mana pun di Kota Pontianak. + +## Fitur Utama + +- **Pemetaan Interaktif**: Visualisasi peta dengan Leaflet.js yang berpusat di Kota Pontianak. +- **Manajemen Data Spasial**: + - **Rumah Ibadah**: Lokasi titik rumah ibadah (Masjid, Gereja, Vihara, dll) beserta jangkauan radius jemaah/bantuan. + - **Penduduk Miskin**: Pemetaan warga kurang mampu dan integrasi log/riwayat bantuan sosial yang disalurkan melalui rumah ibadah terdekat. +- **Pencarian Cepat**: Cari data rumah ibadah langsung dari bilah pencarian. +- **Impor GeoJSON Eksternal**: Pengguna dapat menambahkan file GeoJSON dari perangkat lokal ke dalam peta. + +## Persyaratan Sistem + +- **Server Web**: Apache (misal menggunakan XAMPP atau Laragon). +- **Bahasa Pemrograman**: PHP 7.4 ke atas. +- **Database**: MySQL versi 5.7+ atau MariaDB versi 10.2+ (Wajib mendukung fitur fungsi spasial seperti `ST_GeomFromGeoJSON` dan `ST_AsGeoJSON`). + +## Cara Instalasi & Penggunaan + +1. **Unduh/Clone Repositori**: + Tempatkan folder `webgis-poverty-pontianak` di dalam direktori root server web Anda (misalnya `C:/xampp/htdocs/webgis/webgis-poverty-pontianak`). + +2. **Setup Database**: + - Buka phpMyAdmin atau MySQL client pilihan Anda. + - Buat database baru bernama `webgis`: + ```sql + CREATE DATABASE webgis; + ``` + - Import file `database.sql` ke dalam database `webgis` tersebut. + +3. **Konfigurasi Koneksi**: + - Buka file [api/db_connect.php](api/db_connect.php). + - Sesuaikan konfigurasi host, user, password, dan database sesuai dengan setup database MySQL lokal Anda: + ```php + $host = "localhost"; + $user = "root"; + $pass = ""; + $db = "webgis"; + ``` + +4. **Jalankan Aplikasi**: + - Aktifkan modul **Apache** dan **MySQL** di Control Panel XAMPP Anda. + - Buka browser dan navigasikan ke alamat: + [http://localhost/webgis/webgis-poverty-pontianak/index.php](http://localhost/webgis/webgis-poverty-pontianak/index.php) + +## Akun Akses Default (Login) + +Anda dapat masuk ke dalam sistem menggunakan akun simulasi berikut: + +- **Akun Administrator (Admin)**: + - **Username**: `admin` + - **Password**: `password` + - **Hak Akses**: Mengelola data spasial rumah ibadah, penduduk miskin, mengelola akun pengelola rumah ibadah, dan manajemen pengguna secara penuh. + +- **Akun Pengelola Rumah Ibadah**: + - **Username**: `pengelola_mujahidin` + - **Password**: `password` + - **Hak Akses**: Mengelola (tambah, edit, hapus, impor, geser lokasi) data penduduk miskin, serta menginput log bantuan sosial yang disalurkan melalui masjid kelolaannya (Masjid Raya Mujahidin). + +## Struktur Folder + +- `api/` — Kumpulan REST API endpoint untuk operasi CRUD masing-masing fitur. + - `rumah_ibadah/`, `penduduk_miskin/`, `log_bantuan/` +- `assets/` — File aset frontend. + - `css/` — Gaya UI (custom style.css). + - `js/` — Logika frontend peta dan pengelolaan interaksi panel data. + - `features/` — Modul fitur Leaflet (manajemen layer, geolokasi, dll). +- `index.php` — Halaman utama interface WebGIS. +- `database.sql` — Skema database beserta **data dummy** Pontianak untuk pengetesan awal. Seluruh data di dalamnya bersifat fiktif dan tidak merepresentasikan data nyata. +- `uploads/` — Folder penyimpanan foto yang diunggah. File yang sudah ada merupakan contoh dummy semata. diff --git a/webgis-poverty-pontianak/api/auth_helper.php b/webgis-poverty-pontianak/api/auth_helper.php new file mode 100644 index 0000000..fef32e9 --- /dev/null +++ b/webgis-poverty-pontianak/api/auth_helper.php @@ -0,0 +1,56 @@ + $_SESSION['user_id'], + 'username' => $_SESSION['username'], + 'role' => $_SESSION['role'], + 'ibadah_id' => $_SESSION['ibadah_id'] ? intval($_SESSION['ibadah_id']) : null + ]; +} + +function requireLogin() { + if (!isLoggedIn()) { + header('HTTP/1.1 401 Unauthorized'); + echo json_encode(['status' => 'error', 'message' => 'Unauthorized: Silakan login terlebih dahulu.']); + exit; + } +} + +function requireAdmin() { + requireLogin(); + if ($_SESSION['role'] !== 'admin') { + header('HTTP/1.1 403 Forbidden'); + echo json_encode(['status' => 'error', 'message' => 'Forbidden: Akses ditolak. Hanya Admin yang diizinkan.']); + exit; + } +} + +function requireAdminOrPengelola() { + requireLogin(); + if ($_SESSION['role'] !== 'admin' && $_SESSION['role'] !== 'pengelola') { + header('HTTP/1.1 403 Forbidden'); + echo json_encode(['status' => 'error', 'message' => 'Forbidden: Akses ditolak.']); + exit; + } +} + +function canManageIbadah($ibadah_id) { + if (!isLoggedIn()) return false; + if ($_SESSION['role'] === 'admin') return true; + if ($_SESSION['role'] === 'pengelola') { + return intval($_SESSION['ibadah_id']) === intval($ibadah_id); + } + return false; +} +?> diff --git a/webgis-poverty-pontianak/api/check_session.php b/webgis-poverty-pontianak/api/check_session.php new file mode 100644 index 0000000..b9d2f69 --- /dev/null +++ b/webgis-poverty-pontianak/api/check_session.php @@ -0,0 +1,27 @@ + 'success', + 'isLoggedIn' => true, + 'data' => [ + 'id' => intval($_SESSION['user_id']), + 'username' => $_SESSION['username'], + 'role' => $_SESSION['role'], + 'ibadah_id' => $_SESSION['ibadah_id'] ? intval($_SESSION['ibadah_id']) : null, + 'nama_ibadah' => $_SESSION['nama_ibadah'] ?? null + ] + ]); +} else { + echo json_encode([ + 'status' => 'success', + 'isLoggedIn' => false, + 'data' => null + ]); +} +?> diff --git a/webgis-poverty-pontianak/api/dashboard/stats.php b/webgis-poverty-pontianak/api/dashboard/stats.php new file mode 100644 index 0000000..f058620 --- /dev/null +++ b/webgis-poverty-pontianak/api/dashboard/stats.php @@ -0,0 +1,196 @@ +query("SELECT * FROM rumah_ibadah WHERE id=$ibadahId"); +} else { + $riRes = $conn->query("SELECT * FROM rumah_ibadah"); +} +$ibadahList = []; +while ($row = $riRes->fetch_assoc()) $ibadahList[] = $row; +$totalIbadah = count($ibadahList); + +// Distribusi per jenis +$jenisDist = []; +foreach ($ibadahList as $ib) { + $j = $ib['jenis'] ?? 'Lainnya'; + $jenisDist[$j] = ($jenisDist[$j] ?? 0) + 1; +} + +// ── 2. Penduduk Miskin ──────────────────────────────────────────────────── +$pmRes = $conn->query("SELECT * FROM penduduk_miskin"); +$allMiskin = []; +while ($row = $pmRes->fetch_assoc()) $allMiskin[] = $row; + +// Filter: pengelola hanya lihat yang dalam radius ibadahnya +if ($isPengelola && $ibadahId && !empty($ibadahList)) { + $ib = $ibadahList[0]; + $filteredMiskin = array_filter($allMiskin, function($m) use ($ib) { + return haversine((float)$ib['lat'], (float)$ib['lng'], (float)$m['lat'], (float)$m['lng']) <= (float)$ib['radius']; + }); + $filteredMiskin = array_values($filteredMiskin); +} else { + $filteredMiskin = $allMiskin; +} + +$totalMiskin = count($filteredMiskin); +$totalJiwa = array_sum(array_column($filteredMiskin, 'jumlah_jiwa')); + +// Kategori bantuan +$kategoriDist = []; +foreach ($filteredMiskin as $m) { + $k = $m['kategori_bantuan'] ?? 'Lainnya'; + $kategoriDist[$k] = ($kategoriDist[$k] ?? 0) + 1; +} + +// Terurus vs Tidak (dalam radius salah satu ibadah) +$terurusCount = 0; +$tidakTerurusCount = 0; +foreach ($filteredMiskin as $m) { + $inAnyRadius = false; + foreach ($ibadahList as $ib) { + if (haversine((float)$ib['lat'], (float)$ib['lng'], (float)$m['lat'], (float)$m['lng']) <= (float)$ib['radius']) { + $inAnyRadius = true; + break; + } + } + if ($inAnyRadius) $terurusCount++; + else $tidakTerurusCount++; +} + +// Jika admin: hitung seluruh miskin dalam radius seluruh ibadah +if (!$isPengelola) { + $allIbadahRes = $conn->query("SELECT * FROM rumah_ibadah"); + $allIbadahList = []; + while ($row = $allIbadahRes->fetch_assoc()) $allIbadahList[] = $row; + + $terurusCount = 0; + $tidakTerurusCount = 0; + foreach ($allMiskin as $m) { + $inAnyRadius = false; + foreach ($allIbadahList as $ib) { + if (haversine((float)$ib['lat'], (float)$ib['lng'], (float)$m['lat'], (float)$m['lng']) <= (float)$ib['radius']) { + $inAnyRadius = true; + break; + } + } + if ($inAnyRadius) $terurusCount++; + else $tidakTerurusCount++; + } +} + +// ── 3. Log Bantuan ──────────────────────────────────────────────────────── +if ($isPengelola && $ibadahId) { + $logRes = $conn->query(" + SELECT lb.*, ri.nama as nama_ibadah, ri.jenis as jenis_ibadah, pm.nama as nama_kk + FROM log_bantuan lb + JOIN rumah_ibadah ri ON ri.id = lb.ibadah_id + JOIN penduduk_miskin pm ON pm.id = lb.miskin_id + WHERE lb.ibadah_id = $ibadahId + ORDER BY lb.tanggal DESC, lb.id DESC + LIMIT 10 + "); + $totalLogRes = $conn->query("SELECT COUNT(*) as cnt FROM log_bantuan WHERE ibadah_id=$ibadahId"); +} else { + $logRes = $conn->query(" + SELECT lb.*, ri.nama as nama_ibadah, ri.jenis as jenis_ibadah, pm.nama as nama_kk + FROM log_bantuan lb + JOIN rumah_ibadah ri ON ri.id = lb.ibadah_id + JOIN penduduk_miskin pm ON pm.id = lb.miskin_id + ORDER BY lb.tanggal DESC, lb.id DESC + LIMIT 10 + "); + $totalLogRes = $conn->query("SELECT COUNT(*) as cnt FROM log_bantuan"); +} + +$recentLogs = []; +while ($row = $logRes->fetch_assoc()) $recentLogs[] = $row; + +$totalLog = 0; +if ($totalLogRes && $trow = $totalLogRes->fetch_assoc()) $totalLog = (int)$trow['cnt']; + +// Distribusi tipe bantuan dari log +$tipeDist = []; +if ($isPengelola && $ibadahId) { + $tipeRes = $conn->query("SELECT tipe_bantuan, COUNT(*) as cnt FROM log_bantuan WHERE ibadah_id=$ibadahId GROUP BY tipe_bantuan"); +} else { + $tipeRes = $conn->query("SELECT tipe_bantuan, COUNT(*) as cnt FROM log_bantuan GROUP BY tipe_bantuan"); +} +while ($row = $tipeRes->fetch_assoc()) $tipeDist[$row['tipe_bantuan']] = (int)$row['cnt']; + +// Bantuan per bulan (6 bulan terakhir) +if ($isPengelola && $ibadahId) { + $bulanRes = $conn->query(" + SELECT DATE_FORMAT(tanggal, '%Y-%m') as bulan, COUNT(*) as cnt + FROM log_bantuan + WHERE ibadah_id=$ibadahId AND tanggal >= DATE_SUB(CURDATE(), INTERVAL 6 MONTH) + GROUP BY bulan ORDER BY bulan ASC + "); +} else { + $bulanRes = $conn->query(" + SELECT DATE_FORMAT(tanggal, '%Y-%m') as bulan, COUNT(*) as cnt + FROM log_bantuan + WHERE tanggal >= DATE_SUB(CURDATE(), INTERVAL 6 MONTH) + GROUP BY bulan ORDER BY bulan ASC + "); +} +$bantuanPerBulan = []; +while ($row = $bulanRes->fetch_assoc()) $bantuanPerBulan[] = $row; + +// ── 4. Ibadah Tipe (admin only: performa per ibadah) ───────────────────── +$ibadahPerforma = []; +if (!$isPengelola) { + $perfRes = $conn->query(" + SELECT ri.id, ri.nama, ri.jenis, ri.radius, + COUNT(DISTINCT lb.id) as total_log, + COUNT(DISTINCT lb.miskin_id) as total_penerima + FROM rumah_ibadah ri + LEFT JOIN log_bantuan lb ON lb.ibadah_id = ri.id + GROUP BY ri.id + ORDER BY total_log DESC + "); + while ($row = $perfRes->fetch_assoc()) $ibadahPerforma[] = $row; +} + +// ── Output ──────────────────────────────────────────────────────────────── +echo json_encode([ + 'status' => 'success', + 'role' => $user['role'], + 'ibadah_id' => $ibadahId, + 'stats' => [ + 'total_ibadah' => $totalIbadah, + 'total_miskin' => $totalMiskin, + 'total_jiwa' => $totalJiwa, + 'total_log' => $totalLog, + 'terurus' => $terurusCount, + 'tidak_terurus' => $tidakTerurusCount, + 'pct_terurus' => $totalMiskin > 0 ? round($terurusCount / $totalMiskin * 100, 1) : 0, + ], + 'distribusi' => [ + 'jenis_ibadah' => $jenisDist, + 'kategori' => $kategoriDist, + 'tipe_bantuan' => $tipeDist, + 'per_bulan' => $bantuanPerBulan, + ], + 'ibadah_list' => $ibadahList, + 'ibadah_performa' => $ibadahPerforma, + 'recent_logs' => $recentLogs, +]); diff --git a/webgis-poverty-pontianak/api/dashboard/stats_extended.php b/webgis-poverty-pontianak/api/dashboard/stats_extended.php new file mode 100644 index 0000000..5ce391c --- /dev/null +++ b/webgis-poverty-pontianak/api/dashboard/stats_extended.php @@ -0,0 +1,171 @@ +connect_error) return null; + $c->set_charset("utf8mb4"); + return $c; +} + +// ── Koneksi ke masing-masing database ──────────────────────────────────── +$connPoverty = makeConn("webgis_poverty"); // atau "webgis" sesuai db.sql +$connJalan = makeConn("jalan"); +$connSpbu = makeConn("spbu"); + +// ── 1. Data dari webgis_poverty (kemiskinan) ───────────────────────────── +$poverty = [ + 'total_miskin' => 0, + 'total_jiwa' => 0, + 'total_ibadah' => 0, + 'total_log' => 0, + 'terurus' => 0, + 'tidak_terurus' => 0, + 'pct_terurus' => 0, + 'distribusi' => ['kategori' => [], 'tipe_bantuan' => [], 'per_bulan' => []], +]; + +if ($connPoverty) { + // Total KK miskin & jiwa + $r = $connPoverty->query("SELECT COUNT(*) as c, COALESCE(SUM(jumlah_jiwa),0) as j FROM penduduk_miskin"); + if ($r && $row = $r->fetch_assoc()) { + $poverty['total_miskin'] = (int)$row['c']; + $poverty['total_jiwa'] = (int)$row['j']; + } + + // Total rumah ibadah + $r = $connPoverty->query("SELECT COUNT(*) as c FROM rumah_ibadah"); + if ($r && $row = $r->fetch_assoc()) $poverty['total_ibadah'] = (int)$row['c']; + + // Total log bantuan + $r = $connPoverty->query("SELECT COUNT(*) as c FROM log_bantuan"); + if ($r && $row = $r->fetch_assoc()) $poverty['total_log'] = (int)$row['c']; + + // Kategori bantuan + $r = $connPoverty->query("SELECT kategori_bantuan, COUNT(*) as c FROM penduduk_miskin GROUP BY kategori_bantuan"); + if ($r) while ($row = $r->fetch_assoc()) $poverty['distribusi']['kategori'][$row['kategori_bantuan']] = (int)$row['c']; + + // Tipe bantuan dari log + $r = $connPoverty->query("SELECT tipe_bantuan, COUNT(*) as c FROM log_bantuan GROUP BY tipe_bantuan"); + if ($r) while ($row = $r->fetch_assoc()) $poverty['distribusi']['tipe_bantuan'][$row['tipe_bantuan']] = (int)$row['c']; + + // Bantuan per bulan (6 bulan terakhir) + $r = $connPoverty->query(" + SELECT DATE_FORMAT(tanggal,'%Y-%m') as bulan, COUNT(*) as cnt + FROM log_bantuan + WHERE tanggal >= DATE_SUB(CURDATE(), INTERVAL 6 MONTH) + GROUP BY bulan ORDER BY bulan ASC + "); + if ($r) while ($row = $r->fetch_assoc()) $poverty['distribusi']['per_bulan'][] = $row; + + // Terurus vs tidak (radius sederhana: ada di radius salah satu ibadah) + $ibadahRes = $connPoverty->query("SELECT lat, lng, radius FROM rumah_ibadah"); + $ibadahArr = []; + if ($ibadahRes) while ($row = $ibadahRes->fetch_assoc()) $ibadahArr[] = $row; + + $miskinRes = $connPoverty->query("SELECT lat, lng FROM penduduk_miskin"); + if ($miskinRes) { + while ($m = $miskinRes->fetch_assoc()) { + $inRadius = false; + foreach ($ibadahArr as $ib) { + $dlat = deg2rad($ib['lat'] - $m['lat']); + $dlng = deg2rad($ib['lng'] - $m['lng']); + $a = sin($dlat/2)**2 + cos(deg2rad($m['lat']))*cos(deg2rad($ib['lat']))*sin($dlng/2)**2; + $dist = 6371000 * 2 * atan2(sqrt($a), sqrt(1-$a)); + if ($dist <= (float)$ib['radius']) { $inRadius = true; break; } + } + if ($inRadius) $poverty['terurus']++; else $poverty['tidak_terurus']++; + } + $tot = $poverty['total_miskin']; + $poverty['pct_terurus'] = $tot > 0 ? round($poverty['terurus'] / $tot * 100, 1) : 0; + } + $connPoverty->close(); +} + +// ── 2. Data Jalan ───────────────────────────────────────────────────────── +$jalan = [ + 'total_jalan' => 0, + 'total_panjang_m' => 0, + 'per_status' => [], + 'total_parsil' => 0, + 'total_luas_m2' => 0, + 'per_kepemilikan' => [], +]; + +if ($connJalan) { + $r = $connJalan->query("SELECT COUNT(*) as c, COALESCE(SUM(panjang_meter),0) as p FROM jalan"); + if ($r && $row = $r->fetch_assoc()) { + $jalan['total_jalan'] = (int)$row['c']; + $jalan['total_panjang_m'] = (float)$row['p']; + } + + $r = $connJalan->query("SELECT status_jalan, COUNT(*) as c FROM jalan GROUP BY status_jalan"); + if ($r) while ($row = $r->fetch_assoc()) $jalan['per_status'][$row['status_jalan']] = (int)$row['c']; + + $r = $connJalan->query("SELECT COUNT(*) as c, COALESCE(SUM(luas_m2),0) as l FROM parsil_tanah"); + if ($r && $row = $r->fetch_assoc()) { + $jalan['total_parsil'] = (int)$row['c']; + $jalan['total_luas_m2'] = (float)$row['l']; + } + + $r = $connJalan->query("SELECT status_kepemilikan, COUNT(*) as c FROM parsil_tanah GROUP BY status_kepemilikan"); + if ($r) while ($row = $r->fetch_assoc()) $jalan['per_kepemilikan'][$row['status_kepemilikan']] = (int)$row['c']; + + $connJalan->close(); +} + +// ── 3. Data SPBU ────────────────────────────────────────────────────────── +$spbu = [ + 'total_spbu' => 0, + 'buka_24_jam' => 0, + 'tidak_24_jam' => 0, + 'list' => [], +]; + +if ($connSpbu) { + $r = $connSpbu->query("SELECT COUNT(*) as c FROM spbu"); + if ($r && $row = $r->fetch_assoc()) $spbu['total_spbu'] = (int)$row['c']; + + $r = $connSpbu->query("SELECT SUM(buka_24_jam=1) as buka, SUM(buka_24_jam=0) as tidak FROM spbu"); + if ($r && $row = $r->fetch_assoc()) { + $spbu['buka_24_jam'] = (int)$row['buka']; + $spbu['tidak_24_jam'] = (int)$row['tidak']; + } + + $r = $connSpbu->query("SELECT nama_spbu, nomor_wa, buka_24_jam, latitude, longitude FROM spbu ORDER BY nama_spbu"); + if ($r) while ($row = $r->fetch_assoc()) $spbu['list'][] = $row; + + $connSpbu->close(); +} + +// ── 4. Data Penduduk (choropleth — static dari pontianak.json) ──────────── +// Data kepadatan per kecamatan sudah ada di file JS, ringkasan di sini +$penduduk = [ + 'kecamatan' => [ + ['nama' => 'Pontianak Barat', 'density' => 9.331], + ['nama' => 'Pontianak Kota', 'density' => 8.102], + ['nama' => 'Pontianak Timur', 'density' => 9.196], + ['nama' => 'Pontianak Selatan', 'density' => 5.673], + ['nama' => 'Pontianak Utara', 'density' => 3.642], + ['nama' => 'Pontianak Tenggara', 'density' => 3.103], + ] +]; +$penduduk['total_kecamatan'] = count($penduduk['kecamatan']); +$penduduk['rata_density'] = round(array_sum(array_column($penduduk['kecamatan'],'density')) / $penduduk['total_kecamatan'], 3); +$penduduk['terpadat'] = $penduduk['kecamatan'][array_search(max(array_column($penduduk['kecamatan'],'density')), array_column($penduduk['kecamatan'],'density'))]['nama']; + +// ── Output ──────────────────────────────────────────────────────────────── +echo json_encode([ + 'status' => 'success', + 'poverty' => $poverty, + 'jalan' => $jalan, + 'spbu' => $spbu, + 'penduduk' => $penduduk, +], JSON_UNESCAPED_UNICODE); diff --git a/webgis-poverty-pontianak/api/db_connect.php b/webgis-poverty-pontianak/api/db_connect.php new file mode 100644 index 0000000..a3922ed --- /dev/null +++ b/webgis-poverty-pontianak/api/db_connect.php @@ -0,0 +1,17 @@ +connect_error) { + die("Koneksi gagal: " . $conn->connect_error); +} +// Set charset +$conn->set_charset("utf8mb4"); + +// Jika di-include oleh file API, biarkan $conn tersedia +?> diff --git a/webgis-poverty-pontianak/api/log_bantuan/create.php b/webgis-poverty-pontianak/api/log_bantuan/create.php new file mode 100644 index 0000000..df855e8 --- /dev/null +++ b/webgis-poverty-pontianak/api/log_bantuan/create.php @@ -0,0 +1,37 @@ + 'error', 'message' => 'Forbidden: Anda tidak diizinkan membuat log untuk rumah ibadah lain.']); + exit; + } +} + +if (!$miskin_id || !$ibadah_id || !$tipe_bantuan || !$tanggal) { + echo json_encode(['status' => 'error', 'message' => 'Data tidak lengkap']); + exit; +} + +$sql = "INSERT INTO log_bantuan (miskin_id, ibadah_id, tipe_bantuan, tanggal, keterangan) VALUES (?, ?, ?, ?, ?)"; +$stmt = $conn->prepare($sql); +$stmt->bind_param('iisss', $miskin_id, $ibadah_id, $tipe_bantuan, $tanggal, $keterangan); + +if ($stmt->execute()) { + echo json_encode(['status' => 'success', 'id' => $stmt->insert_id]); +} else { + echo json_encode(['status' => 'error', 'message' => $conn->error]); +} +$conn->close(); diff --git a/webgis-poverty-pontianak/api/log_bantuan/read.php b/webgis-poverty-pontianak/api/log_bantuan/read.php new file mode 100644 index 0000000..4cbc5c2 --- /dev/null +++ b/webgis-poverty-pontianak/api/log_bantuan/read.php @@ -0,0 +1,37 @@ + 'error', 'message' => 'miskin_id diperlukan']); + exit; +} + +$sql = " + SELECT + lb.id, + lb.tipe_bantuan, + lb.tanggal, + lb.keterangan, + ri.nama AS nama_ibadah, + ri.jenis AS jenis_ibadah + FROM log_bantuan lb + JOIN rumah_ibadah ri ON ri.id = lb.ibadah_id + WHERE lb.miskin_id = ? + ORDER BY lb.tanggal DESC, lb.id DESC +"; + +$stmt = $conn->prepare($sql); +$stmt->bind_param('i', $miskin_id); +$stmt->execute(); +$result = $stmt->get_result(); + +$data = []; +while ($row = $result->fetch_assoc()) { + $data[] = $row; +} + +echo json_encode(['status' => 'success', 'data' => $data]); +$conn->close(); diff --git a/webgis-poverty-pontianak/api/login.php b/webgis-poverty-pontianak/api/login.php new file mode 100644 index 0000000..8db0e64 --- /dev/null +++ b/webgis-poverty-pontianak/api/login.php @@ -0,0 +1,55 @@ + 'error', 'message' => 'Username dan password wajib diisi']); + exit; +} + +// Cari user di database +$sql = "SELECT u.*, ri.nama as nama_ibadah + FROM users u + LEFT JOIN rumah_ibadah ri ON u.ibadah_id = ri.id + WHERE u.username = ?"; +$stmt = $conn->prepare($sql); +$stmt->bind_param('s', $username); +$stmt->execute(); +$result = $stmt->get_result(); + +if ($result->num_rows === 1) { + $user = $result->fetch_assoc(); + // Verifikasi password + if (password_verify($password, $user['password'])) { + $_SESSION['user_id'] = $user['id']; + $_SESSION['username'] = $user['username']; + $_SESSION['role'] = $user['role']; + $_SESSION['ibadah_id'] = $user['ibadah_id']; + $_SESSION['nama_ibadah'] = $user['nama_ibadah']; + + echo json_encode([ + 'status' => 'success', + 'message' => 'Login berhasil', + 'data' => [ + 'id' => intval($user['id']), + 'username' => $user['username'], + 'role' => $user['role'], + 'ibadah_id' => $user['ibadah_id'] ? intval($user['ibadah_id']) : null, + 'nama_ibadah' => $user['nama_ibadah'] + ] + ]); + exit; + } +} + +echo json_encode(['status' => 'error', 'message' => 'Username atau password salah']); +$conn->close(); +?> diff --git a/webgis-poverty-pontianak/api/logout.php b/webgis-poverty-pontianak/api/logout.php new file mode 100644 index 0000000..3e6c6de --- /dev/null +++ b/webgis-poverty-pontianak/api/logout.php @@ -0,0 +1,21 @@ + 'success', 'message' => 'Logout berhasil']); +?> diff --git a/webgis-poverty-pontianak/api/penduduk_miskin/bulk_create.php b/webgis-poverty-pontianak/api/penduduk_miskin/bulk_create.php new file mode 100644 index 0000000..974d79a --- /dev/null +++ b/webgis-poverty-pontianak/api/penduduk_miskin/bulk_create.php @@ -0,0 +1,83 @@ + 'error', 'message' => 'Akun pengelola tidak terhubung ke rumah ibadah manapun.']); + exit; + } + $res = $conn->query("SELECT lat, lng, radius FROM rumah_ibadah WHERE id=$ibadah_id"); + if (!$res || $res->num_rows === 0) { + echo json_encode(['status' => 'error', 'message' => 'Rumah ibadah yang dikelola tidak ditemukan.']); + exit; + } + $ibadahFilter = $res->fetch_assoc(); +} + +$data = json_decode(file_get_contents("php://input")); + +if (is_array($data)) { + $conn->begin_transaction(); + $inserted = 0; + $skipped = 0; + $errors = []; + foreach ($data as $item) { + if (isset($item->lat) && isset($item->lng) && $item->lat !== '' && $item->lng !== '') { + $nama = $conn->real_escape_string($item->nama ?? ''); + $kategori = $conn->real_escape_string($item->kategori_bantuan ?? 'Makan'); + $jumlah_jiwa = (int)($item->jumlah_jiwa ?? 1); + $lat = (float)$item->lat; + $lng = (float)$item->lng; + + // Jika pengelola, cek apakah item berada dalam radius ibadahnya + if ($ibadahFilter !== null) { + $R = 6371000; + $lat1 = deg2rad((float)$ibadahFilter['lat']); + $lat2 = deg2rad($lat); + $dLat = $lat2 - $lat1; + $dLng = deg2rad($lng - (float)$ibadahFilter['lng']); + $a = sin($dLat/2)*sin($dLat/2) + cos($lat1)*cos($lat2)*sin($dLng/2)*sin($dLng/2); + $dist = $R * 2 * atan2(sqrt($a), sqrt(1-$a)); + if ($dist > (float)$ibadahFilter['radius']) { + $skipped++; + continue; // Lewati item di luar radius + } + } + + $query = "INSERT INTO penduduk_miskin (nama, kategori_bantuan, jumlah_jiwa, lat, lng) + VALUES ('$nama', '$kategori', $jumlah_jiwa, $lat, $lng)"; + + if (!$conn->query($query)) { + $errors[] = $conn->error; + } else { + $inserted++; + } + } + } + + if (empty($errors) && $inserted > 0) { + $conn->commit(); + $msg = "Berhasil mengimpor $inserted data penduduk miskin."; + if ($skipped > 0) $msg .= " ($skipped data di luar radius diabaikan.)"; + echo json_encode(["status" => "success", "message" => $msg]); + } else if ($inserted === 0) { + $conn->rollback(); + $msg = $skipped > 0 + ? "Semua $skipped data berada di luar radius rumah ibadah Anda, tidak ada yang diimpor." + : "Tidak ada data valid yang diimpor."; + echo json_encode(["status" => "error", "message" => $msg]); + } else { + $conn->rollback(); + echo json_encode(["status" => "error", "message" => "Gagal mengimpor beberapa data. Transaksi dibatalkan.", "errors" => $errors]); + } +} else { + echo json_encode(["status" => "error", "message" => "Format data salah."]); +} +?> diff --git a/webgis-poverty-pontianak/api/penduduk_miskin/create.php b/webgis-poverty-pontianak/api/penduduk_miskin/create.php new file mode 100644 index 0000000..85037bd --- /dev/null +++ b/webgis-poverty-pontianak/api/penduduk_miskin/create.php @@ -0,0 +1,109 @@ +real_escape_string($_POST['nama'] ?? ''); + $kategori = $conn->real_escape_string($_POST['kategori_bantuan'] ?? 'Makan'); + $jumlah_jiwa = (int)($_POST['jumlah_jiwa'] ?? 1); + $lat = (float)($_POST['lat'] ?? 0); + $lng = (float)($_POST['lng'] ?? 0); +} else { + $data = json_decode(file_get_contents("php://input")); + if ($data) { + $nama = $conn->real_escape_string($data->nama ?? ''); + $kategori = $conn->real_escape_string($data->kategori_bantuan ?? 'Makan'); + $jumlah_jiwa = (int)($data->jumlah_jiwa ?? 1); + $lat = (float)($data->lat ?? 0); + $lng = (float)($data->lng ?? 0); + } +} + +// Validasi pengelola: hanya boleh tambah jika lokasi berada dalam radius ibadah yang dikelolanya +$currentUser = getCurrentUser(); +if ($currentUser && $currentUser['role'] === 'pengelola') { + $ibadah_id = $currentUser['ibadah_id']; + if (!$ibadah_id) { + http_response_code(403); + echo json_encode(['status' => 'error', 'message' => 'Akun pengelola tidak terhubung ke rumah ibadah manapun.']); + exit; + } + // Ambil data ibadah (lat, lng, radius) + $res = $conn->query("SELECT lat, lng, radius FROM rumah_ibadah WHERE id=$ibadah_id"); + if (!$res || $res->num_rows === 0) { + http_response_code(403); + echo json_encode(['status' => 'error', 'message' => 'Rumah ibadah yang dikelola tidak ditemukan.']); + exit; + } + $ib = $res->fetch_assoc(); + // Hitung jarak menggunakan Haversine formula + $R = 6371000; // meter + $lat1 = deg2rad((float)$ib['lat']); + $lat2 = deg2rad($lat); + $dLat = $lat2 - $lat1; + $dLng = deg2rad($lng - (float)$ib['lng']); + $a = sin($dLat/2)*sin($dLat/2) + cos($lat1)*cos($lat2)*sin($dLng/2)*sin($dLng/2); + $dist = $R * 2 * atan2(sqrt($a), sqrt(1-$a)); + if ($dist > (float)$ib['radius']) { + http_response_code(403); + echo json_encode(['status' => 'error', 'message' => 'Lokasi penduduk di luar radius rumah ibadah Anda. Hanya boleh menambah penduduk dalam radius yang dikelola.']); + exit; + } +} + +if ($lat != 0 && $lng != 0) { + $upload_dir = "../../uploads/"; + if (!file_exists($upload_dir)) { + mkdir($upload_dir, 0777, true); + } + + $foto_rumah = null; + $foto_kk = null; + + function uploadFile($fileKey, $upload_dir) { + if (isset($_FILES[$fileKey]) && $_FILES[$fileKey]['error'] === UPLOAD_ERR_OK) { + $fileTmpPath = $_FILES[$fileKey]['tmp_name']; + $fileName = $_FILES[$fileKey]['name']; + + $fileNameCmps = explode(".", $fileName); + $fileExtension = strtolower(end($fileNameCmps)); + + $allowedfileExtensions = array('jpg', 'jpeg', 'png', 'gif'); + if (in_array($fileExtension, $allowedfileExtensions)) { + $newFileName = uniqid() . '_' . preg_replace('/[^a-zA-Z0-9\._-]/', '_', $fileName); + $dest_path = $upload_dir . $newFileName; + + if (move_uploaded_file($fileTmpPath, $dest_path)) { + return $newFileName; + } + } + } + return null; + } + + $foto_rumah = uploadFile('foto_rumah', $upload_dir); + $foto_kk = uploadFile('foto_kk', $upload_dir); + + $val_foto_rumah = $foto_rumah ? "'$foto_rumah'" : "NULL"; + $val_foto_kk = $foto_kk ? "'$foto_kk'" : "NULL"; + + $query = "INSERT INTO penduduk_miskin (nama, kategori_bantuan, jumlah_jiwa, lat, lng, foto_rumah, foto_kk) + VALUES ('$nama', '$kategori', $jumlah_jiwa, $lat, $lng, $val_foto_rumah, $val_foto_kk)"; + + if ($conn->query($query)) { + echo json_encode(["status" => "success", "id" => $conn->insert_id, "message" => "Berhasil ditambahkan."]); + } else { + echo json_encode(["status" => "error", "message" => "Gagal: " . $conn->error]); + } +} else { + echo json_encode(["status" => "error", "message" => "Data tidak lengkap."]); +} +?> diff --git a/webgis-poverty-pontianak/api/penduduk_miskin/delete.php b/webgis-poverty-pontianak/api/penduduk_miskin/delete.php new file mode 100644 index 0000000..b994db8 --- /dev/null +++ b/webgis-poverty-pontianak/api/penduduk_miskin/delete.php @@ -0,0 +1,65 @@ +id)) { + $id = (int)$data->id; + + // Validasi pengelola: hanya boleh hapus penduduk dalam radius ibadah yang dikelolanya + $currentUser = getCurrentUser(); + if ($currentUser && $currentUser['role'] === 'pengelola') { + $ibadah_id = $currentUser['ibadah_id']; + if (!$ibadah_id) { + http_response_code(403); + echo json_encode(['status' => 'error', 'message' => 'Akun pengelola tidak terhubung ke rumah ibadah manapun.']); + exit; + } + // Ambil koordinat penduduk + $mRes = $conn->query("SELECT lat, lng FROM penduduk_miskin WHERE id=$id"); + if (!$mRes || $mRes->num_rows === 0) { + echo json_encode(['status' => 'error', 'message' => 'Data penduduk tidak ditemukan.']); + exit; + } + $mRow = $mRes->fetch_assoc(); + $pLat = (float)$mRow['lat']; + $pLng = (float)$mRow['lng']; + + // Ambil data ibadah + $iRes = $conn->query("SELECT lat, lng, radius FROM rumah_ibadah WHERE id=$ibadah_id"); + if (!$iRes || $iRes->num_rows === 0) { + http_response_code(403); + echo json_encode(['status' => 'error', 'message' => 'Rumah ibadah yang dikelola tidak ditemukan.']); + exit; + } + $ib = $iRes->fetch_assoc(); + + // Hitung jarak Haversine + $R = 6371000; + $lat1 = deg2rad((float)$ib['lat']); + $lat2 = deg2rad($pLat); + $dLat = $lat2 - $lat1; + $dLng = deg2rad($pLng - (float)$ib['lng']); + $a = sin($dLat/2)*sin($dLat/2) + cos($lat1)*cos($lat2)*sin($dLng/2)*sin($dLng/2); + $dist = $R * 2 * atan2(sqrt($a), sqrt(1-$a)); + if ($dist > (float)$ib['radius']) { + http_response_code(403); + echo json_encode(['status' => 'error', 'message' => 'Penduduk ini berada di luar radius rumah ibadah Anda. Tidak diizinkan menghapus.']); + exit; + } + } + + $query = "DELETE FROM penduduk_miskin WHERE id=$id"; + + if($conn->query($query)) { + echo json_encode(["status" => "success", "message" => "Berhasil dihapus."]); + } else { + echo json_encode(["status" => "error", "message" => "Gagal hapus: " . $conn->error]); + } +} else { + echo json_encode(["status" => "error", "message" => "ID tidak diberikan."]); +} +?> diff --git a/webgis-poverty-pontianak/api/penduduk_miskin/read.php b/webgis-poverty-pontianak/api/penduduk_miskin/read.php new file mode 100644 index 0000000..50e9817 --- /dev/null +++ b/webgis-poverty-pontianak/api/penduduk_miskin/read.php @@ -0,0 +1,28 @@ +query($query); + +$arr = array(); + +if($result->num_rows > 0) { + while($row = $result->fetch_assoc()) { + $item = array( + "id" => $row['id'], + "nama" => $row['nama'], + "kategori_bantuan" => $row['kategori_bantuan'], + "jumlah_jiwa" => isset($row['jumlah_jiwa']) ? (int)$row['jumlah_jiwa'] : 1, + "lat" => (float)$row['lat'], + "lng" => (float)$row['lng'], + "foto_rumah" => $row['foto_rumah'], + "foto_kk" => $row['foto_kk'] + ); + array_push($arr, $item); + } + echo json_encode(["status" => "success", "data" => $arr]); +} else { + echo json_encode(["status" => "success", "data" => []]); +} +?> diff --git a/webgis-poverty-pontianak/api/penduduk_miskin/update.php b/webgis-poverty-pontianak/api/penduduk_miskin/update.php new file mode 100644 index 0000000..2f8539c --- /dev/null +++ b/webgis-poverty-pontianak/api/penduduk_miskin/update.php @@ -0,0 +1,148 @@ +real_escape_string($_POST['nama'] ?? ''); + $kategori = $conn->real_escape_string($_POST['kategori_bantuan'] ?? 'Makan'); + $jumlah_jiwa = (int)($_POST['jumlah_jiwa'] ?? 1); + $lat = (float)($_POST['lat'] ?? 0); + $lng = (float)($_POST['lng'] ?? 0); +} else { + $data = json_decode(file_get_contents("php://input")); + if ($data) { + $id = (int)($data->id ?? 0); + $nama = $conn->real_escape_string($data->nama ?? ''); + $kategori = $conn->real_escape_string($data->kategori_bantuan ?? 'Makan'); + $jumlah_jiwa = (int)($data->jumlah_jiwa ?? 1); + $lat = (float)($data->lat ?? 0); + $lng = (float)($data->lng ?? 0); + } +} + +// Validasi pengelola: hanya boleh edit penduduk yang lokasinya dalam radius ibadah yang dikelolanya +$currentUser = getCurrentUser(); +if ($currentUser && $currentUser['role'] === 'pengelola') { + $ibadah_id = $currentUser['ibadah_id']; + if (!$ibadah_id) { + http_response_code(403); + echo json_encode(['status' => 'error', 'message' => 'Akun pengelola tidak terhubung ke rumah ibadah manapun.']); + exit; + } + $res = $conn->query("SELECT lat, lng, radius FROM rumah_ibadah WHERE id=$ibadah_id"); + if (!$res || $res->num_rows === 0) { + http_response_code(403); + echo json_encode(['status' => 'error', 'message' => 'Rumah ibadah yang dikelola tidak ditemukan.']); + exit; + } + $ib = $res->fetch_assoc(); + // Gunakan koordinat penduduk yang sedang diedit (dari DB jika lat/lng 0, atau dari input) + $checkLat = $lat; + $checkLng = $lng; + if ($checkLat == 0 && $checkLng == 0 && $id > 0) { + $mRes = $conn->query("SELECT lat, lng FROM penduduk_miskin WHERE id=$id"); + if ($mRes && $mRow = $mRes->fetch_assoc()) { + $checkLat = (float)$mRow['lat']; + $checkLng = (float)$mRow['lng']; + } + } + $R = 6371000; + $lat1 = deg2rad((float)$ib['lat']); + $lat2 = deg2rad($checkLat); + $dLat = $lat2 - $lat1; + $dLng = deg2rad($checkLng - (float)$ib['lng']); + $a = sin($dLat/2)*sin($dLat/2) + cos($lat1)*cos($lat2)*sin($dLng/2)*sin($dLng/2); + $dist = $R * 2 * atan2(sqrt($a), sqrt(1-$a)); + if ($dist > (float)$ib['radius']) { + http_response_code(403); + echo json_encode(['status' => 'error', 'message' => 'Penduduk ini berada di luar radius rumah ibadah Anda. Tidak diizinkan mengedit.']); + exit; + } +} + + +if ($id > 0) { + // Get current files to delete them if updated + $old_foto_rumah = null; + $old_foto_kk = null; + $res = $conn->query("SELECT foto_rumah, foto_kk FROM penduduk_miskin WHERE id=$id"); + if ($res && $row = $res->fetch_assoc()) { + $old_foto_rumah = $row['foto_rumah']; + $old_foto_kk = $row['foto_kk']; + } + + $upload_dir = "../../uploads/"; + if (!file_exists($upload_dir)) { + mkdir($upload_dir, 0777, true); + } + + $foto_rumah = null; + $foto_kk = null; + + function uploadFile($fileKey, $upload_dir) { + if (isset($_FILES[$fileKey]) && $_FILES[$fileKey]['error'] === UPLOAD_ERR_OK) { + $fileTmpPath = $_FILES[$fileKey]['tmp_name']; + $fileName = $_FILES[$fileKey]['name']; + + $fileNameCmps = explode(".", $fileName); + $fileExtension = strtolower(end($fileNameCmps)); + + $allowedfileExtensions = array('jpg', 'jpeg', 'png', 'gif'); + if (in_array($fileExtension, $allowedfileExtensions)) { + $newFileName = uniqid() . '_' . preg_replace('/[^a-zA-Z0-9\._-]/', '_', $fileName); + $dest_path = $upload_dir . $newFileName; + + if (move_uploaded_file($fileTmpPath, $dest_path)) { + return $newFileName; + } + } + } + return null; + } + + $foto_rumah = uploadFile('foto_rumah', $upload_dir); + $foto_kk = uploadFile('foto_kk', $upload_dir); + + // Build update fields + $update_fields = [ + "nama='$nama'", + "kategori_bantuan='$kategori'", + "jumlah_jiwa=$jumlah_jiwa", + "lat=$lat", + "lng=$lng" + ]; + + if ($foto_rumah !== null) { + $update_fields[] = "foto_rumah='$foto_rumah'"; + if ($old_foto_rumah && file_exists($upload_dir . $old_foto_rumah)) { + unlink($upload_dir . $old_foto_rumah); + } + } + if ($foto_kk !== null) { + $update_fields[] = "foto_kk='$foto_kk'"; + if ($old_foto_kk && file_exists($upload_dir . $old_foto_kk)) { + unlink($upload_dir . $old_foto_kk); + } + } + + $query = "UPDATE penduduk_miskin SET " . implode(", ", $update_fields) . " WHERE id=$id"; + + if ($conn->query($query)) { + echo json_encode(["status" => "success", "message" => "Update berhasil."]); + } else { + echo json_encode(["status" => "error", "message" => "Gagal update: " . $conn->error]); + } +} else { + echo json_encode(["status" => "error", "message" => "ID tidak diberikan."]); +} +?> diff --git a/webgis-poverty-pontianak/api/rumah_ibadah/create.php b/webgis-poverty-pontianak/api/rumah_ibadah/create.php new file mode 100644 index 0000000..2aa14bd --- /dev/null +++ b/webgis-poverty-pontianak/api/rumah_ibadah/create.php @@ -0,0 +1,28 @@ +lat) && !empty($data->lng)) { + $nama = $conn->real_escape_string($data->nama ?? ''); + $jenis = $conn->real_escape_string($data->jenis ?? 'Masjid'); + $alamat = $conn->real_escape_string($data->alamat ?? ''); + $radius = (float)($data->radius ?? 500); + $lat = (float)$data->lat; + $lng = (float)$data->lng; + + $query = "INSERT INTO rumah_ibadah (nama, jenis, alamat, radius, lat, lng) + VALUES ('$nama', '$jenis', '$alamat', $radius, $lat, $lng)"; + + if ($conn->query($query)) { + echo json_encode(["status" => "success", "id" => $conn->insert_id, "message" => "Rumah Ibadah berhasil ditambahkan."]); + } else { + echo json_encode(["status" => "error", "message" => "Gagal menambahkan: " . $conn->error]); + } +} else { + echo json_encode(["status" => "error", "message" => "Data tidak lengkap."]); +} +?> diff --git a/webgis-poverty-pontianak/api/rumah_ibadah/delete.php b/webgis-poverty-pontianak/api/rumah_ibadah/delete.php new file mode 100644 index 0000000..2a69540 --- /dev/null +++ b/webgis-poverty-pontianak/api/rumah_ibadah/delete.php @@ -0,0 +1,22 @@ +id)) { + $id = (int)$data->id; + + $query = "DELETE FROM rumah_ibadah WHERE id=$id"; + + if($conn->query($query)) { + echo json_encode(["status" => "success", "message" => "Berhasil dihapus."]); + } else { + echo json_encode(["status" => "error", "message" => "Gagal hapus: " . $conn->error]); + } +} else { + echo json_encode(["status" => "error", "message" => "ID tidak diberikan."]); +} +?> diff --git a/webgis-poverty-pontianak/api/rumah_ibadah/read.php b/webgis-poverty-pontianak/api/rumah_ibadah/read.php new file mode 100644 index 0000000..92b5a3c --- /dev/null +++ b/webgis-poverty-pontianak/api/rumah_ibadah/read.php @@ -0,0 +1,27 @@ +query($query); + +$arr = array(); + +if($result->num_rows > 0) { + while($row = $result->fetch_assoc()) { + $item = array( + "id" => $row['id'], + "nama" => $row['nama'], + "jenis" => $row['jenis'], + "alamat" => $row['alamat'], + "radius" => (float)$row['radius'], + "lat" => (float)$row['lat'], + "lng" => (float)$row['lng'] + ); + array_push($arr, $item); + } + echo json_encode(["status" => "success", "data" => $arr]); +} else { + echo json_encode(["status" => "success", "data" => []]); +} +?> diff --git a/webgis-poverty-pontianak/api/rumah_ibadah/update.php b/webgis-poverty-pontianak/api/rumah_ibadah/update.php new file mode 100644 index 0000000..0df1f5e --- /dev/null +++ b/webgis-poverty-pontianak/api/rumah_ibadah/update.php @@ -0,0 +1,30 @@ +id)) { + $id = (int)$data->id; + $nama = $conn->real_escape_string($data->nama ?? ''); + $jenis = $conn->real_escape_string($data->jenis ?? 'Masjid'); + $alamat = $conn->real_escape_string($data->alamat ?? ''); + $radius = (float)($data->radius ?? 500); + $lat = (float)$data->lat; + $lng = (float)$data->lng; + + $query = "UPDATE rumah_ibadah + SET nama='$nama', jenis='$jenis', alamat='$alamat', radius=$radius, lat=$lat, lng=$lng + WHERE id=$id"; + + if ($conn->query($query)) { + echo json_encode(["status" => "success", "message" => "Update berhasil."]); + } else { + echo json_encode(["status" => "error", "message" => "Gagal update: " . $conn->error]); + } +} else { + echo json_encode(["status" => "error", "message" => "ID tidak diberikan."]); +} +?> diff --git a/webgis-poverty-pontianak/api/users/create.php b/webgis-poverty-pontianak/api/users/create.php new file mode 100644 index 0000000..3de6ddc --- /dev/null +++ b/webgis-poverty-pontianak/api/users/create.php @@ -0,0 +1,47 @@ + 'error', 'message' => 'Username dan password wajib diisi']); + exit; +} + +if ($role !== 'admin' && $role !== 'pengelola') { + echo json_encode(['status' => 'error', 'message' => 'Role tidak valid']); + exit; +} + +// Cek apakah username sudah ada +$stmt = $conn->prepare("SELECT id FROM users WHERE username = ?"); +$stmt->bind_param('s', $username); +$stmt->execute(); +if ($stmt->get_result()->num_rows > 0) { + echo json_encode(['status' => 'error', 'message' => 'Username sudah digunakan']); + exit; +} + +// Hash password +$hashed_password = password_hash($password, PASSWORD_BCRYPT); + +// Insert user baru +$stmt = $conn->prepare("INSERT INTO users (username, password, role, ibadah_id) VALUES (?, ?, ?, ?)"); +$stmt->bind_param('sssi', $username, $hashed_password, $role, $ibadah_id); + +if ($stmt->execute()) { + echo json_encode(['status' => 'success', 'message' => 'User berhasil ditambahkan', 'id' => $stmt->insert_id]); +} else { + echo json_encode(['status' => 'error', 'message' => 'Gagal menambahkan user: ' . $conn->error]); +} + +$conn->close(); +?> diff --git a/webgis-poverty-pontianak/api/users/delete.php b/webgis-poverty-pontianak/api/users/delete.php new file mode 100644 index 0000000..08e507f --- /dev/null +++ b/webgis-poverty-pontianak/api/users/delete.php @@ -0,0 +1,30 @@ + 'error', 'message' => 'ID tidak valid']); + exit; +} + +if ($id === intval($_SESSION['user_id'])) { + echo json_encode(['status' => 'error', 'message' => 'Anda tidak bisa menghapus akun Anda sendiri']); + exit; +} + +$stmt = $conn->prepare("DELETE FROM users WHERE id = ?"); +$stmt->bind_param('i', $id); + +if ($stmt->execute()) { + echo json_encode(['status' => 'success', 'message' => 'User berhasil dihapus']); +} else { + echo json_encode(['status' => 'error', 'message' => 'Gagal menghapus user: ' . $conn->error]); +} + +$conn->close(); +?> diff --git a/webgis-poverty-pontianak/api/users/read.php b/webgis-poverty-pontianak/api/users/read.php new file mode 100644 index 0000000..4478784 --- /dev/null +++ b/webgis-poverty-pontianak/api/users/read.php @@ -0,0 +1,31 @@ +query($sql); +$arr = array(); + +if ($result && $result->num_rows > 0) { + while ($row = $result->fetch_assoc()) { + $item = array( + "id" => intval($row['id']), + "username" => $row['username'], + "role" => $row['role'], + "ibadah_id" => $row['ibadah_id'] ? intval($row['ibadah_id']) : null, + "nama_ibadah" => $row['nama_ibadah'] ?? '-' + ); + array_push($arr, $item); + } + echo json_encode(["status" => "success", "data" => $arr]); +} else { + echo json_encode(["status" => "success", "data" => []]); +} +$conn->close(); +?> diff --git a/webgis-poverty-pontianak/api/users/update.php b/webgis-poverty-pontianak/api/users/update.php new file mode 100644 index 0000000..117e7a1 --- /dev/null +++ b/webgis-poverty-pontianak/api/users/update.php @@ -0,0 +1,52 @@ + 'error', 'message' => 'Data tidak lengkap']); + exit; +} + +if ($role !== 'admin' && $role !== 'pengelola') { + echo json_encode(['status' => 'error', 'message' => 'Role tidak valid']); + exit; +} + +// Cek apakah username sudah ada di user lain +$stmt = $conn->prepare("SELECT id FROM users WHERE username = ? AND id != ?"); +$stmt->bind_param('si', $username, $id); +$stmt->execute(); +if ($stmt->get_result()->num_rows > 0) { + echo json_encode(['status' => 'error', 'message' => 'Username sudah digunakan oleh user lain']); + exit; +} + +if (!empty($password)) { + // Hash new password + $hashed_password = password_hash($password, PASSWORD_BCRYPT); + $stmt = $conn->prepare("UPDATE users SET username = ?, password = ?, role = ?, ibadah_id = ? WHERE id = ?"); + $stmt->bind_param('ssssi', $username, $hashed_password, $role, $ibadah_id, $id); +} else { + // Keep existing password + $stmt = $conn->prepare("UPDATE users SET username = ?, role = ?, ibadah_id = ? WHERE id = ?"); + $stmt->bind_param('sssi', $username, $role, $ibadah_id, $id); +} + +if ($stmt->execute()) { + echo json_encode(['status' => 'success', 'message' => 'User berhasil diperbarui']); +} else { + echo json_encode(['status' => 'error', 'message' => 'Gagal memperbarui user: ' . $conn->error]); +} + +$conn->close(); +?> diff --git a/webgis-poverty-pontianak/assets/css/style.css b/webgis-poverty-pontianak/assets/css/style.css new file mode 100644 index 0000000..d6762c2 --- /dev/null +++ b/webgis-poverty-pontianak/assets/css/style.css @@ -0,0 +1,1341 @@ +/* Reset & Base */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body, html { + height: 100%; + font-family: 'Google Sans Flex', 'Inter', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + overflow: hidden; +} + +/* Map Container */ +#map { + width: 100vw; + height: 100vh; + z-index: 1; +} + +/* Custom UI Container over Map */ +.ui-container { + position: absolute; + top: 20px; + left: 30%; + transform: translateX(-70%); + z-index: 1000; + width: 100%; + max-width: 400px; + display: flex; + flex-direction: column; + gap: 10px; + padding: 0 15px; +} + +/* Search Bar */ +.search-bar { + display: flex; + align-items: center; + background-color: white; + border-radius: 8px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + overflow: hidden; + height: 48px; + transition: box-shadow 0.3s; +} + +.search-bar:focus-within { + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25); +} + +.search-icon { + padding: 0 15px; + color: #666; + display: flex; + align-items: center; + justify-content: center; +} + +.search-input { + flex: 1; + border: none; + outline: none; + font-size: 16px; + padding: 10px 0; + color: #333; +} + +.search-clear { + padding: 0 15px; + color: #999; + cursor: pointer; + background: none; + border: none; + display: flex; + align-items: center; + justify-content: center; + visibility: hidden; +} + +.search-clear:hover { + color: #333; +} + +/* Custom Layer Control Button */ +.custom-layer-btn { + background-color: white; + border-radius: 8px; + width: 48px; + height: 48px; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + cursor: pointer; + border: none; + color: #333; +} + +.custom-layer-btn:hover { + background-color: #f8f9fa; +} + +#layerBtn { + position: absolute; + top: 20px; + right: 20px; + z-index: 1000; + transition: right 0.3s cubic-bezier(0.4, 0, 0.2, 1); +} + +body.right-panel-open #layerBtn { + right: 340px; +} + +.custom-layer-panel { + position: absolute; + top: 80px; + right: 20px; + z-index: 1000; + background-color: white; + border-radius: 8px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + padding: 15px; + width: 250px; + display: none; + transition: right 0.3s cubic-bezier(0.4, 0, 0.2, 1); +} + +body.right-panel-open .custom-layer-panel { + right: 340px; +} + + +.custom-layer-panel h3 { + margin-bottom: 10px; + font-size: 16px; + border-bottom: 1px solid #eee; + padding-bottom: 5px; +} + +.layer-section-title { + font-size: 11px; + font-weight: 700; + color: #6366f1; + text-transform: uppercase; + letter-spacing: 0.5px; + margin-bottom: 8px; + margin-top: 12px; + padding-bottom: 2px; + border-bottom: 1px dashed #e2e8f0; +} + +.layer-option { + display: flex; + align-items: center; + gap: 10px; + margin-bottom: 8px; + font-size: 14px; +} + +/* ===== Sidebar Toggle Button ===== */ +.sidebar-toggle-btn { + position: absolute; + left: 20px; + top: 190px; + z-index: 1001; + border-radius: 8px; + width: 48px; + height: 48px; + background: white; + border: none; + box-shadow: 0 3px 10px rgba(0,0,0,0.15); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + color: #6366f1; + font-size: 13px; + transition: all 0.2s; +} + +.sidebar-toggle-btn:hover { + background: #6366f1; + color: white; + box-shadow: 0 4px 14px rgba(99,102,241,0.4); +} + +.sidebar-toggle-btn.open { + background: #6366f1; + color: white; +} + +/* ===== Left Sidebar ===== */ +.left-sidebar { + position: absolute; + left: 20px; + top: 250px; /* di bawah toggle button */ + z-index: 1000; + display: flex; + flex-direction: column; + gap: 8px; +} + +.sidebar-section-label { + font-size: 9px; + font-weight: 700; + color: #94a3b8; + text-transform: uppercase; + text-align: center; + letter-spacing: 0.8px; + margin-top: 6px; + margin-bottom: 2px; + pointer-events: none; + user-select: none; +} + +.sidebar-divider { + height: 1px; + background: #e2e8f0; + margin: 4px 6px; +} + +.sidebar-btn { + width: 60px; + height: 60px; + background: white; + border: none; + border-radius: 12px; + box-shadow: 0 4px 12px rgba(0,0,0,0.12); + cursor: pointer; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 2px; + transition: all 0.2s ease; + padding: 6px 4px; +} + +.sidebar-btn:hover { + transform: translateX(3px); + box-shadow: 0 6px 18px rgba(0,0,0,0.18); + background: #f8f9fa; +} + +.sidebar-btn.active { + background: linear-gradient(135deg, #6366f1, #4f46e5); + color: white; + box-shadow: 0 6px 18px rgba(99,102,241,0.4); + transform: translateX(4px); +} + +.sidebar-emoji { + font-size: 22px; + line-height: 1; +} + +.sidebar-label { + font-size: 9px; + font-weight: 600; + letter-spacing: 0.3px; + color: #555; + text-transform: uppercase; +} + +.sidebar-btn.active .sidebar-label { + color: rgba(255,255,255,0.85); +} + +/* ===== Right Panel ===== */ +.right-panel { + position: absolute; + top: 0; + right: 0; + bottom: 0; + width: 320px; + background: #f8f9fb; + z-index: 999; + box-shadow: -4px 0 20px rgba(0,0,0,0.12); + display: flex; + flex-direction: column; + transform: translateX(100%); + transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1); + /* shift layer control when panel open */ +} + +.right-panel.open { + transform: translateX(0); +} + +.right-panel-header { + padding: 16px 16px 12px; + background: white; + border-bottom: 1px solid #eee; + display: flex; + align-items: center; + justify-content: space-between; + flex-shrink: 0; + padding-top: 26px; +} + +.right-panel-header h3 { + font-size: 15px; + font-weight: 700; + color: #1e1e2e; +} + +.right-panel-close { + width: 30px; + height: 30px; + border: none; + background: #f3f4f6; + border-radius: 8px; + cursor: pointer; + color: #555; + display: flex; + align-items: center; + justify-content: center; + font-size: 13px; + transition: background 0.2s; +} + +.right-panel-close:hover { + background: #e5e7eb; + color: #333; +} + +.right-panel-actions { + padding: 12px 14px; + background: white; + border-bottom: 1px solid #eee; + display: flex; + gap: 8px; + flex-shrink: 0; +} + +.right-panel-actions button { + flex: 1; + padding: 9px 10px; + border: none; + border-radius: 8px; + font-size: 12px; + font-weight: 600; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + gap: 6px; + transition: all 0.2s; +} + +.btn-panel-add { + background: linear-gradient(135deg, #6366f1, #4f46e5); + color: white; + box-shadow: 0 3px 10px rgba(99,102,241,0.3); +} + +.btn-panel-add:hover { + box-shadow: 0 5px 14px rgba(99,102,241,0.45); + transform: translateY(-1px); +} + +.btn-panel-import { + background: #f0fdf4; + color: #16a34a; + border: 1px solid #bbf7d0 !important; +} + +.btn-panel-import:hover { + background: #dcfce7; +} + +.right-panel-body { + flex: 1; + overflow-y: auto; + padding: 12px; + display: flex; + flex-direction: column; + gap: 8px; +} + +/* Panel Section Heading */ +.panel-section-title { + font-size: 11px; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.5px; + color: #9ca3af; + padding: 4px 2px 6px; + border-bottom: 1px solid #e5e7eb; + margin-top: 4px; +} + +/* Panel Empty State */ +.panel-empty { + text-align: center; + color: #aaa; + font-size: 13px; + padding: 40px 10px; +} + +/* ===== Data Card ===== */ +.data-card { + background: white; + border-radius: 12px; + padding: 12px 12px 10px; + box-shadow: 0 1px 4px rgba(0,0,0,0.07); + transition: box-shadow 0.2s; + cursor: pointer; +} + +.data-card:hover { + box-shadow: 0 3px 12px rgba(0,0,0,0.12); +} + +.data-card-main { + display: flex; + align-items: center; + gap: 10px; +} + +.data-card-icon { + width: 40px; + height: 40px; + border-radius: 10px; + display: flex; + align-items: center; + justify-content: center; + font-size: 20px; + flex-shrink: 0; +} + +.card-icon-ibadah { background: #fff7ed; } +.card-icon-miskin-out { background: #f0fdf4; } +.card-icon-miskin-in { background: #fef2f2; } + +.data-card-info { + flex: 1; + min-width: 0; +} + +.data-card-name { + font-size: 13px; + font-weight: 600; + color: #1e1e2e; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.data-card-sub { + font-size: 11px; + color: #6b7280; + margin-top: 2px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.data-card-badge { + font-size: 10px; + font-weight: 600; + padding: 2px 7px; + border-radius: 99px; + margin-top: 4px; + display: inline-block; +} + +.badge-green { background: #dcfce7; color: #16a34a; } +.badge-red { background: #fee2e2; color: #dc2626; } +.badge-blue { background: #dbeafe; color: #2563eb; } +.badge-orange { background: #ffedd5; color: #ea580c; } +.badge-yellow { background: #fef9c3; color: #ca8a04; } + +.data-card-actions { + display: flex; + gap: 6px; + flex-shrink: 0; + align-items: center; +} + +.btn-card-action { + width: 30px; + height: 30px; + border: none; + border-radius: 7px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + font-size: 12px; + transition: all 0.15s; +} + +.btn-card-edit { + background: #eff6ff; + color: #3b82f6; +} + +.btn-card-edit:hover { + background: #3b82f6; + color: white; +} + +.btn-card-delete { + background: #fef2f2; + color: #ef4444; +} + +.btn-card-delete:hover { + background: #ef4444; + color: white; +} + +/* Expandable card (miskin) */ +.data-card-expand { + overflow: hidden; + max-height: 0; + transition: max-height 0.3s ease, padding 0.2s; + border-top: 0px solid #f3f4f6; +} + +.data-card.expanded .data-card-expand { + max-height: 400px; + border-top: 1px solid #f3f4f6; + margin-top: 10px; + padding-top: 10px; +} + +.expand-row { + display: flex; + justify-content: space-between; + font-size: 12px; + color: #6b7280; + padding: 3px 0; +} + +.expand-row span:first-child { + font-weight: 500; + color: #374151; +} + +.btn-log-bantuan { + margin-top: 10px; + width: 100%; + padding: 8px; + background: linear-gradient(135deg, #6366f1, #4f46e5); + color: white; + border: none; + border-radius: 8px; + font-size: 12px; + font-weight: 600; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + gap: 6px; + transition: all 0.2s; +} + +.btn-log-bantuan:hover { + box-shadow: 0 4px 12px rgba(99,102,241,0.4); +} + +/* Log Bantuan Item */ +.log-item { + background: #f8f9fb; + border-radius: 8px; + padding: 10px 12px; + display: flex; + gap: 10px; + align-items: flex-start; +} + +.log-dot { + width: 8px; + height: 8px; + border-radius: 50%; + background: #6366f1; + flex-shrink: 0; + margin-top: 5px; +} + +.log-info { + flex: 1; +} + +.log-type { + font-size: 12px; + font-weight: 600; + color: #1e1e2e; +} + +.log-meta { + font-size: 11px; + color: #9ca3af; + margin-top: 2px; +} + +.log-keterangan { + font-size: 11px; + color: #6b7280; + margin-top: 3px; + font-style: italic; +} + +/* Popup Form */ +.popup-form { + display: flex; + flex-direction: column; + gap: 10px; + width: 200px; +} + +.popup-form label { + font-size: 12px; + font-weight: bold; + color: #555; +} + +.popup-form input[type="text"], +.popup-form input[type="number"] { + width: 100%; + padding: 6px; + border: 1px solid #ccc; + border-radius: 4px; +} + +.popup-form .radio-group { + display: flex; + gap: 10px; +} + +.popup-form button { + padding: 8px; + background-color: #007bff; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; + font-weight: bold; +} + +.popup-form button.btn-danger { + background-color: #dc3545; +} + +.popup-form button:hover { + opacity: 0.9; +} + +/* Unified Modal */ +.unified-modal { + display: none; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0,0,0,0.5); + z-index: 2000; + align-items: center; + justify-content: center; +} + +.unified-modal.show { + display: flex; +} + +.modal-content { + background-color: white; + border-radius: 12px; + width: 400px; + max-width: 90%; + box-shadow: 0 8px 30px rgba(0,0,0,0.2); + display: flex; + flex-direction: column; +} + +.modal-header { + padding: 15px; + border-bottom: 1px solid #eee; + display: flex; + justify-content: space-between; + align-items: center; +} + +.modal-header h3 { + font-size: 16px; + margin: 0; +} + +.modal-close { + font-size: 20px; + font-weight: bold; + cursor: pointer; + color: #888; +} + +.modal-close:hover { + color: #333; +} + +.modal-body { + padding: 15px; + display: flex; + flex-direction: column; + gap: 12px; +} + +.modal-body label { + font-size: 13px; + font-weight: 600; + color: #444; +} + +.modal-body input[type="text"], +.modal-body input[type="number"], +.modal-body input[type="date"], +.modal-body input[type="password"], +.modal-body select, +.modal-body textarea { + width: 100%; + padding: 8px; + border: 1px solid #ccc; + border-radius: 6px; + font-size: 14px; + font-family: inherit; +} + +.modal-footer { + padding: 15px; + border-top: 1px solid #eee; + display: flex; + justify-content: flex-end; + gap: 10px; +} + +.btn-save { + background: linear-gradient(135deg, #6366f1, #4f46e5); + color: white; + border: none; + padding: 8px 18px; + border-radius: 7px; + cursor: pointer; + font-weight: 600; + font-size: 13px; +} + +.btn-cancel { + background-color: #f8f9fa; + border: 1px solid #ddd; + padding: 8px 18px; + border-radius: 7px; + cursor: pointer; + font-size: 13px; +} + +.form-group { + display: flex; + flex-direction: column; + gap: 4px; +} + +/* Custom Cursor Tooltip */ +.custom-cursor-tooltip { + position: absolute; + display: none; + background-color: rgba(0, 0, 0, 0.75); + color: white; + padding: 6px 12px; + border-radius: 4px; + font-size: 13px; + font-weight: 500; + pointer-events: none; + z-index: 9999; + white-space: nowrap; + box-shadow: 0 2px 6px rgba(0,0,0,0.2); +} + +/* Sembunyikan default tooltip Leaflet Draw */ +.leaflet-draw-tooltip { + display: none !important; +} + +/* Sub-layer collapsible */ +.layer-group-item { + margin-bottom: 6px; +} + +.layer-group-item > .layer-group-header { + display: flex; + align-items: center; + justify-content: space-between; +} + +.layer-toggle-icon { + cursor: pointer; + padding: 2px 6px; + color: #666; + font-size: 11px; + border-radius: 4px; + transition: background 0.2s; + flex-shrink: 0; +} + +.layer-toggle-icon:hover { + background: #f0f0f0; + color: #333; +} + +.layer-toggle-icon i { + transition: transform 0.2s; +} + +.layer-toggle-icon.collapsed i { + transform: rotate(-90deg); +} + +.sub-layer-list { + padding-left: 18px; + margin-top: 4px; + border-left: 2px solid #eee; + overflow: hidden; + transition: max-height 0.2s ease; +} + +.sub-option { + font-size: 12px !important; + color: #555; + margin-bottom: 3px !important; +} + +/* ===== Emoji Marker (Pin Bubble) ===== */ +.emoji-marker { + display: flex; + flex-direction: column; + align-items: center; + pointer-events: auto; /* changed from none to allow click/drag */ +} + +.emoji-marker .bubble { + width: 38px; + height: 38px; + border-radius: 50% 50% 50% 0; + transform: rotate(-45deg); + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 3px 10px rgba(0,0,0,0.25); + border: 2px solid rgba(255,255,255,0.8); + animation: markerPop 0.25s cubic-bezier(0.175, 0.885, 0.32, 1.275) both; +} + +.emoji-marker .bubble span { + transform: rotate(45deg); + font-size: 18px; + line-height: 1; +} + +@keyframes markerPop { + 0% { transform: rotate(-45deg) scale(0); } + 100% { transform: rotate(-45deg) scale(1); } +} + +/* Warna bubble per tipe */ +.emoji-marker .bubble.ibadah { background: linear-gradient(135deg, #f97316, #ea580c); } +.emoji-marker .bubble.miskin-in { background: linear-gradient(135deg, #ef4444, #dc2626); } +.emoji-marker .bubble.miskin-out { background: linear-gradient(135deg, #22c55e, #16a34a); } + +/* ===== Toast Notification ===== */ +#toastContainer { + position: fixed; + bottom: 28px; + left: 50%; + transform: translateX(-50%); + z-index: 9999; + display: flex; + flex-direction: column; + align-items: center; + gap: 10px; + pointer-events: none; +} + +.toast { + display: flex; + align-items: center; + gap: 10px; + padding: 12px 20px; + border-radius: 12px; + font-size: 13px; + font-weight: 500; + color: white; + box-shadow: 0 6px 24px rgba(0,0,0,0.18); + backdrop-filter: blur(6px); + pointer-events: auto; + animation: toastSlideIn 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) both; + max-width: 340px; + text-align: center; +} + +.toast.hiding { + animation: toastSlideOut 0.3s ease forwards; +} + +.toast-success { background: linear-gradient(135deg, #22c55e, #16a34a); } +.toast-error { background: linear-gradient(135deg, #ef4444, #dc2626); } +.toast-info { background: linear-gradient(135deg, #6366f1, #4f46e5); } +.toast-warning { background: linear-gradient(135deg, #f59e0b, #d97706); } + +.toast-icon { font-size: 16px; flex-shrink: 0; } + +@keyframes toastSlideIn { + 0% { opacity: 0; transform: translateY(20px) scale(0.9); } + 100% { opacity: 1; transform: translateY(0) scale(1); } +} + +@keyframes toastSlideOut { + 0% { opacity: 1; transform: translateY(0) scale(1); } + 100% { opacity: 0; transform: translateY(10px) scale(0.95); } +} + +/* Auth Widget Styling */ +.auth-widget { + position: absolute; + top: 20px; + right: 80px; + z-index: 1000; + transition: right 0.3s cubic-bezier(0.4, 0, 0.2, 1); +} + +body.right-panel-open .auth-widget { + right: 400px; +} + +.btn-login { + background: linear-gradient(135deg, #6366f1, #4f46e5); + color: white; + border: none; + border-radius: 24px; + height: 48px; + padding: 0 24px; + font-size: 14px; + font-weight: 600; + cursor: pointer; + box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3); + display: flex; + align-items: center; + gap: 8px; + transition: all 0.2s ease; +} + +.btn-login:hover { + box-shadow: 0 6px 16px rgba(99, 102, 241, 0.45); + transform: translateY(-1px); +} + +.user-profile-pill { + background-color: white; + border-radius: 24px; + height: 48px; + padding: 0 8px 0 16px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + display: flex; + align-items: center; + gap: 12px; + border: 1px solid rgba(226, 232, 240, 0.8); + backdrop-filter: blur(10px); + background: rgba(255, 255, 255, 0.9); +} + +.user-profile-info { + display: flex; + flex-direction: column; +} + +.user-profile-name { + font-size: 12px; + font-weight: 700; + color: #1e1e2e; +} + +.user-profile-role { + font-size: 9px; + font-weight: 600; + color: #6366f1; + text-transform: uppercase; +} + +.btn-profile-logout { + width: 32px; + height: 32px; + border-radius: 50%; + border: none; + background: #f1f5f9; + color: #64748b; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s ease; +} + +.btn-profile-logout:hover { + background: #fee2e2; + color: #ef4444; +} + +/* User management table styling */ +#userManagementModal table th { + padding: 10px 12px; + font-weight: 600; + background-color: #f1f5f9; + border-bottom: 1px solid #cbd5e1; +} + +#userManagementModal table td { + padding: 10px 12px; + border-bottom: 1px solid #e2e8f0; +} + + +/* ============================================================ + DASHBOARD STYLES + ============================================================ */ + +#dashboardModal .modal-content { + width: min(920px, 96vw); + max-height: 90vh; + overflow: hidden; + display: flex; + flex-direction: column; +} + +#dashboardModal .modal-header { + background: linear-gradient(135deg, #1e1b4b 0%, #312e81 50%, #4338ca 100%); + border-radius: 12px 12px 0 0; + padding: 18px 20px; + flex-shrink: 0; +} + +#dashboardModal .modal-header h3 { + color: white; + font-size: 17px; + font-weight: 700; + letter-spacing: 0.3px; +} + +#dashboardModal .modal-close { + color: rgba(255,255,255,0.7); + font-size: 22px; + transition: color 0.2s; +} +#dashboardModal .modal-close:hover { color: white; } + +#dashboardBody { + flex: 1; + overflow-y: auto; + padding: 20px; + display: flex; + flex-direction: column; + gap: 20px; + background: #f1f5f9; +} + +.db-loading { + display: flex; + align-items: center; + justify-content: center; + gap: 14px; + padding: 60px 0; + color: #6b7280; + font-size: 14px; +} + +.db-spinner { + width: 28px; + height: 28px; + border: 3px solid #e2e8f0; + border-top-color: #6366f1; + border-radius: 50%; + animation: dbSpin 0.7s linear infinite; +} +@keyframes dbSpin { to { transform: rotate(360deg); } } + +.db-error { + text-align: center; + color: #ef4444; + padding: 40px; + font-size: 14px; +} + +.db-ibadah-header { + background: linear-gradient(135deg, #312e81, #4338ca); + border-radius: 14px; + padding: 16px 20px; + display: flex; + align-items: center; + gap: 16px; + color: white; + box-shadow: 0 4px 20px rgba(67,56,202,0.3); +} + +.db-ibadah-emoji { font-size: 36px; filter: drop-shadow(0 2px 4px rgba(0,0,0,0.2)); } +.db-ibadah-name { font-size: 18px; font-weight: 700; } +.db-ibadah-meta { font-size: 12px; color: rgba(255,255,255,0.75); margin-top: 3px; } + +.db-kpi-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); + gap: 14px; +} + +.db-kpi-card { + background: white; + border-radius: 16px; + padding: 18px 16px; + display: flex; + flex-direction: column; + align-items: center; + gap: 6px; + box-shadow: 0 2px 8px rgba(0,0,0,0.06); + transition: transform 0.2s, box-shadow 0.2s; + position: relative; + overflow: hidden; +} + +.db-kpi-card::before { + content: ''; + position: absolute; + top: 0; left: 0; right: 0; + height: 4px; + border-radius: 16px 16px 0 0; +} + +.kpi-ibadah::before { background: linear-gradient(90deg, #f97316, #ea580c); } +.kpi-miskin::before { background: linear-gradient(90deg, #ef4444, #dc2626); } +.kpi-jiwa::before { background: linear-gradient(90deg, #6366f1, #4f46e5); } +.kpi-log::before { background: linear-gradient(90deg, #22c55e, #16a34a); } + +.db-kpi-card:hover { transform: translateY(-3px); box-shadow: 0 8px 24px rgba(0,0,0,0.1); } + +.db-kpi-icon { font-size: 28px; line-height: 1; margin-bottom: 2px; } +.db-kpi-val { font-size: 32px; font-weight: 800; color: #1e1e2e; line-height: 1; } +.db-kpi-label { font-size: 11px; font-weight: 600; color: #6b7280; text-align: center; text-transform: uppercase; letter-spacing: 0.4px; } + +.db-section { + background: white; + border-radius: 14px; + padding: 16px 18px; + box-shadow: 0 2px 8px rgba(0,0,0,0.06); +} + +.db-section-title { + font-size: 13px; + font-weight: 700; + color: #374151; + margin-bottom: 12px; + letter-spacing: 0.2px; +} + +.db-coverage-labels { + display: flex; + justify-content: space-between; + font-size: 13px; + color: #374151; + flex-wrap: wrap; + gap: 6px; + margin-bottom: 8px; +} + +.db-progress-bar { + height: 12px; + background: #fee2e2; + border-radius: 99px; + overflow: hidden; +} + +.db-progress-fill { + height: 100%; + border-radius: 99px; + transition: width 0.8s cubic-bezier(0.4, 0, 0.2, 1); +} + +.db-charts-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: 14px; +} + +.db-chart-card { + background: white; + border-radius: 14px; + padding: 14px 16px; + box-shadow: 0 2px 8px rgba(0,0,0,0.06); +} + +.db-chart-wide { grid-column: 1 / -1; } + +.db-chart-title { + font-size: 11px; + font-weight: 700; + color: #374151; + margin-bottom: 12px; + text-transform: uppercase; + letter-spacing: 0.4px; +} + +.db-chart-card canvas { width: 100% !important; display: block; } + +.db-log-list { + display: flex; + flex-direction: column; + gap: 8px; + max-height: 260px; + overflow-y: auto; +} + +.db-log-item { + display: flex; + align-items: flex-start; + gap: 10px; + padding: 10px 12px; + background: #f8fafc; + border-radius: 10px; + transition: background 0.15s; +} + +.db-log-item:hover { background: #f1f5f9; } + +.db-log-dot { + width: 8px; height: 8px; + border-radius: 50%; + background: #6366f1; + flex-shrink: 0; + margin-top: 5px; +} + +.db-log-info { flex: 1; min-width: 0; } + +.db-log-main { + font-size: 12px; + font-weight: 600; + color: #1e1e2e; + display: flex; + gap: 6px; + flex-wrap: wrap; + align-items: center; +} + +.db-log-tipe { + background: #ede9fe; + color: #4f46e5; + padding: 1px 7px; + border-radius: 99px; + font-size: 11px; + font-weight: 700; +} + +.db-log-kk { color: #374151; } + +.db-log-meta { font-size: 10px; color: #9ca3af; margin-top: 3px; } + +.db-table-wrap { + overflow-x: auto; + border-radius: 8px; + border: 1px solid #e5e7eb; +} + +.db-table { width: 100%; border-collapse: collapse; font-size: 13px; } +.db-table thead tr { background: #f8fafc; } +.db-table th { padding: 10px 14px; text-align: left; font-size: 11px; font-weight: 700; color: #6b7280; text-transform: uppercase; letter-spacing: 0.4px; border-bottom: 1px solid #e5e7eb; } +.db-table td { padding: 10px 14px; color: #374151; border-bottom: 1px solid #f3f4f6; } +.db-table tbody tr:last-child td { border-bottom: none; } +.db-table tbody tr:hover td { background: #f8fafc; } + +.db-badge { + background: linear-gradient(135deg, #6366f1, #4f46e5); + color: white; + padding: 2px 9px; + border-radius: 99px; + font-size: 11px; + font-weight: 700; +} + +.db-empty { text-align: center; color: #aaa; font-size: 13px; padding: 20px; } + +/* ══════════════════════════════════════════════════════ + Dashboard Tab Bar (Integrasi Multi-Database) + ══════════════════════════════════════════════════════ */ + +.db-tab-bar { + display: flex; + gap: 4px; + padding: 12px 20px 0; + background: #f8fafc; + border-bottom: 2px solid #e5e7eb; + flex-wrap: wrap; +} + +.db-tab-btn { + padding: 8px 16px; + border: none; + background: transparent; + border-radius: 8px 8px 0 0; + font-size: 13px; + font-weight: 500; + color: #6b7280; + cursor: pointer; + transition: all 0.2s; + margin-bottom: -2px; + border-bottom: 2px solid transparent; + font-family: inherit; +} + +.db-tab-btn:hover { + background: #ede9fe; + color: #4f46e5; +} + +.db-tab-btn.active { + background: white; + color: #4f46e5; + border-bottom: 2px solid #4f46e5; + font-weight: 700; +} + +.db-tab-content { + padding: 20px; + overflow-y: auto; + max-height: calc(80vh - 100px); +} + +/* KPI card color override via CSS variable */ +.db-kpi-card { + --kpi-color: #6366f1; +} +.db-kpi-card .db-kpi-val { + color: var(--kpi-color, #6366f1); +} diff --git a/webgis-poverty-pontianak/assets/js/features/auth.js b/webgis-poverty-pontianak/assets/js/features/auth.js new file mode 100644 index 0000000..6d76deb --- /dev/null +++ b/webgis-poverty-pontianak/assets/js/features/auth.js @@ -0,0 +1,383 @@ +// --- Fitur Autentikasi dan Manajemen User (RBAC) --- + +(function() { + window.currentUser = null; + + // Elements + const authWidget = document.getElementById('authWidget'); + const loginModal = document.getElementById('loginModal'); + const loginUsernameInput = document.getElementById('loginUsername'); + const loginPasswordInput = document.getElementById('loginPassword'); + const loginSubmitBtn = document.getElementById('loginSubmitBtn'); + const loginErrorMsg = document.getElementById('loginErrorMsg'); + const closeLoginModal = document.getElementById('closeLoginModal'); + + // User Management Modal Elements + const userManagementModal = document.getElementById('userManagementModal'); + const closeUserManagementModal = document.getElementById('closeUserManagementModal'); + const menuUsersBtn = document.getElementById('menuUsers'); + const userTableBody = document.getElementById('userTableBody'); + const btnSaveUser = document.getElementById('btnSaveUser'); + const btnCancelUserEdit = document.getElementById('btnCancelUserEdit'); + const userFormTitle = document.getElementById('userFormTitle'); + + const manageUserId = document.getElementById('manageUserId'); + const manageUsername = document.getElementById('manageUsername'); + const managePassword = document.getElementById('managePassword'); + const manageRole = document.getElementById('manageRole'); + const manageIbadahId = document.getElementById('manageIbadahId'); + const manageIbadahGroup = document.getElementById('manageIbadahGroup'); + + // Startup Session Check + function checkSession() { + fetch('api/check_session.php') + .then(res => res.json()) + .then(data => { + if (data.status === 'success' && data.isLoggedIn) { + window.currentUser = data.data; + } else { + window.currentUser = null; + } + updateAuthUI(); + refreshAllLayers(); + }) + .catch(err => { + console.error("Session check failed:", err); + window.currentUser = null; + updateAuthUI(); + }); + } + + // Update UI based on logged-in state + function updateAuthUI() { + if (!authWidget) return; + + const dashboardBtn = document.getElementById('menuDashboard'); + + if (window.currentUser) { + // Logged In state + const roleLabel = window.currentUser.role === 'admin' ? 'Admin' : 'Pengelola'; + const extraLabel = window.currentUser.nama_ibadah ? ` - ${window.currentUser.nama_ibadah}` : ''; + + authWidget.innerHTML = ` + + `; + + document.getElementById('authLogoutBtn').addEventListener('click', logout); + + // Show Dashboard button for all logged-in users + if (dashboardBtn) dashboardBtn.style.display = 'flex'; + + // Show user management button in sidebar for Admin + const adminDivider = document.getElementById('sidebarAdminDivider'); + if (window.currentUser.role === 'admin') { + if (menuUsersBtn) menuUsersBtn.style.display = 'flex'; + if (adminDivider) adminDivider.style.display = 'block'; + } else { + if (menuUsersBtn) menuUsersBtn.style.display = 'none'; + if (adminDivider) adminDivider.style.display = 'none'; + } + } else { + // Logged Out state + authWidget.innerHTML = ` + + `; + document.getElementById('authLoginBtn').addEventListener('click', showLoginModal); + if (menuUsersBtn) menuUsersBtn.style.display = 'none'; + if (dashboardBtn) dashboardBtn.style.display = 'none'; + const adminDivider = document.getElementById('sidebarAdminDivider'); + if (adminDivider) adminDivider.style.display = 'none'; + } + } + + function refreshAllLayers() { + if (typeof loadSpbu === 'function') loadSpbu(); + if (typeof loadJalan === 'function') loadJalan(); + if (typeof loadParsil === 'function') loadParsil(); + if (typeof loadRumahIbadah === 'function') loadRumahIbadah(); + if (typeof loadPendudukMiskin === 'function') loadPendudukMiskin(); + if (window.refreshActivePanel) window.refreshActivePanel(); + } + + // Login Modals logic + function showLoginModal() { + loginUsernameInput.value = ''; + loginPasswordInput.value = ''; + loginErrorMsg.style.display = 'none'; + loginModal.classList.add('show'); + } + + function hideLoginModal() { + loginModal.classList.remove('show'); + } + + if (closeLoginModal) { + closeLoginModal.addEventListener('click', hideLoginModal); + } + + loginSubmitBtn.addEventListener('click', function() { + const username = loginUsernameInput.value.trim(); + const password = loginPasswordInput.value; + + if (!username || !password) { + loginErrorMsg.textContent = 'Username dan password wajib diisi'; + loginErrorMsg.style.display = 'block'; + return; + } + + fetch('api/login.php', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ username, password }) + }) + .then(res => res.json()) + .then(data => { + if (data.status === 'success') { + window.currentUser = data.data; + hideLoginModal(); + updateAuthUI(); + refreshAllLayers(); + showToast('Login berhasil', 'success'); + } else { + loginErrorMsg.textContent = data.message || 'Login gagal'; + loginErrorMsg.style.display = 'block'; + } + }) + .catch(err => { + console.error(err); + loginErrorMsg.textContent = 'Koneksi ke server terputus'; + loginErrorMsg.style.display = 'block'; + }); + }); + + function logout() { + fetch('api/logout.php') + .then(res => res.json()) + .then(data => { + window.currentUser = null; + updateAuthUI(); + refreshAllLayers(); + showToast('Logout berhasil', 'success'); + }) + .catch(err => { + console.error(err); + showToast('Gagal logout', 'error'); + }); + } + + // User Management Modal Logic + if (menuUsersBtn) { + menuUsersBtn.addEventListener('click', function() { + userManagementModal.classList.add('show'); + loadUsers(); + populateIbadahDropdown(); + resetUserForm(); + }); + } + + // Dashboard Button + const menuDashboardBtn = document.getElementById('menuDashboard'); + if (menuDashboardBtn) { + menuDashboardBtn.addEventListener('click', function() { + if (typeof window.openDashboard === 'function') window.openDashboard(); + }); + } + + if (closeUserManagementModal) { + closeUserManagementModal.addEventListener('click', function() { + userManagementModal.classList.remove('show'); + }); + } + + // Show/hide ibadah dropdown based on selected role in form + if (manageRole) { + manageRole.addEventListener('change', function() { + if (this.value === 'admin') { + manageIbadahGroup.style.display = 'none'; + manageIbadahId.value = ''; + } else { + manageIbadahGroup.style.display = 'flex'; + } + }); + } + + function populateIbadahDropdown() { + if (!manageIbadahId) return; + manageIbadahId.innerHTML = ''; + if (typeof ibadahDataList !== 'undefined') { + ibadahDataList.forEach(ib => { + const opt = document.createElement('option'); + opt.value = ib.id; + opt.textContent = `${ib.jenis || '🕌'} ${ib.nama}`; + manageIbadahId.appendChild(opt); + }); + } + } + + function loadUsers() { + if (!userTableBody) return; + userTableBody.innerHTML = 'Memuat user...'; + + fetch('api/users/read.php') + .then(res => res.json()) + .then(data => { + if (data.status === 'success') { + userTableBody.innerHTML = ''; + if (data.data.length === 0) { + userTableBody.innerHTML = 'Belum ada user'; + return; + } + data.data.forEach(user => { + const tr = document.createElement('tr'); + tr.style.borderBottom = '1px solid #e2e8f0'; + + const roleBadge = user.role === 'admin' + ? 'Admin' + : 'Pengelola'; + + tr.innerHTML = ` + ${escHtml(user.username)} + ${roleBadge} + ${escHtml(user.nama_ibadah)} + + + + + `; + userTableBody.appendChild(tr); + }); + } + }) + .catch(err => { + userTableBody.innerHTML = 'Gagal memuat user'; + }); + } + + window.editUser = function(user) { + userFormTitle.textContent = 'Edit Pengguna'; + manageUserId.value = user.id; + manageUsername.value = user.username; + managePassword.value = ''; // Password cleared in edit + manageRole.value = user.role; + + if (user.role === 'admin') { + manageIbadahGroup.style.display = 'none'; + manageIbadahId.value = ''; + } else { + manageIbadahGroup.style.display = 'flex'; + manageIbadahId.value = user.ibadah_id || ''; + } + + btnCancelUserEdit.style.display = 'inline-block'; + }; + + window.deleteUser = function(id) { + if (confirm('Apakah Anda yakin ingin menghapus user ini?')) { + fetch('api/users/delete.php', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id }) + }) + .then(res => res.json()) + .then(data => { + if (data.status === 'success') { + showToast(data.message, 'success'); + loadUsers(); + resetUserForm(); + } else { + showToast(data.message || 'Gagal menghapus user', 'error'); + } + }) + .catch(err => { + showToast('Koneksi terputus', 'error'); + }); + } + }; + + btnSaveUser.addEventListener('click', function() { + const id = manageUserId.value; + const username = manageUsername.value.trim(); + const password = managePassword.value; + const role = manageRole.value; + const ibadah_id = manageIbadahId.value; + + if (!username) { + alert('Username wajib diisi'); + return; + } + + if (!id && !password) { + alert('Password wajib diisi untuk user baru'); + return; + } + + const payload = { username, role, ibadah_id }; + if (id) payload.id = id; + if (password) payload.password = password; + + const endpoint = id ? 'api/users/update.php' : 'api/users/create.php'; + + fetch(endpoint, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload) + }) + .then(res => res.json()) + .then(data => { + if (data.status === 'success') { + showToast(data.message, 'success'); + loadUsers(); + resetUserForm(); + } else { + alert(data.message || 'Gagal menyimpan user'); + } + }) + .catch(err => { + alert('Koneksi terputus'); + }); + }); + + btnCancelUserEdit.addEventListener('click', resetUserForm); + + function resetUserForm() { + userFormTitle.textContent = 'Tambah User Baru'; + manageUserId.value = ''; + manageUsername.value = ''; + managePassword.value = ''; + manageRole.value = 'pengelola'; + manageIbadahGroup.style.display = 'flex'; + manageIbadahId.value = ''; + btnCancelUserEdit.style.display = 'none'; + } + + // Helper functions + function escHtml(str) { + if (!str) return ''; + return String(str).replace(/&/g,'&').replace(//g,'>').replace(/"/g,'"'); + } + + // Toast Notification helper + function showToast(message, type = 'success') { + if (typeof window.showToast === 'function') { + window.showToast(message, type); + return; + } + // Fallback alert + alert(message); + } + + // Run session check on initialization + checkSession(); +})(); diff --git a/webgis-poverty-pontianak/assets/js/features/dashboard.js b/webgis-poverty-pontianak/assets/js/features/dashboard.js new file mode 100644 index 0000000..83d8693 --- /dev/null +++ b/webgis-poverty-pontianak/assets/js/features/dashboard.js @@ -0,0 +1,468 @@ +// ===== Dashboard Feature (Terintegrasi) ===== +// Menghubungkan: webgis-poverty-pontianak, jalan, penduduk, spbu + +(function () { + 'use strict'; + + // ── State ────────────────────────────────────────────────────────────── + let dashboardData = null; + let activeTab = 'kemiskinan'; + + // ── Modal Element ────────────────────────────────────────────────────── + const modal = document.getElementById('dashboardModal'); + if (!modal) return; + + // ── Open / Close ─────────────────────────────────────────────────────── + window.openDashboard = function () { + modal.classList.add('show'); + if (!dashboardData) loadDashboard(); + else renderTab(activeTab); + }; + + window.closeDashboard = function () { + modal.classList.remove('show'); + }; + + document.getElementById('closeDashboardModal')?.addEventListener('click', window.closeDashboard); + modal.addEventListener('click', function (e) { + if (e.target === modal) window.closeDashboard(); + }); + + // ── Load Data ────────────────────────────────────────────────────────── + function loadDashboard() { + const body = document.getElementById('dashboardBody'); + body.innerHTML = ` +
+
+ Memuat data dashboard terintegrasi… +
`; + + fetch('api/dashboard/stats_extended.php') + .then(r => r.json()) + .then(data => { + if (data.status !== 'success') throw new Error(data.message || 'Gagal memuat'); + dashboardData = data; + renderShell(); + renderTab(activeTab); + }) + .catch(err => { + body.innerHTML = `
❌ Gagal memuat data: ${err.message}
`; + }); + } + + // ── Shell (tab bar + container) ──────────────────────────────────────── + function renderShell() { + const body = document.getElementById('dashboardBody'); + const tabs = [ + { id: 'kemiskinan', label: '🏠 Kemiskinan' }, + { id: 'jalan', label: '🛣️ Jalan' }, + { id: 'spbu', label: '⛽ SPBU' }, + { id: 'penduduk', label: '👥 Penduduk' }, + ]; + + body.innerHTML = ` +
+ ${tabs.map(t => ` + + `).join('')} +
+
`; + + document.getElementById('dbTabBar').addEventListener('click', function (e) { + const btn = e.target.closest('[data-tab]'); + if (!btn) return; + activeTab = btn.dataset.tab; + document.querySelectorAll('.db-tab-btn').forEach(b => b.classList.toggle('active', b.dataset.tab === activeTab)); + renderTab(activeTab); + }); + } + + // ── Route to tab ─────────────────────────────────────────────────────── + function renderTab(tab) { + const content = document.getElementById('dbTabContent'); + if (!content || !dashboardData) return; + if (tab === 'kemiskinan') renderKemiskinan(content, dashboardData.poverty); + else if (tab === 'jalan') renderJalan(content, dashboardData.jalan); + else if (tab === 'spbu') renderSpbu(content, dashboardData.spbu); + else if (tab === 'penduduk') renderPenduduk(content, dashboardData.penduduk); + } + + // ══════════════════════════════════════════════════════════════════════ + // Tab 1: Kemiskinan + // ══════════════════════════════════════════════════════════════════════ + function renderKemiskinan(el, d) { + const pctColor = d.pct_terurus >= 70 ? '#22c55e' : d.pct_terurus >= 40 ? '#f59e0b' : '#ef4444'; + + el.innerHTML = ` +
+
+
🕌
+
${d.total_ibadah}
+
Rumah Ibadah
+
+
+
🏠
+
${d.total_miskin}
+
KK Miskin
+
+
+
👥
+
${d.total_jiwa}
+
Total Jiwa
+
+
+
📋
+
${d.total_log}
+
Log Bantuan
+
+
+ + ${d.total_miskin > 0 ? ` +
+
📊 Cakupan Penanganan
+
+
+ ✅ Terurus: ${d.terurus} + ⚠️ Tidak Terurus: ${d.tidak_terurus} + ${d.pct_terurus}% +
+
+
+
+
+
` : ''} + +
+
+
📦 Kategori Bantuan
+ +
+
+
🎁 Tipe Bantuan
+ +
+
+
📅 Aktivitas Bantuan (6 Bulan)
+ +
+
`; + + setTimeout(() => { + drawPieChart('chartKategori', d.distribusi.kategori, ['#6366f1','#f59e0b','#22c55e','#ef4444','#06b6d4']); + drawPieChart('chartTipe', d.distribusi.tipe_bantuan, ['#4f46e5','#16a34a','#dc2626','#d97706','#0891b2','#7c3aed']); + drawBarChart('chartBulan', d.distribusi.per_bulan); + }, 50); + } + + // ══════════════════════════════════════════════════════════════════════ + // Tab 2: Jalan + // ══════════════════════════════════════════════════════════════════════ + function renderJalan(el, d) { + const panjangKm = (d.total_panjang_m / 1000).toFixed(2); + const luasHa = (d.total_luas_m2 / 10000).toFixed(2); + + el.innerHTML = ` +
+
+
🛣️
+
${d.total_jalan}
+
Ruas Jalan
+
+
+
📏
+
${panjangKm} km
+
Total Panjang
+
+
+
🗂️
+
${d.total_parsil}
+
Persil Tanah
+
+
+
📐
+
${luasHa} ha
+
Total Luas Persil
+
+
+ +
+
+
🛣️ Jalan per Status
+ +
+
+
📋 Persil per Kepemilikan
+ +
+
+ + ${Object.keys(d.per_status).length > 0 ? ` +
+
🛣️ Rincian Status Jalan
+
+ + + + ${Object.entries(d.per_status).map(([k,v]) => ` + + `).join('')} + +
StatusJumlah Ruas
${esc(k)}${v}
+
+
` : '
Belum ada data jalan tersimpan di database.
'}`; + + setTimeout(() => { + drawPieChart('chartStatusJalan', d.per_status, ['#3b82f6','#0ea5e9','#38bdf8']); + drawPieChart('chartKepemilikan', d.per_kepemilikan, ['#8b5cf6','#a78bfa','#c4b5fd','#7c3aed']); + }, 50); + } + + // ══════════════════════════════════════════════════════════════════════ + // Tab 3: SPBU + // ══════════════════════════════════════════════════════════════════════ + function renderSpbu(el, d) { + el.innerHTML = ` +
+
+
+
${d.total_spbu}
+
Total SPBU
+
+
+
🕐
+
${d.buka_24_jam}
+
Buka 24 Jam
+
+
+
🕙
+
${d.tidak_24_jam}
+
Tidak 24 Jam
+
+
+ +
+
+
⏰ Status Operasional
+ +
+
+ + ${d.list.length > 0 ? ` +
+
📍 Daftar SPBU
+
+ + + + + + + + + + + + ${d.list.map((s, i) => ` + + + + + + + `).join('')} + +
#Nama SPBUNomor WAOperasionalKoordinat
${i+1}${esc(s.nama_spbu)}${esc(s.nomor_wa)}${s.buka_24_jam == 1 + ? '24 Jam' + : 'Terbatas'}${parseFloat(s.latitude).toFixed(5)}, ${parseFloat(s.longitude).toFixed(5)}
+
+
` : '
Belum ada data SPBU tersimpan di database.
'}`; + + setTimeout(() => { + drawPieChart('chartSpbuOps', { 'Buka 24 Jam': d.buka_24_jam, 'Tidak 24 Jam': d.tidak_24_jam }, ['#22c55e','#ef4444']); + }, 50); + } + + // ══════════════════════════════════════════════════════════════════════ + // Tab 4: Penduduk (Choropleth Kecamatan) + // ══════════════════════════════════════════════════════════════════════ + function renderPenduduk(el, d) { + const maxDensity = Math.max(...d.kecamatan.map(k => k.density)); + + el.innerHTML = ` +
+
+
🗺️
+
${d.total_kecamatan}
+
Kecamatan
+
+
+
📊
+
${d.rata_density.toLocaleString('id-ID')}
+
Rata-rata Kepadatan (jiwa/km²)
+
+
+
🏆
+
${esc(d.terpadat)}
+
Kecamatan Terpadat
+
+
+ +
+
👥 Kepadatan Penduduk per Kecamatan (jiwa/km²)
+ ${d.kecamatan.map(k => { + const pct = ((k.density / maxDensity) * 100).toFixed(1); + const color = k.density >= 8 ? '#ef4444' : k.density >= 5 ? '#f59e0b' : '#22c55e'; + return ` +
+
+ ${esc(k.nama)} + ${k.density.toLocaleString('id-ID')} jiwa/km² +
+
+
+
+
`; + }).join('')} +
+ 🟢 <5 Rendah + 🟡 5–8 Sedang + 🔴 ≥8 Tinggi +
+
+ +
+
+
📊 Kepadatan per Kecamatan
+ +
+
`; + + setTimeout(() => { + drawDensityBar('chartDensity', d.kecamatan); + }, 50); + } + + // ══════════════════════════════════════════════════════════════════════ + // Chart Helpers + // ══════════════════════════════════════════════════════════════════════ + function drawPieChart(canvasId, dataObj, colors) { + const canvas = document.getElementById(canvasId); + if (!canvas) return; + const entries = Object.entries(dataObj || {}).filter(([,v]) => v > 0); + const ctx = canvas.getContext('2d'); + ctx.clearRect(0, 0, canvas.width, canvas.height); + + if (entries.length === 0) { + ctx.fillStyle = '#aaa'; ctx.font = '13px Inter'; ctx.textAlign = 'center'; + ctx.fillText('Belum ada data', canvas.width/2, canvas.height/2); + return; + } + + const labels = entries.map(([k]) => k); + const values = entries.map(([,v]) => v); + const total = values.reduce((a,b) => a+b, 0); + const cx = canvas.width/2, cy = canvas.height * 0.42; + const r = Math.min(cx, cy) * 0.72; + + let startAngle = -Math.PI/2; + values.forEach((v,i) => { + const slice = (v/total)*2*Math.PI; + ctx.beginPath(); ctx.moveTo(cx, cy); + ctx.arc(cx, cy, r, startAngle, startAngle+slice); + ctx.closePath(); + ctx.fillStyle = colors[i % colors.length]; + ctx.fill(); ctx.strokeStyle='#fff'; ctx.lineWidth=2; ctx.stroke(); + startAngle += slice; + }); + + ctx.fillStyle='#333'; ctx.font='bold 15px Inter'; ctx.textAlign='center'; + ctx.fillText(total, cx, cy+5); + + const legY = cy+r+14, legItemW = 92, perRow = Math.floor(canvas.width/legItemW); + labels.forEach((lbl,i) => { + const row=Math.floor(i/perRow), col=i%perRow; + const lx=(canvas.width - Math.min(labels.length,perRow)*legItemW)/2 + col*legItemW; + const ly=legY+row*17; + ctx.fillStyle=colors[i%colors.length]; ctx.fillRect(lx,ly,10,10); + ctx.fillStyle='#555'; ctx.font='10px Inter'; ctx.textAlign='left'; + const shortLbl = lbl.length>11 ? lbl.slice(0,10)+'…' : lbl; + ctx.fillText(`${shortLbl} (${values[i]})`, lx+13, ly+9); + }); + } + + function drawBarChart(canvasId, perBulan) { + const canvas = document.getElementById(canvasId); + if (!canvas) return; + const ctx = canvas.getContext('2d'); + ctx.clearRect(0, 0, canvas.width, canvas.height); + if (!perBulan || perBulan.length === 0) { + ctx.fillStyle='#aaa'; ctx.font='13px Inter'; ctx.textAlign='center'; + ctx.fillText('Belum ada data bantuan', canvas.width/2, canvas.height/2); + return; + } + const padL=36, padR=12, padT=12, padB=28; + const W=canvas.width-padL-padR, H=canvas.height-padT-padB; + const values=perBulan.map(d=>parseInt(d.cnt)), maxVal=Math.max(...values,1); + const barW=W/perBulan.length*0.6, gap=W/perBulan.length; + ctx.strokeStyle='#e5e7eb'; ctx.lineWidth=1; + for (let i=0;i<=4;i++){ + const y=padT+H-(i/4)*H; + ctx.beginPath(); ctx.moveTo(padL,y); ctx.lineTo(padL+W,y); ctx.stroke(); + ctx.fillStyle='#9ca3af'; ctx.font='9px Inter'; ctx.textAlign='right'; + ctx.fillText(Math.round((i/4)*maxVal), padL-4, y+3); + } + perBulan.forEach((d,i)=>{ + const bh=(parseInt(d.cnt)/maxVal)*H, bx=padL+i*gap+(gap-barW)/2, by=padT+H-bh; + const grad=ctx.createLinearGradient(0,by,0,padT+H); + grad.addColorStop(0,'#6366f1'); grad.addColorStop(1,'#a5b4fc'); + ctx.fillStyle=grad; + ctx.beginPath(); + if(ctx.roundRect) ctx.roundRect(bx,by,barW,bh,[4,4,0,0]); else ctx.rect(bx,by,barW,bh); + ctx.fill(); + ctx.fillStyle='#4f46e5'; ctx.font='bold 10px Inter'; ctx.textAlign='center'; + ctx.fillText(d.cnt, bx+barW/2, by-4); + const ml=d.bulan ? d.bulan.slice(5)+'/'+d.bulan.slice(2,4) : ''; + ctx.fillStyle='#6b7280'; ctx.font='9px Inter'; + ctx.fillText(ml, bx+barW/2, padT+H+14); + }); + } + + function drawDensityBar(canvasId, kecamatan) { + const canvas = document.getElementById(canvasId); + if (!canvas) return; + const ctx = canvas.getContext('2d'); + ctx.clearRect(0, 0, canvas.width, canvas.height); + const padL=130, padR=50, padT=12, padB=12; + const W=canvas.width-padL-padR, H=canvas.height-padT-padB; + const maxVal=Math.max(...kecamatan.map(k=>k.density),1); + const barH=Math.floor(H/kecamatan.length)-6; + + kecamatan.forEach((k,i) => { + const bw=(k.density/maxVal)*W; + const by=padT+i*(barH+6); + const color=k.density>=8?'#ef4444':k.density>=5?'#f59e0b':'#22c55e'; + // Label kecamatan + ctx.fillStyle='#374151'; ctx.font='11px Inter'; ctx.textAlign='right'; + ctx.fillText(k.nama, padL-6, by+barH/2+4); + // Bar + ctx.fillStyle=color+'33'; + ctx.fillRect(padL, by, W, barH); + const grad=ctx.createLinearGradient(padL,0,padL+bw,0); + grad.addColorStop(0,color); grad.addColorStop(1,color+'99'); + ctx.fillStyle=grad; + if(ctx.roundRect) ctx.roundRect(padL,by,bw,barH,[0,4,4,0]); else ctx.fillRect(padL,by,bw,barH); + ctx.fill(); + // Value + ctx.fillStyle=color; ctx.font='bold 11px Inter'; ctx.textAlign='left'; + ctx.fillText(k.density.toFixed(3), padL+bw+5, by+barH/2+4); + }); + } + + // ── Utility ─────────────────────────────────────────────────────────── + function esc(str) { + if (!str) return ''; + return String(str).replace(/&/g,'&').replace(//g,'>').replace(/"/g,'"'); + } + +})(); diff --git a/webgis-poverty-pontianak/assets/js/features/geojson.js b/webgis-poverty-pontianak/assets/js/features/geojson.js new file mode 100644 index 0000000..7c4fab9 --- /dev/null +++ b/webgis-poverty-pontianak/assets/js/features/geojson.js @@ -0,0 +1,181 @@ +// --- Fitur Import GeoJSON --- + +const fileGeoJson = document.getElementById('fileGeoJson'); +let geoJsonLayers = {}; +let geoJsonCounter = 0; + +window.toggleGeoJsonMenu = function() { + const list = document.getElementById('geoJsonFileList'); + const icon = document.getElementById('geoJsonToggleIcon'); + if (list.style.display === 'none') { + list.style.display = 'block'; + icon.className = 'fas fa-minus'; + } else { + list.style.display = 'none'; + icon.className = 'fas fa-plus'; + } +}; + +// Cek apakah fitur GeoJSON ini terlihat seperti data penduduk miskin +function isMiskinFeature(feature) { + if (!feature || !feature.geometry || feature.geometry.type !== 'Point') return false; + const props = feature.properties || {}; + const keys = Object.keys(props).map(k => k.toLowerCase()); + // Dianggap data miskin jika punya properti nama (dan bukan ibadah atau spbu) + const hasNama = keys.some(k => ['nama', 'name', 'penduduk'].includes(k)); + const isIbadah = keys.some(k => ['jenis', 'radius', 'alamat'].includes(k)); + const isSpbu = keys.some(k => ['alamat_spbu', 'is_24_jam'].includes(k)); + return hasNama && !isIbadah && !isSpbu; +} + +fileGeoJson.addEventListener('change', function(e) { + const file = e.target.files[0]; + if (!file) return; + + const reader = new FileReader(); + reader.onload = function(event) { + try { + const geoJsonData = JSON.parse(event.target.result); + const fileName = file.name; + + // Pisahkan fitur menjadi dua kelompok: miskin dan non-miskin + const features = geoJsonData.type === 'FeatureCollection' + ? geoJsonData.features + : [geoJsonData]; + + const miskinFeatures = features.filter(f => isMiskinFeature(f)); + const otherFeatures = features.filter(f => !isMiskinFeature(f)); + + // ---- Proses fitur miskin: Simpan ke DB, lalu tampilkan seperti penduduk miskin ---- + if (miskinFeatures.length > 0) { + const bulkData = miskinFeatures.map(f => { + const props = f.properties || {}; + const coords = f.geometry.coordinates; + return { + nama: props.nama || props.name || props.penduduk || 'Data Impor', + kategori_bantuan: props.kategori_bantuan || props.kategori || props.bantuan || 'Makan', + jumlah_jiwa: parseInt(props.jumlah_jiwa || props.jumlah || props.jiwa || 1, 10) || 1, + lat: parseFloat(coords[1]), + lng: parseFloat(coords[0]) + }; + }); + + fetch('api/penduduk_miskin/bulk_create.php', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(bulkData) + }) + .then(res => res.json()) + .then(data => { + if (data.status === 'success') { + // Reload layer penduduk miskin agar marker tampil dengan edit/hapus/log bantuan + if (typeof loadPendudukMiskin === 'function') { + loadPendudukMiskin(); + } + if (typeof window.refreshActivePanel === 'function') { + window.refreshActivePanel(); + } + showToast(data.message || 'Data berhasil diimpor ke layer Penduduk Miskin.', 'success'); + } else { + showToast(data.message || 'Gagal menyimpan data miskin.', 'error'); + } + }) + .catch(err => { + console.error(err); + showToast('Gagal terhubung ke server saat menyimpan data miskin.', 'error'); + }); + } + + // ---- Proses fitur non-miskin: Render sebagai layer GeoJSON biasa ---- + if (otherFeatures.length > 0) { + const layerId = 'gj_' + (++geoJsonCounter); + const individualLayer = L.featureGroup(); + + const otherGeoJson = { + type: 'FeatureCollection', + features: otherFeatures + }; + + L.geoJSON(otherGeoJson, { + pointToLayer: function(feature, latlng) { + const props = feature.properties || {}; + let emoji = props.emoji; + + if (!emoji) { + const text = JSON.stringify(props).toLowerCase(); + if (text.includes('spbu')) emoji = '⛽'; + else if (text.includes('masjid')) emoji = '🕌'; + else if (text.includes('gereja')) emoji = '⛪'; + else if (text.includes('vihara')) emoji = '🪷'; + else if (text.includes('pura')) emoji = '🛕'; + else if (text.includes('kelenteng')) emoji = '🏮'; + else emoji = '📍'; + } + + let cls = 'miskin-out'; + if (emoji === '⛽') cls = 'spbu-24'; + else if (['🕌','⛪','🛕','🪷','🏮'].includes(emoji)) cls = 'ibadah'; + + const icon = L.divIcon({ + className: '', + html: `
${emoji}
`, + iconSize: [38, 38], + iconAnchor: [19, 38], + popupAnchor: [0, -40] + }); + + return L.marker(latlng, { icon: icon }); + }, + onEachFeature: function(feature, layer) { + if (feature.properties) { + let popupContent = '

Informasi Feature

    '; + for (let key in feature.properties) { + popupContent += `
  • ${key}: ${feature.properties[key]}
  • `; + } + popupContent += '
'; + layer.bindPopup(popupContent); + } + }, + style: function(feature) { + return { + color: (feature.properties && feature.properties.color) || '#3388ff', + weight: 2, + fillOpacity: 0.4 + }; + } + }).addTo(individualLayer); + + individualLayer.addTo(map); + geoJsonLayers[layerId] = individualLayer; + + // Tambahkan checkbox ke UI + const container = document.getElementById('geoJsonLayersContainer'); + const label = document.createElement('label'); + label.className = 'layer-option'; + label.innerHTML = ` ${fileName}`; + + label.querySelector('input').addEventListener('change', function(e) { + if (e.target.checked) { + map.addLayer(geoJsonLayers[layerId]); + } else { + map.removeLayer(geoJsonLayers[layerId]); + } + }); + + container.appendChild(label); + + if (miskinFeatures.length === 0) { + showToast('File GeoJSON berhasil dimuat!', 'success'); + } + } + + // Reset input file agar bisa import file yang sama + fileGeoJson.value = ''; + + } catch (error) { + showToast('Gagal memproses file GeoJSON. Pastikan format valid.', 'error'); + console.error(error); + } + }; + reader.readAsText(file); +}); diff --git a/webgis-poverty-pontianak/assets/js/features/geolocation.js b/webgis-poverty-pontianak/assets/js/features/geolocation.js new file mode 100644 index 0000000..aa6179b --- /dev/null +++ b/webgis-poverty-pontianak/assets/js/features/geolocation.js @@ -0,0 +1,30 @@ +// --- Fitur Geolocation --- + +// Tambahkan tombol di dalam wadah zoom control +const geoBtn = document.createElement('button'); +geoBtn.className = 'custom-layer-btn'; +geoBtn.style.position = 'relative'; +geoBtn.style.top = '0'; +geoBtn.style.left = '0'; +geoBtn.style.right = 'auto'; +geoBtn.innerHTML = ''; +geoBtn.title = 'Lokasi Saya'; +document.querySelector('.custom-zoom-control').appendChild(geoBtn); + +let userMarker = null; + +geoBtn.addEventListener('click', function() { + map.locate({setView: true, maxZoom: 16}); +}); + +map.on('locationfound', function(e) { + if (userMarker) { + map.removeLayer(userMarker); + } + userMarker = L.marker(e.latlng).addTo(map) + .bindPopup("Anda berada di sini!").openPopup(); +}); + +map.on('locationerror', function(e) { + alert("Gagal mendapatkan lokasi Anda."); +}); diff --git a/webgis-poverty-pontianak/assets/js/features/kemiskinan.js b/webgis-poverty-pontianak/assets/js/features/kemiskinan.js new file mode 100644 index 0000000..f977216 --- /dev/null +++ b/webgis-poverty-pontianak/assets/js/features/kemiskinan.js @@ -0,0 +1,916 @@ +// --- Fitur Pemetaan Kemiskinan --- + +// Emoji per jenis ibadah +const IBADAH_EMOJI_MAP = { + 'Masjid': '🕌', + 'Gereja': '⛪', + 'Pura': '🛕', + 'Vihara': '🪷', + 'Kelenteng': '🏮', +}; + +// Emoji Bubble Icon builder +function makeIbadahIcon(jenis) { + const emot = IBADAH_EMOJI_MAP[jenis] || '🕌'; + return L.divIcon({ + className: '', + html: `
${emot}
`, + iconSize: [38, 38], + iconAnchor: [19, 38], + popupAnchor: [0, -40] + }); +} + +function makeMiskinIcon(inRadius) { + const cls = inRadius ? 'miskin-in' : 'miskin-out'; + return L.divIcon({ + className: '', + html: `
🏠
`, + iconSize: [38, 38], + iconAnchor: [19, 38], + popupAnchor: [0, -40] + }); +} + + +let ibadahDataList = []; +let miskinMarkerList = []; // Simpan referensi marker untuk update warna + +// Helper: cek apakah koordinat (lat, lng) berada dalam radius ibadah pengelola yang login +function isInMyIbadahRadius(lat, lng) { + if (!window.currentUser || window.currentUser.role !== 'pengelola') return true; // admin selalu bisa + const myIbadahId = window.currentUser.ibadah_id; + if (!myIbadahId) return false; + const ib = ibadahDataList.find(i => i.id == myIbadahId); + if (!ib) return false; + const dist = L.latLng(lat, lng).distanceTo(L.latLng(ib.lat, ib.lng)); + return dist <= ib.radius; +} +window.isInMyIbadahRadius = isInMyIbadahRadius; + +let isResizing = false; +let resizingCircle = null; +let resizingIbadah = null; + +map.on('mousemove', function(e) { + if (isResizing && resizingCircle && resizingIbadah) { + const center = resizingCircle.getLatLng(); + const newRadius = center.distanceTo(e.latlng); + resizingCircle.setRadius(newRadius); + resizingIbadah.radius = newRadius; + + // Update data radius di marker juga + rumahIbadahLayer.eachLayer(function(layer) { + if (layer.ibadahData && layer.ibadahData.id === resizingIbadah.id && layer instanceof L.Marker) { + layer.ibadahData.radius = newRadius; + } + }); + + updateSemuaWarnaMiskin(); + } +}); + +map.on('mouseup', function(e) { + if (isResizing) { + isResizing = false; + map.dragging.enable(); + if (resizingIbadah) { + updateIbadah(resizingIbadah.id, resizingIbadah.nama, resizingIbadah.jenis, resizingIbadah.alamat, resizingIbadah.radius, resizingIbadah.lat, resizingIbadah.lng); + } + resizingCircle = null; + resizingIbadah = null; + } +}); + +// --- Rumah Ibadah --- +function loadRumahIbadah() { + rumahIbadahLayer.clearLayers(); + ibadahDataList = []; + fetch('api/rumah_ibadah/read.php') + .then(res => res.json()) + .then(data => { + if (data.status === 'success' && data.data) { + ibadahDataList = data.data; + data.data.forEach(item => { + addIbadahMarker(item); + }); + updateSemuaWarnaMiskin(); + } + if (window.refreshActivePanel) window.refreshActivePanel(); + }); +} + +function addIbadahMarker(item) { + const lat = parseFloat(item.lat); + const lng = parseFloat(item.lng); + const radius = parseFloat(item.radius) || 100; // fallback if invalid + + if (isNaN(lat) || isNaN(lng)) return; + + const isAdmin = !!(window.currentUser && window.currentUser.role === 'admin'); + + const marker = L.marker([lat, lng], { icon: makeIbadahIcon(item.jenis), draggable: isAdmin }); + + // Lingkaran radius + const circle = L.circle([lat, lng], { + radius: radius, + color: '#ff7800', + weight: 2, + fillColor: '#ff7800', + fillOpacity: 0.2 + }); + + circle.on('mousemove', function(e) { + if (!isAdmin || isResizing) return; + const center = circle.getLatLng(); + const radius = circle.getRadius(); + const dist = center.distanceTo(e.latlng); + + const metersPerPixel = map.distance(map.containerPointToLatLng([0,0]), map.containerPointToLatLng([0,1])); + const tolerance = Math.max(radius * 0.1, metersPerPixel * 15); // toleransi 15px atau 10% + + if (Math.abs(dist - radius) <= tolerance) { + if (circle._path) circle._path.style.cursor = 'ew-resize'; + circle.nearEdge = true; + } else { + if (circle._path) circle._path.style.cursor = 'pointer'; + circle.nearEdge = false; + } + }); + + circle.on('mousedown', function(e) { + if (isAdmin && circle.nearEdge) { + map.dragging.disable(); + isResizing = true; + resizingCircle = circle; + resizingIbadah = item; + L.DomEvent.stopPropagation(e); + } + }); + + marker.ibadahData = item; + marker.circleLayer = circle; + + const d = item; + const emot = IBADAH_EMOJI_MAP[d.jenis] || '🕌'; + let actionButtons = ''; + if (isAdmin) { + actionButtons = ` +
+ + +
+ `; + } + const popupContent = ` +
+

${emot} ${d.nama}

+

Jenis: ${d.jenis || 'Masjid'}

+

Alamat: ${d.alamat}

+

Radius: ${d.radius} m

+ ${actionButtons} +
+ `; + marker.bindPopup(popupContent); + + marker.on('dragend', function(e) { + const newPos = marker.getLatLng(); + circle.setLatLng(newPos); + item.lat = newPos.lat; + item.lng = newPos.lng; + // Update ke DB + updateIbadah(item.id, item.nama, item.jenis, item.alamat, item.radius, newPos.lat, newPos.lng); + }); + + rumahIbadahLayer.addLayer(circle); + rumahIbadahLayer.addLayer(marker); +} + +// Konteks Menu untuk Tambah Penduduk Miskin (klik kanan peta) +map.on('contextmenu', function(e) { + + const isAdminOrPengelola = !!(window.currentUser && (window.currentUser.role === 'admin' || window.currentUser.role === 'pengelola')); + if (!isAdminOrPengelola) return; + + const canAddHere = isInMyIbadahRadius(e.latlng.lat, e.latlng.lng); + + if (!canAddHere) { + // Pengelola: lokasi di luar radius ibadahnya + const warnContent = ` + + `; + L.popup().setLatLng(e.latlng).setContent(warnContent).openOn(map); + return; + } + + const popupContent = ` + + `; + L.popup().setLatLng(e.latlng).setContent(popupContent).openOn(map); +}); + +// Map Click -> Form Add Rumah Ibadah +map.on('click', function(e) { + if (window.currentAddMode === 'rumah_ibadah') { + const lat = e.latlng.lat; + const lng = e.latlng.lng; + + // Reverse Geocoding + fetch(`https://nominatim.openstreetmap.org/reverse?format=json&lat=${lat}&lon=${lng}`) + .then(res => res.json()) + .then(geoData => { + const alamat = geoData.display_name || 'Alamat tidak ditemukan'; + const bodyHTML = ` +
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ `; + + openModal("Tambah Rumah Ibadah", bodyHTML, function() { + window.saveNewIbadah(lat, lng, 'modalIbadahNama', 'modalIbadahJenis', 'modalIbadahAlamat', 'modalIbadahRadius'); + }); + + window.deactivateAddMode(); + }) + .catch(err => { + // Tetap buka modal meskipun gagal mendapatkan alamat + const alamat = ''; + const bodyHTML = ` +
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ `; + + openModal("Tambah Rumah Ibadah", bodyHTML, function() { + window.saveNewIbadah(lat, lng, 'modalIbadahNama', 'modalIbadahJenis', 'modalIbadahAlamat', 'modalIbadahRadius'); + }); + + window.deactivateAddMode(); + }); + } +}); + +window.saveNewIbadah = function(lat, lng, namaId, jenisId, alamatId, radiusId) { + const nama = document.getElementById(namaId).value; + const jenis = document.getElementById(jenisId).value; + const alamat = document.getElementById(alamatId).value; + const radius = document.getElementById(radiusId).value; + + if (!nama) { alert("Nama Rumah Ibadah harus diisi!"); return; } + + fetch('api/rumah_ibadah/create.php', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ nama, jenis, alamat, radius, lat, lng }) + }) + .then(res => res.json()) + .then(data => { + if(data.status === 'success') { closeModal(); loadRumahIbadah(); } + else { alert(data.message); } + }); +}; + +window.openEditIbadahModal = function(id) { + let d = null; + rumahIbadahLayer.eachLayer(function(layer) { + if (layer.ibadahData && layer.ibadahData.id == id) d = layer.ibadahData; + }); + if (!d) return; + + const jenisOpts = ['Masjid','Gereja','Pura','Vihara','Kelenteng'].map(j => + `` + ).join(''); + + const bodyHTML = ` +
+ + +
+
+ + +
+
+ + +
+
+ + +
+ `; + map.closePopup(); + openModal("Edit Rumah Ibadah", bodyHTML, function() { + window.saveEditIbadah(d.id, d.lat, d.lng, 'editIbadahNama', 'editIbadahJenis', 'editIbadahAlamat', 'editIbadahRadius'); + }); +}; + +window.previewRadius = function(id, newRadius) { + rumahIbadahLayer.eachLayer(function(layer) { + // layer ini bisa marker atau circle, kita cek yang punya circleLayer (marker) + if (layer.ibadahData && layer.ibadahData.id === id && layer.circleLayer) { + layer.circleLayer.setRadius(parseFloat(newRadius)); + layer.ibadahData.radius = parseFloat(newRadius); + updateSemuaWarnaMiskin(); // Update warna miskin real-time + } + }); +}; + +window.saveEditIbadah = function(id, lat, lng, namaId, jenisId, alamatId, radiusId) { + const nama = document.getElementById(namaId).value; + const jenis = document.getElementById(jenisId).value; + const alamat = document.getElementById(alamatId).value; + const radius = document.getElementById(radiusId).value; + updateIbadah(id, nama, jenis, alamat, radius, lat, lng); +}; + +function updateIbadah(id, nama, jenis, alamat, radius, lat, lng) { + fetch('api/rumah_ibadah/update.php', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id, nama, jenis, alamat, radius, lat, lng }) + }).then(res => res.json()).then(data => { + if(data.status === 'success') { + if (typeof closeModal === 'function') closeModal(); + map.closePopup(); + loadRumahIbadah(); + } + }); +} + +window.deleteIbadah = function(id) { + openConfirmModal("Yakin hapus rumah ibadah ini?", function() { + fetch('api/rumah_ibadah/delete.php', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id }) + }).then(res => res.json()).then(data => { + if(data.status === 'success') { map.closePopup(); loadRumahIbadah(); } + }); + }); +}; + + +// --- Penduduk Miskin --- +function loadPendudukMiskin() { + pendudukMiskinLayer.clearLayers(); + miskinMarkerList = []; + fetch('api/penduduk_miskin/read.php') + .then(res => res.json()) + .then(data => { + if (data.status === 'success' && data.data) { + data.data.forEach(item => { + addMiskinMarker(item); + }); + updateSemuaWarnaMiskin(); + } + if (window.refreshActivePanel) window.refreshActivePanel(); + }); +} + +function addMiskinMarker(item) { + const lat = parseFloat(item.lat); + const lng = parseFloat(item.lng); + if (isNaN(lat) || isNaN(lng)) return; + + // Pengelola hanya bisa manage marker yang ada di dalam radius ibadahnya + const isAdminOrPengelola = !!(window.currentUser && (window.currentUser.role === 'admin' || window.currentUser.role === 'pengelola')); + const canManage = isAdminOrPengelola && isInMyIbadahRadius(lat, lng); + + const marker = L.marker([lat, lng], { icon: makeMiskinIcon(false), draggable: canManage }); + marker.miskinData = item; + + const d = item; + let actionButtons = ''; + if (canManage) { + actionButtons = ` + + + `; + } + + let photoLinksHtml = ''; + if (d.foto_rumah) { + photoLinksHtml += ` + `; + } + if (d.foto_kk) { + photoLinksHtml += ` + `; + } + + const popupContent = ` +
+

🏠 ${d.nama}

+

Bantuan: ${d.kategori_bantuan}

+

Jiwa: ${d.jumlah_jiwa || '-'}

+ ${photoLinksHtml} +
+ + ${actionButtons} +
+
+ `; + marker.bindPopup(popupContent); + + marker.on('dragend', function(e) { + const newPos = marker.getLatLng(); + item.lat = newPos.lat; + item.lng = newPos.lng; + updateSemuaWarnaMiskin(); // Update warna segera + // Simpan ke DB + fetch('api/penduduk_miskin/update.php', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(item) + }); + }); + + miskinMarkerList.push(marker); + pendudukMiskinLayer.addLayer(marker); +} + +window.formAddMiskin = function(lat, lng) { + map.closePopup(); + const bodyHTML = ` +
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ `; + openModal("Tambah Penduduk Miskin", bodyHTML, function() { + window.saveNewMiskin(lat, lng); + }); +}; + +window.saveNewMiskin = function(lat, lng) { + const nama = document.getElementById('miskinNama').value; + const kategori_bantuan = document.getElementById('miskinKategori').value; + const jumlah_jiwa = document.getElementById('miskinJiwa').value; + const fotoRumahInput = document.getElementById('miskinFotoRumah'); + const fotoKKInput = document.getElementById('miskinFotoKK'); + + if (!nama) { alert('Nama kepala keluarga harus diisi!'); return; } + + const formData = new FormData(); + formData.append('nama', nama); + formData.append('kategori_bantuan', kategori_bantuan); + formData.append('jumlah_jiwa', jumlah_jiwa); + formData.append('lat', lat); + formData.append('lng', lng); + if (fotoRumahInput.files[0]) formData.append('foto_rumah', fotoRumahInput.files[0]); + if (fotoKKInput.files[0]) formData.append('foto_kk', fotoKKInput.files[0]); + + fetch('api/penduduk_miskin/create.php', { + method: 'POST', + body: formData + }) + .then(res => res.json()) + .then(data => { + if(data.status === 'success') { + closeModal(); + loadPendudukMiskin(); + } else { alert(data.message); } + }); +}; + +window.openEditMiskinModal = function(id) { + let d = null; + pendudukMiskinLayer.eachLayer(function(layer) { + if (layer.miskinData && layer.miskinData.id == id) d = layer.miskinData; + }); + if (!d) return; + + const bodyHTML = ` +
+ + +
+
+ + +
+
+ + +
+
+ + + ${d.foto_rumah ? ` +
+ + Foto Rumah + ❌ File gambar rusak atau tidak ditemukan + +
Upload baru untuk mengganti
+
` : ''} +
+
+ + + ${d.foto_kk ? ` +
+ + Foto KK + ❌ File gambar rusak atau tidak ditemukan + +
Upload baru untuk mengganti
+
` : ''} +
+ `; + map.closePopup(); + openModal("Edit Penduduk Miskin", bodyHTML, function() { + window.saveEditMiskin(d.id, d.lat, d.lng, 'editMiskinNama', 'editMiskinKategori', 'editMiskinJiwa'); + }); +}; + +window.saveEditMiskin = function(id, lat, lng, namaId, kategoriId, jiwaId) { + const nama = document.getElementById(namaId).value; + const kategori_bantuan = document.getElementById(kategoriId).value; + const jumlah_jiwa = jiwaId ? document.getElementById(jiwaId).value : 1; + const fotoRumahInput = document.getElementById('editMiskinFotoRumah'); + const fotoKKInput = document.getElementById('editMiskinFotoKK'); + + const formData = new FormData(); + formData.append('id', id); + formData.append('nama', nama); + formData.append('kategori_bantuan', kategori_bantuan); + formData.append('jumlah_jiwa', jumlah_jiwa); + formData.append('lat', lat); + formData.append('lng', lng); + if (fotoRumahInput.files[0]) formData.append('foto_rumah', fotoRumahInput.files[0]); + if (fotoKKInput.files[0]) formData.append('foto_kk', fotoKKInput.files[0]); + + fetch('api/penduduk_miskin/update.php', { + method: 'POST', + body: formData + }).then(res => res.json()).then(data => { + if(data.status === 'success') { closeModal(); loadPendudukMiskin(); } + }); +}; + +window.deleteMiskin = function(id) { + openConfirmModal("Yakin hapus penduduk miskin ini?", function() { + fetch('api/penduduk_miskin/delete.php', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ id }) + }).then(res => res.json()).then(data => { + if(data.status === 'success') { map.closePopup(); loadPendudukMiskin(); } + }); + }); +}; + +// Logika dinamis warna: Merah jika di dalam salah satu radius Rumah Ibadah, Hijau jika di luar +function updateSemuaWarnaMiskin() { + miskinMarkerList.forEach(marker => { + let inRadius = false; + const pLatlng = L.latLng(marker.miskinData.lat, marker.miskinData.lng); + + for (let i = 0; i < ibadahDataList.length; i++) { + const ibadah = ibadahDataList[i]; + const iLatlng = L.latLng(ibadah.lat, ibadah.lng); + const dist = pLatlng.distanceTo(iLatlng); // meter + + if (dist <= ibadah.radius) { + inRadius = true; + break; // Jika sudah masuk satu radius, langsung merah + } + } + + if (inRadius) { + marker.setIcon(makeMiskinIcon(true)); + } else { + marker.setIcon(makeMiskinIcon(false)); + } + }); +} + +// ========================== +// ===== Import Feature ===== +// ========================== +let parsedImportData = []; + +window.openImportMiskinModal = function() { + parsedImportData = []; // Reset data + + const bodyHTML = ` +
+ + +
+ Format CSV yang didukung:
+ Header minimal berisi: nama, kategori_bantuan (atau kategori), jumlah_jiwa, lat, lng.
+ Pemisah: Koma (,), Titik Koma (;), atau Tab. +
+
+ + + `; + + map.closePopup(); + + openModal("Impor Penduduk Miskin", bodyHTML, function() { + if (parsedImportData.length === 0) { + showToast('Silakan pilih file terlebih dahulu atau pastikan data valid.', 'warning'); + return; + } + + // Kirim data ke API bulk_create.php + fetch('api/penduduk_miskin/bulk_create.php', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(parsedImportData) + }) + .then(res => res.json()) + .then(data => { + if (data.status === 'success') { + closeModal(); + loadPendudukMiskin(); + showToast(data.message, 'success'); + } else { + showToast(data.message || 'Gagal mengimpor data.', 'error'); + } + }) + .catch(err => { + console.error(err); + showToast('Terjadi kesalahan saat menghubungi server.', 'error'); + }); + }); + + // Register file input listener + document.getElementById('importMiskinFile').addEventListener('change', handleImportFileChange); +}; + +function parseCSV(text) { + const lines = text.split(/\r?\n/); + if (lines.length < 2) return []; + + const firstLine = lines[0]; + let delimiter = ','; + if (firstLine.includes(';')) delimiter = ';'; + else if (firstLine.includes('\t')) delimiter = '\t'; + + const headers = firstLine.split(delimiter).map(h => h.trim().replace(/^["']|["']$/g, '').toLowerCase()); + + const results = []; + for (let i = 1; i < lines.length; i++) { + const line = lines[i].trim(); + if (!line) continue; + + let fields = []; + let currentField = ''; + let insideQuote = false; + + for (let j = 0; j < line.length; j++) { + const char = line[j]; + if (char === '"' || char === "'") { + insideQuote = !insideQuote; + } else if (char === delimiter && !insideQuote) { + fields.push(currentField.trim()); + currentField = ''; + } else { + currentField += char; + } + } + fields.push(currentField.trim()); + + fields = fields.map(f => f.replace(/^["']|["']$/g, '')); + + const row = {}; + headers.forEach((header, index) => { + row[header] = fields[index] || ''; + }); + results.push(row); + } + return results; +} + +function handleImportFileChange(e) { + const file = e.target.files[0]; + const previewContainer = document.getElementById('importPreviewContainer'); + const previewCount = document.getElementById('importPreviewCount'); + const previewTableBody = document.getElementById('importPreviewTableBody'); + const errorMsg = document.getElementById('importErrorMsg'); + + if (!file) { + previewContainer.style.display = 'none'; + parsedImportData = []; + return; + } + + errorMsg.style.display = 'none'; + previewContainer.style.display = 'none'; + previewTableBody.innerHTML = ''; + parsedImportData = []; + + const reader = new FileReader(); + reader.onload = function(event) { + try { + const text = event.target.result; + let rawData = []; + + if (file.name.endsWith('.csv')) { + rawData = parseCSV(text); + } else if (file.name.endsWith('.json') || file.name.endsWith('.geojson')) { + const json = JSON.parse(text); + if (json.type === 'FeatureCollection' && Array.isArray(json.features)) { + rawData = json.features.map(f => { + const props = f.properties || {}; + const coords = f.geometry && f.geometry.coordinates; + return { + nama: props.nama || props.name || props.penduduk || '', + kategori_bantuan: props.kategori_bantuan || props.kategori || props.bantuan || 'Makan', + jumlah_jiwa: props.jumlah_jiwa || props.jumlah || props.jiwa || 1, + lat: coords ? coords[1] : (props.lat || props.latitude), + lng: coords ? coords[0] : (props.lng || props.longitude) + }; + }); + } else if (Array.isArray(json)) { + rawData = json; + } else { + throw new Error("Format JSON tidak didukung."); + } + } + + if (rawData.length === 0) { + errorMsg.textContent = "File kosong atau format tidak didukung."; + errorMsg.style.display = 'block'; + return; + } + + const validRows = []; + let invalidCount = 0; + + rawData.forEach(row => { + const nama = row.nama || row.name || row.penduduk || row['nama lengkap'] || row.fullname || ''; + const kategori_bantuan = row.kategori_bantuan || row.kategori || row.bantuan || row['kategori bantuan'] || 'Makan'; + const jumlah_jiwa = parseInt(row.jumlah_jiwa || row.jumlah || row.jiwa || row['jumlah jiwa'] || 1, 10) || 1; + const lat = parseFloat(row.lat || row.latitude || row.y); + const lng = parseFloat(row.lng || row.longitude || row.long || row.x); + + const isValid = !isNaN(lat) && !isNaN(lng) && lat !== 0 && lng !== 0 && nama.trim() !== ''; + + if (isValid) { + validRows.push({ nama, kategori_bantuan, jumlah_jiwa, lat, lng }); + } else { + invalidCount++; + } + }); + + parsedImportData = validRows; + + if (validRows.length === 0) { + errorMsg.textContent = "Tidak ditemukan data valid (pastikan kolom nama_kk/nama, lat, dan lng terisi)."; + errorMsg.style.display = 'block'; + return; + } + + validRows.forEach(row => { + const tr = document.createElement('tr'); + tr.style.borderBottom = '1px solid #e2e8f0'; + tr.innerHTML = ` + ${row.nama} + ${row.kategori_bantuan} + ${row.jumlah_jiwa} + ${row.lat.toFixed(5)}, ${row.lng.toFixed(5)} + `; + previewTableBody.appendChild(tr); + }); + + previewCount.textContent = validRows.length; + previewContainer.style.display = 'block'; + + const statusEl = document.getElementById('importPreviewStatus'); + if (statusEl) { + if (invalidCount > 0) { + statusEl.innerHTML = ` ${invalidCount} baris tidak valid diabaikan`; + } else { + statusEl.innerHTML = ` Semua data valid`; + } + } + + } catch (err) { + console.error(err); + errorMsg.textContent = "Gagal memproses file. Pastikan format file sesuai."; + errorMsg.style.display = 'block'; + } + }; + reader.readAsText(file); +} + +// Initial Load +loadRumahIbadah(); +loadPendudukMiskin(); diff --git a/webgis-poverty-pontianak/assets/js/map.js b/webgis-poverty-pontianak/assets/js/map.js new file mode 100644 index 0000000..c660d8f --- /dev/null +++ b/webgis-poverty-pontianak/assets/js/map.js @@ -0,0 +1,242 @@ +// Inisialisasi Peta +// Koordinat awal: [-0.0263, 109.3425] (Pontianak) +const map = L.map('map', { zoomControl: false }).setView([-0.0263, 109.3425], 13); + +// ===== Toast Notification ===== +window.showToast = function(message, type = 'success', duration = 3500) { + const icons = { success: '✅', error: '❌', info: 'ℹ️', warning: '⚠️' }; + const container = document.getElementById('toastContainer'); + if (!container) return; + + const toast = document.createElement('div'); + toast.className = `toast toast-${type}`; + toast.innerHTML = `${icons[type] || 'ℹ️'}${message}`; + container.appendChild(toast); + + setTimeout(() => { + toast.classList.add('hiding'); + toast.addEventListener('animationend', () => toast.remove()); + }, duration); +}; + +// Custom Zoom Control Logic +document.getElementById('zoomInBtn').addEventListener('click', function() { map.zoomIn(); }); +document.getElementById('zoomOutBtn').addEventListener('click', function() { map.zoomOut(); }); + +// Base Map dari OpenStreetMap +L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { + attribution: '© OpenStreetMap contributors' +}).addTo(map); + +// Inisialisasi FeatureGroups untuk masing-masing layer +const rumahIbadahLayer = L.featureGroup().addTo(map); +const pendudukMiskinLayer = L.featureGroup().addTo(map); +const geoJsonLayer = L.featureGroup().addTo(map); + +const searchInput = document.getElementById('searchInput'); +const searchClear = document.getElementById('searchClear'); + +searchInput.addEventListener('focus', function() { + if (typeof window.deactivateAddMode === 'function') window.deactivateAddMode(); +}); + +searchInput.addEventListener('input', function() { + const val = this.value.toLowerCase(); + if (val.length > 0) { + searchClear.style.visibility = 'visible'; + window.showSearchResults(val); + } else { + searchClear.style.visibility = 'hidden'; + document.getElementById('searchResults').style.display = 'none'; + } +}); + +searchClear.addEventListener('click', function() { + searchInput.value = ''; + searchClear.style.visibility = 'hidden'; + document.getElementById('searchResults').style.display = 'none'; + searchInput.focus(); +}); + +window.showSearchResults = function(query) { + const resultsContainer = document.getElementById('searchResults'); + resultsContainer.innerHTML = ''; + let results = []; + + + + if (typeof rumahIbadahLayer !== 'undefined') { + rumahIbadahLayer.eachLayer(layer => { + if (layer.ibadahData && layer.ibadahData.nama && layer.ibadahData.nama.toLowerCase().includes(query)) { + if(layer instanceof L.Marker) { + results.push({ type: 'Rumah Ibadah', nama: layer.ibadahData.nama, layer: layer }); + } + } + }); + } + + if (results.length === 0) { + resultsContainer.innerHTML = '
Tidak ada hasil
'; + } else { + results.forEach(res => { + const item = document.createElement('div'); + item.style.padding = '10px 15px'; + item.style.cursor = 'pointer'; + item.style.borderBottom = '1px solid #eee'; + item.style.fontSize = '14px'; + item.innerHTML = `${res.type}: ${res.nama}`; + item.addEventListener('mouseenter', () => item.style.backgroundColor = '#f8f9fa'); + item.addEventListener('mouseleave', () => item.style.backgroundColor = 'white'); + item.addEventListener('click', () => { + if (res.layer instanceof L.Marker) { + map.setView(res.layer.getLatLng(), 17); + } else if (res.layer.getBounds) { + map.fitBounds(res.layer.getBounds()); + } + res.layer.openPopup(); + resultsContainer.style.display = 'none'; + }); + resultsContainer.appendChild(item); + }); + } + resultsContainer.style.display = 'block'; +}; + +// UI Logic: Custom Layer Control Toggle +const layerBtn = document.getElementById('layerBtn'); +const layerPanel = document.getElementById('layerPanel'); + +layerBtn.addEventListener('click', function() { + if (typeof window.deactivateAddMode === 'function') window.deactivateAddMode(); + layerPanel.style.display = layerPanel.style.display === 'block' ? 'none' : 'block'; +}); + +// Sembunyikan layer panel saat klik di peta +map.on('click', function() { + layerPanel.style.display = 'none'; +}); + + +// Logic untuk Toggle Layer Visibility +document.getElementById('layerRumahIbadah').addEventListener('change', function(e) { + e.target.checked ? map.addLayer(rumahIbadahLayer) : map.removeLayer(rumahIbadahLayer); +}); +document.getElementById('layerMiskin').addEventListener('change', function(e) { + e.target.checked ? map.addLayer(pendudukMiskinLayer) : map.removeLayer(pendudukMiskinLayer); +}); + +// --- Sub-layer Toggle (expand/collapse) --- +window.toggleSubLayer = function(subId, iconEl) { + const sub = document.getElementById(subId); + if (!sub) return; + const isHidden = sub.style.display === 'none'; + sub.style.display = isHidden ? '' : 'none'; + iconEl.classList.toggle('collapsed', !isHidden); +}; + +// --- Sub-layer Filter --- +window.applySubFilter = function(type) { + + if (type === 'miskin') { + const checked = [...document.querySelectorAll('.sub-miskin:checked')].map(el => el.value); + pendudukMiskinLayer.eachLayer(layer => { + if (!layer.miskinData) return; + if (checked.includes(layer.miskinData.kategori_bantuan)) { + layer.getElement && layer.getElement() && (layer.getElement().style.display = ''); + } else { + layer.getElement && layer.getElement() && (layer.getElement().style.display = 'none'); + } + }); + } +}; + +// --- Modal Logic --- +const unifiedModal = document.getElementById('unifiedModal'); +const modalTitle = document.getElementById('modalTitle'); +const modalBody = document.getElementById('modalBody'); + +window.openModal = function(title, bodyHTML, saveCallback) { + modalTitle.textContent = title; + modalBody.innerHTML = bodyHTML; + unifiedModal.classList.add('show'); + + // Ambil elemen tombol save terbaru dari DOM + const currentSaveBtn = document.getElementById('modalSaveBtn'); + + // Clone untuk menghapus semua event listener lama + const newSaveBtn = currentSaveBtn.cloneNode(true); + currentSaveBtn.parentNode.replaceChild(newSaveBtn, currentSaveBtn); + + newSaveBtn.addEventListener('click', saveCallback); +}; + +window.closeModal = function() { + unifiedModal.classList.remove('show'); +}; + +const confirmModal = document.getElementById('confirmModal'); +const confirmMessage = document.getElementById('confirmMessage'); + +window.openConfirmModal = function(msg, confirmCallback) { + confirmMessage.textContent = msg; + confirmModal.classList.add('show'); + + const currentYesBtn = document.getElementById('confirmYesBtn'); + const newYesBtn = currentYesBtn.cloneNode(true); + currentYesBtn.parentNode.replaceChild(newYesBtn, currentYesBtn); + + newYesBtn.addEventListener('click', function() { + confirmModal.classList.remove('show'); + confirmCallback(); + }); +}; + +window.closeConfirmModal = function() { + confirmModal.classList.remove('show'); +}; + +// --- Action Menu Logic (replaced by left sidebar) --- + +window.currentAddMode = null; // 'rumah_ibadah' atau 'miskin_click' + +window.activateAddMode = function(mode) { + // Toggle: jika mode yang sama diklik lagi, batalkan + if (window.currentAddMode === mode) { + window.deactivateAddMode(); + return; + } + + window.currentAddMode = mode; + + // Tooltip + const tooltips = { + 'rumah_ibadah': 'Klik untuk Tambah Rumah Ibadah' + }; + if (window.cursorTooltip && tooltips[mode]) window.cursorTooltip.textContent = tooltips[mode]; + + // Ubah kursor map menjadi crosshair + document.getElementById('map').style.cursor = 'crosshair'; +}; + +window.deactivateAddMode = function() { + window.currentAddMode = null; + document.getElementById('map').style.cursor = ''; + if (window.cursorTooltip) window.cursorTooltip.style.display = 'none'; +}; + +// --- Custom Tooltip Cursor --- +window.cursorTooltip = document.createElement('div'); +window.cursorTooltip.className = 'custom-cursor-tooltip'; +document.body.appendChild(window.cursorTooltip); + +// Gunakan document-level mousemove agar selalu terpicu +// bahkan saat Leaflet Draw overlay aktif menangkap event map +document.addEventListener('mousemove', function(e) { + if (window.currentAddMode) { + window.cursorTooltip.style.display = 'block'; + window.cursorTooltip.style.left = e.pageX + 15 + 'px'; + window.cursorTooltip.style.top = e.pageY + 15 + 'px'; + } else { + window.cursorTooltip.style.display = 'none'; + } +}); diff --git a/webgis-poverty-pontianak/assets/js/panel.js b/webgis-poverty-pontianak/assets/js/panel.js new file mode 100644 index 0000000..7eeab4b --- /dev/null +++ b/webgis-poverty-pontianak/assets/js/panel.js @@ -0,0 +1,465 @@ +// ===== Panel Management ===== +// Mengelola Left Sidebar Toggle + Right Panel + Layer Control + +(function () { + // ---- Konstanta Jenis Ibadah ---- + const IBADAH_EMOJI = { + 'Masjid': '🕌', + 'Gereja': '⛪', + 'Pura': '🛕', + 'Vihara': '🪷', + 'Kelenteng': '🏮', + }; + window.IBADAH_EMOJI = IBADAH_EMOJI; + + // ---- State ---- + let activePanel = null; + + // ---- Elements ---- + const sidebarToggleBtn = document.getElementById('sidebarToggleBtn'); + const sidebarToggleIcon = document.getElementById('sidebarToggleIcon'); + const leftSidebar = document.getElementById('leftSidebar'); + const rightPanel = document.getElementById('rightPanel'); + const rightPanelTitle = document.getElementById('rightPanelTitle'); + const rightPanelActions = document.getElementById('rightPanelActions'); + const rightPanelBody = document.getElementById('rightPanelBody'); + const rightPanelClose = document.getElementById('rightPanelClose'); + + // ---- Sidebar Toggle ---- + sidebarToggleBtn.addEventListener('click', function () { + const isOpen = leftSidebar.style.display !== 'none'; + if (isOpen) { + leftSidebar.style.display = 'none'; + sidebarToggleBtn.classList.remove('open'); + sidebarToggleIcon.className = 'fas fa-chevron-right'; + } else { + leftSidebar.style.display = 'flex'; + sidebarToggleBtn.classList.add('open'); + sidebarToggleIcon.className = 'fas fa-chevron-left'; + } + }); + + // ---- Sidebar Buttons ---- + document.querySelectorAll('.sidebar-btn').forEach(btn => { + btn.addEventListener('click', function () { + const panel = this.dataset.panel; + if (activePanel === panel) { + closePanel(); + } else { + openPanel(panel); + } + }); + }); + + rightPanelClose.addEventListener('click', closePanel); + + // ---- Open / Close Panel ---- + function openPanel(panel) { + if (typeof window.deactivateAddMode === 'function') window.deactivateAddMode(); + activePanel = panel; + rightPanel.classList.add('open'); + document.body.classList.add('right-panel-open'); + document.querySelectorAll('.sidebar-btn').forEach(b => b.classList.remove('active')); + const activeBtn = document.querySelector(`.sidebar-btn[data-panel="${panel}"]`); + if (activeBtn) activeBtn.classList.add('active'); + renderPanel(panel); + } + + function closePanel() { + if (typeof window.deactivateAddMode === 'function') window.deactivateAddMode(); + activePanel = null; + rightPanel.classList.remove('open'); + document.body.classList.remove('right-panel-open'); + document.querySelectorAll('.sidebar-btn').forEach(b => b.classList.remove('active')); + } + + window.refreshActivePanel = function () { + if (activePanel && activePanel !== 'layer') renderPanel(activePanel); + }; + + // ---- Render Panel by Type ---- + function renderPanel(type) { + rightPanelBody.innerHTML = '
Memuat data...
'; + rightPanelActions.innerHTML = ''; + + switch (type) { + case 'ibadah': renderIbadahPanel(); break; + case 'miskin': renderMiskinPanel(); break; + } + } + + + + // ========================== + // ===== Ibadah Panel ======= + // ========================== + function renderIbadahPanel() { + rightPanelTitle.textContent = '🕌 Rumah Ibadah'; + const isAdmin = !!(window.currentUser && window.currentUser.role === 'admin'); + if (isAdmin) { + rightPanelActions.innerHTML = ` + `; + document.getElementById('btnPanelAddIbadah').addEventListener('click', () => { + window.activateAddMode('rumah_ibadah'); + }); + } else { + rightPanelActions.innerHTML = ''; + } + + const items = []; + rumahIbadahLayer.eachLayer(l => { + if (l.ibadahData && l instanceof L.Marker) items.push(l.ibadahData); + }); + + if (!items.length) { + rightPanelBody.innerHTML = '
Belum ada data rumah ibadah
'; + return; + } + + rightPanelBody.innerHTML = ''; + items.forEach(d => { + const emoji = IBADAH_EMOJI[d.jenis] || '🕌'; + const card = document.createElement('div'); + card.className = 'data-card'; + let actionButtons = ''; + if (isAdmin) { + actionButtons = ` +
+ + +
+ `; + } + card.innerHTML = ` +
+
${emoji}
+
+
${escHtml(d.nama)}
+
${escHtml(d.jenis || 'Masjid')} • 📡 ${d.radius} m
+
+ ${actionButtons} +
`; + if (isAdmin) { + card.querySelector('.btn-card-edit').addEventListener('click', (e) => { e.stopPropagation(); openEditIbadahModal(d.id); }); + card.querySelector('.btn-card-delete').addEventListener('click', (e) => { e.stopPropagation(); deleteIbadah(d.id); }); + } + card.addEventListener('click', () => flyToIbadah(d.id)); + rightPanelBody.appendChild(card); + }); + } + + function flyToIbadah(id) { + rumahIbadahLayer.eachLayer(l => { + if (l.ibadahData && l.ibadahData.id == id && l instanceof L.Marker) { + map.setView(l.getLatLng(), 17); l.openPopup(); + } + }); + } + + // ========================== + // ===== Miskin Panel ======= + // ========================== + function renderMiskinPanel() { + rightPanelTitle.textContent = '🏠 Penduduk Miskin'; + const canManage = !!(window.currentUser && (window.currentUser.role === 'admin' || window.currentUser.role === 'pengelola')); + if (canManage) { + const isPengelola = window.currentUser.role === 'pengelola'; + const addLabel = isPengelola + ? ' Tambah (dalam radius)' + : ' Tambah'; + rightPanelActions.innerHTML = ` + + `; + + document.getElementById('btnPanelTambahMiskin').addEventListener('click', () => { + window.currentAddMode = 'miskin_click'; + document.getElementById('map').style.cursor = 'crosshair'; + if (window.cursorTooltip) { + const tipText = isPengelola + ? 'Klik di dalam radius ibadah Anda untuk tambah penduduk' + : 'Klik di peta untuk tentukan lokasi penduduk miskin'; + window.cursorTooltip.textContent = tipText; + } + }); + + document.getElementById('btnPanelImportMiskin').addEventListener('click', () => { + if (typeof window.openImportMiskinModal === 'function') { + window.openImportMiskinModal(); + } else { + alert('Fitur impor belum siap.'); + } + }); + } else { + rightPanelActions.innerHTML = ''; + } + + const all = []; + pendudukMiskinLayer.eachLayer(l => { if (l.miskinData) all.push(l.miskinData); }); + + if (!all.length) { + rightPanelBody.innerHTML = '
Belum ada data penduduk miskin
'; + return; + } + + const inRadius = (d) => { + if (typeof ibadahDataList === 'undefined') return false; + for (const ib of ibadahDataList) { + const dist = L.latLng(d.lat, d.lng).distanceTo(L.latLng(ib.lat, ib.lng)); + if (dist <= ib.radius) return true; + } + return false; + }; + + rightPanelBody.innerHTML = ''; + + const terurusItems = all.filter(d => inRadius(d)); + const tidakItems = all.filter(d => !inRadius(d)); + + if (terurusItems.length) { + const h1 = document.createElement('div'); + h1.className = 'panel-section-title'; + h1.innerHTML = `✅ Terurus (${terurusItems.length})`; + rightPanelBody.appendChild(h1); + terurusItems.forEach(d => rightPanelBody.appendChild(buildMiskinCard(d, true))); + } + + if (tidakItems.length) { + const h2 = document.createElement('div'); + h2.className = 'panel-section-title'; + h2.innerHTML = `⚠️ Tidak Terurus (${tidakItems.length})`; + rightPanelBody.appendChild(h2); + tidakItems.forEach(d => rightPanelBody.appendChild(buildMiskinCard(d, false))); + } + } + + function buildMiskinCard(d, terurus) { + // Pengelola hanya boleh edit/hapus penduduk yang dalam radius ibadahnya + const isPengelolaOrAdmin = !!(window.currentUser && (window.currentUser.role === 'admin' || window.currentUser.role === 'pengelola')); + const canManage = isPengelolaOrAdmin && (typeof window.isInMyIbadahRadius === 'function' + ? window.isInMyIbadahRadius(d.lat, d.lng) + : true); + const iconCls = terurus ? 'card-icon-miskin-in' : 'card-icon-miskin-out'; + const badge = d.kategori_bantuan === 'Makan' + ? 'Bantuan Makan' + : 'Pemberdayaan'; + + const card = document.createElement('div'); + card.className = 'data-card'; + card.dataset.miskinId = d.id; + + let actionButtons = ''; + if (canManage) { + actionButtons = ` +
+ + +
+ `; + } + + let fotoHtml = ''; + if (d.foto_rumah || d.foto_kk) { + fotoHtml += `
`; + if (d.foto_rumah) { + fotoHtml += ` +
+ Foto Rumah + + + +
`; + } + if (d.foto_kk) { + fotoHtml += ` +
+ Foto KK + + + +
`; + } + fotoHtml += `
`; + } + + card.innerHTML = ` +
+
🏠
+
+
${escHtml(d.nama)}
+
👨‍👩‍👧 ${d.jumlah_jiwa || '-'} jiwa
+ ${badge} +
+ ${actionButtons} +
+
+
Kepala Keluarga${escHtml(d.nama)}
+
Kategori Bantuan${escHtml(d.kategori_bantuan)}
+
Jumlah Jiwa${d.jumlah_jiwa || '-'}
+
Status${terurus ? 'Terurus ✅' : 'Tidak Terurus ⚠️'}
+ ${fotoHtml} + +
`; + + if (canManage) { + card.querySelector('.btn-card-edit').addEventListener('click', (e) => { e.stopPropagation(); openEditMiskinModal(d.id); }); + card.querySelector('.btn-card-delete').addEventListener('click', (e) => { e.stopPropagation(); deleteMiskin(d.id); }); + } + card.querySelector('.btn-log-bantuan').addEventListener('click', (e) => { e.stopPropagation(); openLogBantuan(d.id, d.nama); }); + + card.querySelector('.data-card-main').addEventListener('click', () => { + card.classList.toggle('expanded'); + flyToMiskin(d.id); + }); + + return card; + } + + function flyToMiskin(id) { + pendudukMiskinLayer.eachLayer(l => { + if (l.miskinData && l.miskinData.id == id) { + map.setView(l.getLatLng(), 17); l.openPopup(); + } + }); + } + + // ---- Hook: klik peta saat mode miskin_click ---- + // Ditangkap oleh kemiskinan.js via contextmenu — mode ini pakai klik kiri + map.on('click', function(e) { + if (window.currentAddMode === 'miskin_click') { + window.currentAddMode = null; + document.getElementById('map').style.cursor = ''; + if (window.cursorTooltip) window.cursorTooltip.style.display = 'none'; + // Buka form tambah miskin + if (typeof window.formAddMiskin === 'function') { + window.formAddMiskin(e.latlng.lat, e.latlng.lng); + } + } + }); + + // ========================== + // ===== Log Bantuan Modal == + // ========================== + const logModal = document.getElementById('logBantuanModal'); + const logTitle = document.getElementById('logBantuanTitle'); + const logList = document.getElementById('logBantuanList'); + const logSaveBtn = document.getElementById('logSaveBtn'); + const logIbadahSel = document.getElementById('logIbadahId'); + let _logMiskinId = null; + + window.openLogBantuan = function (miskinId, nama) { + _logMiskinId = miskinId; + logTitle.textContent = `Log Bantuan — ${nama}`; + logModal.classList.add('show'); + + const isAuth = !!window.currentUser; + const formContainer = document.querySelector('#logBantuanModal .modal-body > div:last-child'); + const modalFooter = document.querySelector('#logBantuanModal .modal-footer'); + + if (isAuth) { + if (formContainer) formContainer.style.display = 'block'; + if (modalFooter) modalFooter.style.display = 'flex'; + } else { + if (formContainer) formContainer.style.display = 'none'; + if (modalFooter) modalFooter.style.display = 'none'; + } + + // Isi dropdown ibadah + logIbadahSel.innerHTML = ''; + if (typeof ibadahDataList !== 'undefined') { + ibadahDataList.forEach(ib => { + const opt = document.createElement('option'); + opt.value = ib.id; + opt.textContent = `${IBADAH_EMOJI[ib.jenis] || '🕌'} ${ib.nama}`; + logIbadahSel.appendChild(opt); + }); + } + + if (window.currentUser && window.currentUser.role === 'pengelola') { + logIbadahSel.value = window.currentUser.ibadah_id; + logIbadahSel.disabled = true; + } else { + logIbadahSel.disabled = false; + } + + // Set tanggal default hari ini + document.getElementById('logTanggal').valueAsDate = new Date(); + fetchLogBantuan(miskinId); + }; + + window.closeLogBantuanModal = function () { + logModal.classList.remove('show'); + _logMiskinId = null; + }; + + function fetchLogBantuan(miskinId) { + logList.innerHTML = '
Memuat...
'; + fetch(`api/log_bantuan/read.php?miskin_id=${miskinId}`) + .then(r => r.json()) + .then(data => { + if (!data.data || !data.data.length) { + logList.innerHTML = '
Belum ada riwayat bantuan
'; + return; + } + logList.innerHTML = ''; + data.data.forEach(log => { + const tgl = new Date(log.tanggal).toLocaleDateString('id-ID', { day:'2-digit', month:'short', year:'numeric' }); + const item = document.createElement('div'); + item.className = 'log-item'; + item.innerHTML = ` +
+
+
${escHtml(log.tipe_bantuan)}
+
${IBADAH_EMOJI[log.jenis_ibadah] || '🕌'} ${escHtml(log.nama_ibadah)} • ${tgl}
+ ${log.keterangan ? `
${escHtml(log.keterangan)}
` : ''} +
`; + logList.appendChild(item); + }); + }) + .catch(() => { + logList.innerHTML = '
Gagal memuat data
'; + }); + } + + logSaveBtn.addEventListener('click', function () { + const ibadah_id = logIbadahSel.value; + const tipe_bantuan = document.getElementById('logTipeBantuan').value; + const tanggal = document.getElementById('logTanggal').value; + const keterangan = document.getElementById('logKeterangan').value; + + if (!ibadah_id) { alert('Pilih rumah ibadah terlebih dahulu!'); return; } + if (!tanggal) { alert('Tanggal harus diisi!'); return; } + + fetch('api/log_bantuan/create.php', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ miskin_id: _logMiskinId, ibadah_id, tipe_bantuan, tanggal, keterangan }) + }) + .then(r => r.json()) + .then(data => { + if (data.status === 'success') { + document.getElementById('logKeterangan').value = ''; + fetchLogBantuan(_logMiskinId); + } else { + alert(data.message || 'Gagal menyimpan'); + } + }); + }); + + // ---- Utility ---- + function escHtml(str) { + if (!str) return ''; + return String(str).replace(/&/g,'&').replace(//g,'>').replace(/"/g,'"'); + } + + // ---- Expose ---- + window.openRightPanel = openPanel; + +})(); diff --git a/webgis-poverty-pontianak/database.sql b/webgis-poverty-pontianak/database.sql new file mode 100644 index 0000000..0590fb1 --- /dev/null +++ b/webgis-poverty-pontianak/database.sql @@ -0,0 +1,90 @@ +-- Database schema for WebGIS Pemetaan Kemiskinan Pontianak + +CREATE DATABASE IF NOT EXISTS webgis; +USE webgis; + +-- 1. Tabel rumah_ibadah +DROP TABLE IF EXISTS `log_bantuan`; +DROP TABLE IF EXISTS `rumah_ibadah`; +CREATE TABLE `rumah_ibadah` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `nama` varchar(255) NOT NULL, + `jenis` varchar(100) NOT NULL, + `alamat` text, + `radius` double NOT NULL DEFAULT 0, + `lat` double NOT NULL, + `lng` double NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- 2. Tabel penduduk_miskin +DROP TABLE IF EXISTS `penduduk_miskin`; +CREATE TABLE `penduduk_miskin` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `nama` varchar(255) NOT NULL, + `kategori_bantuan` varchar(255) NOT NULL, + `jumlah_jiwa` int(11) NOT NULL DEFAULT 1, + `lat` double NOT NULL, + `lng` double NOT NULL, + `foto_rumah` varchar(255) DEFAULT NULL, + `foto_kk` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- 3. Tabel log_bantuan +CREATE TABLE `log_bantuan` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `miskin_id` int(11) NOT NULL, + `ibadah_id` int(11) NOT NULL, + `tipe_bantuan` varchar(255) NOT NULL, + `tanggal` date NOT NULL, + `keterangan` text, + PRIMARY KEY (`id`), + KEY `fk_log_miskin` (`miskin_id`), + KEY `fk_log_ibadah` (`ibadah_id`), + CONSTRAINT `fk_log_ibadah` FOREIGN KEY (`ibadah_id`) REFERENCES `rumah_ibadah` (`id`) ON DELETE CASCADE, + CONSTRAINT `fk_log_miskin` FOREIGN KEY (`miskin_id`) REFERENCES `penduduk_miskin` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + + +-- Data Contoh (Sample Data) untuk Pontianak + +-- Data Contoh Rumah Ibadah +INSERT INTO `rumah_ibadah` (`nama`, `jenis`, `alamat`, `radius`, `lat`, `lng`) VALUES +('Masjid Raya Mujahidin', 'Masjid', 'Jl. Jenderal Ahmad Yani, Akcaya, Kec. Pontianak Sel.', 500, -0.0435, 109.3440), +('Gereja Katedral Santo Yosef', 'Gereja', 'Jl. Patria Tama, Darat Sekip, Kec. Pontianak Kota', 500, -0.0278, 109.3370), +('Vihara Bodhisatva Karaniya Metta', 'Vihara', 'Jl. Kapten Marsan, Darat Sekip, Kec. Pontianak Kota', 500, -0.0232, 109.3432); + +-- Data Contoh Penduduk Miskin +INSERT INTO `penduduk_miskin` (`nama`, `kategori_bantuan`, `jumlah_jiwa`, `lat`, `lng`) VALUES +('Budi Santoso', 'Makan', 4, -0.0420, 109.3415), +('Siti Aminah', 'Pemberdayaan', 3, -0.0285, 109.3395), +('Ahmad Subarjo', 'Makan', 5, -0.0245, 109.3448); + +-- Data Contoh Log Bantuan +INSERT INTO `log_bantuan` (`miskin_id`, `ibadah_id`, `tipe_bantuan`, `tanggal`, `keterangan`) VALUES +(1, 1, 'Sembako', '2026-05-15', 'Pembagian paket sembako bulanan'), +(2, 2, 'Pendidikan', '2026-05-20', 'Bantuan biaya sekolah anak'), +(3, 1, 'Uang Tunai', '2026-06-01', 'Santunan tunai darurat'); + + + +-- 7. Tabel users +DROP TABLE IF EXISTS `users`; +CREATE TABLE `users` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `username` varchar(100) NOT NULL UNIQUE, + `password` varchar(255) NOT NULL, + `role` enum('admin', 'pengelola') NOT NULL, + `ibadah_id` int(11) DEFAULT NULL, + PRIMARY KEY (`id`), + CONSTRAINT `fk_users_ibadah` FOREIGN KEY (`ibadah_id`) REFERENCES `rumah_ibadah` (`id`) ON DELETE SET NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Data Contoh Pengguna (Default Users) +-- Password admin: password +-- Password pengelola: password (terhubung ke Masjid Raya Mujahidin, ibadah_id = 1) +INSERT INTO `users` (`username`, `password`, `role`, `ibadah_id`) VALUES +('admin', '$2y$10$qqKxivn4646czFu/ffwa/uZxJrkj3T9xmsrRbyxJbHx6jllpOOfDO', 'admin', NULL), +('pengelola_mujahidin', '$2y$10$qqKxivn4646czFu/ffwa/uZxJrkj3T9xmsrRbyxJbHx6jllpOOfDO', 'pengelola', 1); + diff --git a/webgis-poverty-pontianak/index.php b/webgis-poverty-pontianak/index.php new file mode 100644 index 0000000..447fe90 --- /dev/null +++ b/webgis-poverty-pontianak/index.php @@ -0,0 +1,408 @@ + + + + + + WebGIS Pemetaan Kemiskinan + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + +
+ + +
+ + + + + + + + + + + + +
+ +
+

Daftar Layer

+ + + +
Pemetaan Kemiskinan
+ + + + + +
+
+ + +
+ +
+ + +
+
+ GeoJSON Eksternal + +
+ +
+
+ + +
+
+

Data

+ +
+
+
+
Pilih menu di kiri untuk menampilkan data
+
+
+
+ + + + +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+ ⚠️ +
+
DISCLAIMER — DATA DUMMY
+
+ Seluruh data pada aplikasi ini termasuk nama kepala keluarga, foto rumah, dan foto Kartu Keluarga (KK) merupakan data fiktif / dummy yang hanya digunakan untuk keperluan demonstrasi dan pengujian sistem. Bukan data nyata. +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/webgis-poverty-pontianak/test_miskin.csv b/webgis-poverty-pontianak/test_miskin.csv new file mode 100644 index 0000000..d9bc426 --- /dev/null +++ b/webgis-poverty-pontianak/test_miskin.csv @@ -0,0 +1,4 @@ +nama,kategori_bantuan,jumlah_jiwa,lat,lng +Budi Santoso,Makan,4,-0.025,109.340 +Siti Aminah,Pemberdayaan,3,-0.028,109.345 +Andi Wijaya,Makan,5,-0.024,109.341 diff --git a/webgis-poverty-pontianak/test_miskin.geojson b/webgis-poverty-pontianak/test_miskin.geojson new file mode 100644 index 0000000..ccc4d62 --- /dev/null +++ b/webgis-poverty-pontianak/test_miskin.geojson @@ -0,0 +1,29 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "nama": "Joko Widodo", + "kategori_bantuan": "Pemberdayaan", + "jumlah_jiwa": 2 + }, + "geometry": { + "type": "Point", + "coordinates": [109.343, -0.027] + } + }, + { + "type": "Feature", + "properties": { + "nama": "Mega Wati", + "kategori_bantuan": "Makan", + "jumlah_jiwa": 6 + }, + "geometry": { + "type": "Point", + "coordinates": [109.344, -0.029] + } + } + ] +}