'')))) { try { $query = " SELECT json_build_object( 'type', 'FeatureCollection', 'features', COALESCE(json_agg( json_build_object( 'type', 'Feature', 'geometry', ST_AsGeoJSON(geom)::json, 'properties', json_build_object( 'time', start_time, 'county', county, 'state', state, 'outage', outagen, 'lastchange', last_change, 'cause', COALESCE(cause, ''), 'area_geometry', ST_AsGeoJSON(COALESCE(realareageom, geom))::json ) ) ORDER BY start_time ASC ), '[]'::json) ) as geojson FROM newpower WHERE cwa = $1 AND active = true AND geom IS NOT NULL "; $result = pg_query_params($dbconn, $query, array('RLX')); if ($result === false) { throw new Exception('Query failed: ' . pg_last_error()); } $resultArray = pg_fetch_assoc($result); if ($resultArray && $resultArray['geojson']) { echo $resultArray['geojson']; } else { echo json_encode(['type' => 'FeatureCollection', 'features' => []]); } pg_free_result($result); } catch (Exception $e) { http_response_code(500); echo json_encode(['error' => 'Query execution failed: ' . $e->getMessage()]); } } // Get states boundaries if (isset($_GET['states'])) { try { $query = " SELECT jsonb_build_object( 'type', 'FeatureCollection', 'features', jsonb_agg(features.feature) ) FROM ( SELECT jsonb_build_object( 'type', 'Feature', 'geometry', ST_AsGeoJSON(ST_Transform(geom, 4326))::jsonb, 'properties', to_jsonb(properties) - 'geom' ) AS feature FROM ( SELECT * FROM states WHERE state IN ('WV', 'VA', 'KY', 'MD', 'PA', 'OH') ) AS properties ) AS features "; $result = pg_query($dbconn, $query); if ($result === false) { throw new Exception('Query failed: ' . pg_last_error()); } $resultArray = pg_fetch_all($result); // Set proper JSON header and handle output header('Content-Type: application/json'); if ($resultArray && isset($resultArray[0]['jsonb_build_object'])) { echo $resultArray[0]['jsonb_build_object']; } else { echo json_encode(['type' => 'FeatureCollection', 'features' => []]); } pg_free_result($result); } catch (Exception $e) { header('Content-Type: application/json'); http_response_code(500); echo json_encode(['error' => 'Query execution failed: ' . $e->getMessage()]); exit; } } // Get current county outages if (isset($_GET['county'])) { try { $query = " WITH latest_fetch AS ( SELECT MAX(fetch_time) as max_fetch_time FROM newcountyoutages ) SELECT n.county, n.state, SUM(n.outages) as outage, MAX(n.fetch_time) as time, SUM(n.served) as served, CASE WHEN SUM(n.served) > 0 THEN ROUND(CAST((SUM(n.outages)::FLOAT / SUM(n.served)) * 100 AS NUMERIC), 2) ELSE 0 END as perout FROM newcountyoutages n, latest_fetch WHERE n.fetch_time = latest_fetch.max_fetch_time AND n.cwa = $1 GROUP BY n.county, n.state "; $result = pg_query_params($dbconn, $query, ['RLX']); if ($result === false) { throw new Exception('Query failed: ' . pg_last_error()); } $results = pg_fetch_all($result) ?: []; header('Content-Type: application/json'); echo json_encode($results); pg_free_result($result); } catch (Exception $e) { header('Content-Type: application/json'); http_response_code(500); echo json_encode(['error' => 'Query execution failed: ' . $e->getMessage()]); } } // Max county outages for a time range if (isset($_GET['max'])) { if (isset($_GET['start']) && isset($_GET['end'])) { try { $starttime = getParam('start'); $endtime = getParam('end'); $query = " SELECT DISTINCT ON (county, state) max(outage) as max_outage, county, state FROM ( SELECT DISTINCT ON (county, state, fetch_time) county, state, SUM(outages) as outage, fetch_time as time, SUM(served) as served FROM newcountyoutages WHERE fetch_time > $2 AND fetch_time < $3 AND cwa = $1 GROUP BY county, state, fetch_time ) as subquery GROUP BY county, state "; $result = pg_query_params( $dbconn, $query, ['RLX', $starttime, $endtime] ); if ($result === false) { throw new Exception('Query failed: ' . pg_last_error()); } $results = []; while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) { $results[] = $line; } header('Content-Type: application/json'); echo json_encode($results); pg_free_result($result); } catch (Exception $e) { header('Content-Type: application/json'); http_response_code(500); echo json_encode(['error' => 'Query execution failed: ' . $e->getMessage()]); exit; } } else { header('Content-Type: application/json'); http_response_code(400); echo json_encode(['error' => 'Both start and end parameters are required']); } } // Archive county outages for a time range if (isset($_GET['countyarchive'])) { if (isset($_GET['start']) && isset($_GET['end'])) { try { $starttime = getParam('start'); $endtime = getParam('end'); $query = " SELECT DISTINCT ON (county, state, fetch_time) county, state, SUM(outages) as outage, fetch_time as time, SUM(served) as served FROM newcountyoutages WHERE fetch_time > $9 AND fetch_time < $10 AND (cwa = $1 OR cwa = $2 OR cwa = $3 OR cwa = $4 OR cwa = $5 OR cwa = $6 OR cwa = $7 OR cwa = $8) GROUP BY county, state, fetch_time "; $result = pg_query_params($dbconn, $query, ['RLX','JKL','ILN','PBZ','MRX','LWX','RNK','CTP',$starttime,$endtime]); if ($result === false) { throw new Exception('Query failed: ' . pg_last_error()); } $results = []; while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) { $results[] = $line; } header('Content-Type: application/json'); echo json_encode($results); pg_free_result($result); } catch (Exception $e) { header('Content-Type: application/json'); http_response_code(500); echo json_encode(['error' => 'Query execution failed: ' . $e->getMessage()]); if (isset($result)) { pg_free_result($result); } exit; } } else { header('Content-Type: application/json'); http_response_code(400); echo json_encode(['error' => 'Both start and end parameters are required']); } } // Archive point data for a time range if (isset($_GET['archivepoint'])) { try { if (!isset($_GET['start']) || !isset($_GET['end'])) { throw new Exception('Both start and end parameters are required'); } $starttime = getParam('start'); $endtime = getParam('end'); $query = " SELECT json_build_object( 'type', 'FeatureCollection', 'features', json_agg( json_build_object( 'type', 'Feature', 'geometry', ST_AsGeoJSON(geom)::json, 'properties', json_build_object( 'time', start_time, 'county', county, 'state', state, 'outage', outagen, 'lastchange', last_change, 'cause', cause ) ) ORDER BY start_time ASC ) ) FROM newpower WHERE cwa = $1 AND start_time > $2 AND last_change < $3 AND geom IS NOT NULL "; $result = pg_query_params($dbconn, $query, ['RLX', $starttime, $endtime]); if ($result === false) { throw new Exception('Query failed: ' . pg_last_error()); } $resultArray = pg_fetch_all($result); header('Content-Type: application/json'); if ($resultArray && isset($resultArray[0]['json_build_object'])) { echo $resultArray[0]['json_build_object']; } else { echo json_encode(['type' => 'FeatureCollection', 'features' => []]); } pg_free_result($result); } catch (Exception $e) { header('Content-Type: application/json'); $statusCode = strpos($e->getMessage(), 'required') !== false ? 400 : 500; http_response_code($statusCode); echo json_encode(['error' => $e->getMessage()]); if (isset($result)) { pg_free_result($result); } exit; } } // Current severe weather warnings if (@$_GET['svr'] == 'current') { try { $result = pg_query($dbconn, "SELECT json_build_object('type', 'FeatureCollection','features', json_agg(json_build_object('type','Feature', 'geometry', ST_AsGeoJSON(nwspoly)::json,'properties',json_build_object('issue',issue,'end',endtime,'vtec',vtec,'type',warntype)))) FROM svr where issue < now() and endtime > now()") or die('Query failed: ' . pg_last_error()); $resultArray = pg_fetch_all($result); header('Content-Type: application/json'); if ($resultArray && isset($resultArray[0]['json_build_object'])) { echo $resultArray[0]['json_build_object']; } else { echo json_encode(['type' => 'FeatureCollection', 'features' => []]); } pg_free_result($result); } catch (Exception $e) { header('Content-Type: application/json'); http_response_code(500); echo json_encode(['error' => 'Query execution failed: ' . $e->getMessage()]); } } // Archive severe weather warnings if (isset($_GET['svr']) && $_GET['svr'] === 'archive') { try { $result = null; if (isset($_GET['start']) && isset($_GET['end'])) { $starttime = getParam('start'); $endtime = getParam('end'); $query = " SELECT json_build_object( 'type', 'FeatureCollection', 'features', json_agg( json_build_object( 'type', 'Feature', 'geometry', ST_AsGeoJSON(nwspoly)::json, 'properties', json_build_object( 'issue', issue, 'end', endtime, 'vtec', vtec, 'type', warntype ) ) ) ) FROM svr WHERE issue > $1 AND endtime < $2 "; $result = pg_query_params($dbconn, $query, [$starttime, $endtime]); } elseif (!isset($_GET['start']) && !isset($_GET['end'])) { $query = " SELECT json_build_object( 'type', 'FeatureCollection', 'features', json_agg( json_build_object( 'type', 'Feature', 'geometry', ST_AsGeoJSON(nwspoly)::json, 'properties', json_build_object( 'issue', issue, 'end', endtime, 'vtec', vtec, 'type', warntype ) ) ) ) FROM svr WHERE issue < NOW() - INTERVAL '24 hours' AND endtime > NOW() - INTERVAL '24 hours' "; $result = pg_query($dbconn, $query); } else { throw new Exception('Both start and end parameters are required together'); } if ($result === false) { throw new Exception('Query failed: ' . pg_last_error()); } $resultArray = pg_fetch_all($result); header('Content-Type: application/json'); if ($resultArray && isset($resultArray[0]['json_build_object'])) { echo $resultArray[0]['json_build_object']; } else { echo json_encode(['type' => 'FeatureCollection', 'features' => []]); } pg_free_result($result); } catch (Exception $e) { if (isset($result)) { pg_free_result($result); } header('Content-Type: application/json'); $statusCode = strpos($e->getMessage(), 'required') !== false ? 400 : 500; http_response_code($statusCode); echo json_encode(['error' => $e->getMessage()]); exit; } } // Severe weather warning polygons if (isset($_GET['svrpolys'])) { try { $query = " SELECT vtec, outagesvalid, polygonpop, outagesbuffer, lsrids FROM svr WHERE EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - endtime)) / 60 / 60 / 24 < 60 "; $result = pg_query($dbconn, $query); if ($result === false) { throw new Exception('Query failed: ' . pg_last_error()); } $results = []; while ($line = pg_fetch_array($result, null, PGSQL_ASSOC)) { $results[] = $line; } header('Content-Type: application/json'); echo json_encode($results); pg_free_result($result); } catch (Exception $e) { if (isset($result)) { pg_free_result($result); } header('Content-Type: application/json'); http_response_code(500); echo json_encode(['error' => $e->getMessage()]); exit; } } // Power outage details by IDs if (isset($_GET['powerids'])) { try { $powerids = $_GET['powerids']; // Validate input exists and isn't empty if (empty($powerids)) { throw new Exception('No power IDs provided'); } // Convert comma-separated string to array and sanitize $poweridArray = explode(',', $powerids); $sanitizedIds = array_filter(array_map('intval', $poweridArray)); if (empty($sanitizedIds)) { throw new Exception('Invalid power ID format'); } // Prepare placeholders for the query $placeholders = implode(',', array_map(function($i) { return '$' . $i; }, range(1, count($sanitizedIds)))); $query = " SELECT lat, lon, last_change, start_time, peakoutage, cause, lsrtime, lsrref, (lsrtime AT TIME ZONE 'America/New_York')::timestamp as lsrlocal FROM newpower WHERE id IN ($placeholders) "; $result = pg_query_params($dbconn, $query, $sanitizedIds); if ($result === false) { throw new Exception('Query failed: ' . pg_last_error()); } $results = pg_fetch_all($result) ?: []; header('Content-Type: application/json'); echo json_encode($results); pg_free_result($result); } catch (Exception $e) { if (isset($result)) { pg_free_result($result); } header('Content-Type: application/json'); $statusCode = strpos($e->getMessage(), 'Invalid') !== false ? 400 : 500; http_response_code($statusCode); echo json_encode(['error' => $e->getMessage()]); exit; } } pg_close($dbconn); ?>