// 1. EXTENDED COORDINATE DATABASE // defines a static database of coordinates for Philippine cities and provinces const cityCoords = {     // --- NCR ---     "Manila": [14.5995, 120.9842],     "Quezon City": [14.6760, 121.0437],     "Makati": [14.5547, 121.0244],     "Taguig": [14.5176, 121.0509],     "Pasig": [14.5763, 121.0851],     "Mandaluyong": [14.5794, 121.0359],     "Marikina": [14.6333, 121.0980],     "Las Pinas": [14.4445, 120.9939],     "Muntinlupa": [14.4081, 121.0415],     "Caloocan": [14.6401, 120.9745],     "Parañaque": [14.4793, 121.0198],     "Valenzuela": [14.7011, 120.9830],     "Pasay": [14.5378, 121.0014],     "Malabon": [14.6625, 120.9512],     "Navotas": [14.6732, 120.9350],     "San Juan": [14.6019, 121.0355],     "Pateros": [14.5454, 121.0687],     // --- CAVITE ---     "Cavite": [14.2831, 120.9168],     "Naic": [14.3168, 120.7628],     "Bacoor": [14.4624, 120.9645],     "Imus": [14.4297, 120.9367],     "Dasmarinas": [14.3294, 120.9367],     "General Trias": [14.3876, 120.8842],     "Tagaytay": [14.1153, 120.9621],     "Kawit": [14.4448, 120.9022],     "Noveleta": [14.4263, 120.8820],     "Rosario": [14.4153, 120.8532],     "Tanza": [14.3949, 120.8532],     "Silang": [14.2312, 120.9746],     "Trece Martires": [14.2883, 120.8677],     // --- LAGUNA ---     "Laguna": [14.2166, 121.1667],     "Calamba": [14.2142, 121.1553],     "Santa Rosa": [14.3121, 121.1132],     "Binan": [14.3400, 121.0827],     "San Pedro": [14.3644, 121.0370],     "Cabuyao": [14.2796, 121.1219],     "Los Banos": [14.1708, 121.2413],     // --- RIZAL ---     "Rizal": [14.5906, 121.2236],     "Antipolo": [14.5844, 121.1763],     "Cainta": [14.5760, 121.1213],     "Taytay": [14.5623, 121.1376],     "San Mateo": [14.6963, 121.1215],     "Binangonan": [14.4759, 121.1893],     // --- BULACAN ---     "Bulacan": [14.8524, 120.8228],     "Malolos": [14.8527, 120.8160],     "Meycauayan": [14.7356, 120.9622],     "San Jose del Monte": [14.8143, 121.0427],     "Bocaue": [14.8066, 120.9256],     // --- MAJOR PROVINCES / CITIES ---     "Pampanga": [15.0359, 120.6924],     "Tarlac": [15.4802, 120.5979],     "Batangas": [13.7565, 121.0583],     "Baguio": [16.4023, 120.5960],     "Cebu": [10.3157, 123.8854],     "Iloilo": [10.7202, 122.5621],     "Davao": [7.1907, 125.4553],     "Cagayan": [17.6133, 121.7302],     "Bicol": [13.4350, 123.4100],     "Albay": [13.1391, 123.7438],     "Tacloban": [11.2442, 125.0039],     "Zamboanga": [6.9214, 122.0790],     "Palawan": [9.8349, 118.7384],     "Mindoro": [13.0264, 121.2227],     "Isabela": [16.9754, 121.8107],     "Pangasinan": [15.9236, 120.3392],     "Philippines": [12.8797, 121.7740] // CENTER OF PH }; let map; let markers = []; // initializes the map view and starts fetching data document.addEventListener("DOMContentLoaded", () => {     // sets the initial map center on the CALABARZON/NCR area     map = L.map('map').setView([14.40, 121.00], 10);     // adds the dark-themed tile layer to the map     L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png', {         attribution: '© OpenStreetMap © CARTO',         subdomains: 'abcd',         maxZoom: 19     }).addTo(map);     console.log("ALISTO Map: Loaded");     // fetches the first set of post data     fetchDataAndPlot();     // sets a timer to refresh data every 30 seconds     setInterval(fetchDataAndPlot, 30000); }); // fetches the list of active disaster posts from the API function fetchDataAndPlot() {     fetch('/api/posts')         .then(response => response.json())         .then(data => {             // updates the alert count in the map sidebar             updateSidebar(data);             // plots the markers on the map             plotMarkers(data);         })         .catch(err => console.error("Map Fetch Error:", err)); } // updates the displayed alert count and system status in the floating sidebar function updateSidebar(data) {     const countEl = document.getElementById('alert-count');     const statusEl = document.getElementById('status-text');     if(countEl) countEl.innerText = data.length;     if(statusEl) statusEl.innerText = "System Active"; } // clears existing markers and plots new circular markers for each post function plotMarkers(posts) {     // removes all existing markers from the map     markers.forEach(m => map.removeLayer(m));     markers = [];     // iterates through all posts to find coordinates and draw markers     posts.forEach(async post => {         // asynchronously finds the latitude and longitude for the location         let coords = await getCoordinatesSmart(post.location);         if (coords) {             // sets color and size based on post urgency level             const urgencyColor = post.urgency_level === 'High' ? '#ff4444' : '#ed4801';             const radius = post.urgency_level === 'High' ? 14 : 8;             // creates and adds a circular marker (L.circleMarker) to the map             const circle = L.circleMarker(coords, {                 color: urgencyColor,                 fillColor: urgencyColor,                 fillOpacity: 0.7,                 radius: radius             }).addTo(map);             const timeStr = new Date(post.timestamp).toLocaleTimeString();                         // binds a detailed pop-up box to the circular marker             circle.bindPopup(`                
                                            ${post.disaster_type}                                                            
                        ⚠ ${post.assistance_type || "General Help"}                    
                    📍 ${post.location}                                        
                                       
                        "${post.title}"                    
                                        ${timeStr}                
            `);             // adds the new marker to the global array             markers.push(circle);         }     }); } // --- NEW SMART FINDER (Hybrid: Static List + API) --- // function to look up coordinates, prioritizing the static list then Nominatim API async function getCoordinatesSmart(locationStr) {     if (!locationStr) return cityCoords["Philippines"];     // 1. Try Static List (Instant)     // direct match check     const exactMatch = Object.keys(cityCoords).find(k => k.toLowerCase() === locationStr.toLowerCase());     if (exactMatch) return cityCoords[exactMatch];     // fuzzy match check     const fuzzyKey = Object.keys(cityCoords).find(city => locationStr.toLowerCase().includes(city.toLowerCase()));     if (fuzzyKey) return cityCoords[fuzzyKey];     // 2. Try OpenStreetMap API (Dynamic)     // checks local cache before making a network request     if (!window.coordCache) window.coordCache = {};     if (window.coordCache[locationStr]) return window.coordCache[locationStr];     try {         console.log(`Fetching coords for: ${locationStr}...`);         // fetches coordinates from the Nominatim API         const response = await fetch(`https://nominatim.openstreetmap.org/search?format=json&q=${locationStr}, Philippines`);         const data = await response.json();                 // processes and caches the result         if (data && data.length > 0) {             const lat = parseFloat(data[0].lat);             const lon = parseFloat(data[0].lon);             const result = [lat, lon];             window.coordCache[locationStr] = result;             return result;         }     } catch (e) {         console.error("Geocoding failed:", e);     }     // 3. Fallback     // returns the center of the Philippines if geocoding fails     return cityCoords["Philippines"]; }