From c5c121510c352308711ee65d9227921e6ee72fe8 Mon Sep 17 00:00:00 2001 From: Christopher J Lowrie Date: Thu, 8 Aug 2024 15:10:42 -0700 Subject: [PATCH 01/19] Adding Google Floods Backend --- api/app/googleflood.py | 57 +++++++++++++++++++++++++ api/app/main.py | 8 ++++ api/app/pytest.ini | 3 ++ api/app/tests/test_google_floods_api.py | 20 +++++++++ 4 files changed, 88 insertions(+) create mode 100644 api/app/googleflood.py create mode 100644 api/app/pytest.ini create mode 100644 api/app/tests/test_google_floods_api.py diff --git a/api/app/googleflood.py b/api/app/googleflood.py new file mode 100644 index 000000000..4a96e1667 --- /dev/null +++ b/api/app/googleflood.py @@ -0,0 +1,57 @@ +"""Get data from Humanitarian Data Cube (HDC) API""" +import logging +from os import getenv + +import requests + +logger = logging.getLogger(__name__) + +GOOGLE_FLOODS_API_KEY = getenv("GOOGLE_FLOODS_API_KEY", "") +if GOOGLE_FLOODS_API_KEY == "": + logger.warning("Missing backend parameter: GOOGLE_FLOODS_API_KEY") + +def format_to_geojson(data): + geojson = { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [data["gaugeLocation"]["longitude"], data["gaugeLocation"]["latitude"]] + }, + "properties": { + "gaugeId": data["gaugeId"], + "issuedTime": data["issuedTime"], + # "forecastTimeRange": data["forecastTimeRange"], + # "forecastChange": data["forecastChange"], + # "forecastTrend": data["forecastTrend"], + "severity": data["severity"], + "source": data["source"], + "qualityVerified": data["qualityVerified"] + } + } + if "inundationMapSet" in data: + geojson["properties"]["inundationMapSet"] = data["inundationMapSet"] + return geojson + + +def get_google_floods_gauges( + iso2: str, + asGeojson: bool = True, +): + """Get statistical charts data""" + logging.info(GOOGLE_FLOODS_API_KEY) + + URL = f'https://floodforecasting.googleapis.com/v1/floodStatus:searchLatestFloodStatusByArea?key={GOOGLE_FLOODS_API_KEY}' + response = requests.post( + URL, + json={'regionCode': iso2} + ).json().get('floodStatuses', []) + + if asGeojson: + geojson_feature_collection = { + "type": "FeatureCollection", + "features": [format_to_geojson(data) for data in response] + } + return geojson_feature_collection + return response + + diff --git a/api/app/main.py b/api/app/main.py index ee054c39c..96b84b021 100644 --- a/api/app/main.py +++ b/api/app/main.py @@ -14,6 +14,7 @@ from app.database.alert_model import AlchemyEncoder, AlertModel from app.database.database import AlertsDataBase from app.database.user_info_model import UserInfoModel +from app.googleflood import get_google_floods_gauges from app.hdc import get_hdc_stats from app.kobo import get_form_dates, get_form_responses, parse_datetime_params from app.models import AcledRequest, RasterGeotiffModel @@ -412,3 +413,10 @@ def post_raster_geotiff(raster_geotiff: RasterGeotiffModel): return JSONResponse( content={"download_url": presigned_download_url}, status_code=200 ) + + +@app.get("/google-floods-gauges") +def get_google_floods_gauges_api( + iso2: str, +): + return get_google_floods_gauges(iso2) \ No newline at end of file diff --git a/api/app/pytest.ini b/api/app/pytest.ini new file mode 100644 index 000000000..11c72fa2e --- /dev/null +++ b/api/app/pytest.ini @@ -0,0 +1,3 @@ +[pytest] +log_cli = true +log_cli_level = INFO diff --git a/api/app/tests/test_google_floods_api.py b/api/app/tests/test_google_floods_api.py new file mode 100644 index 000000000..a6335a539 --- /dev/null +++ b/api/app/tests/test_google_floods_api.py @@ -0,0 +1,20 @@ +from app.googleflood import get_google_floods_gauges +from app.main import app +from fastapi.testclient import TestClient +import logging, json + +client = TestClient(app) + +def test_get_google_floods_gauges(): + gauges = get_google_floods_gauges("BD") + assert len(gauges) > 0 + + +def test_get_google_floods_gauges_api(): + response = client.get("/google-floods-gauges?iso2=BD") + assert response.status_code == 200 + logging.info(json.dumps(response.json())) + # logging.info(response.json()) + assert len(response.json()) > 0 + + \ No newline at end of file From b9722d34a744842fc0a85dab3b5fefa6cbbccf22 Mon Sep 17 00:00:00 2001 From: Will Gislason <8203830+gislawill@users.noreply.github.com> Date: Sun, 11 Aug 2024 22:26:27 -0700 Subject: [PATCH 02/19] Viewing the gauges on the frontend, adding error handling to backend --- api/app/googleflood.py | 53 ++++++++++++++-------- api/app/main.py | 13 ++++-- api/app/tests/test_google_floods_api.py | 9 ++-- frontend/src/config/mozambique/layers.json | 41 +++++++++++++++++ frontend/src/config/mozambique/prism.json | 6 ++- 5 files changed, 94 insertions(+), 28 deletions(-) diff --git a/api/app/googleflood.py b/api/app/googleflood.py index 4a96e1667..740f77cb1 100644 --- a/api/app/googleflood.py +++ b/api/app/googleflood.py @@ -1,8 +1,10 @@ """Get data from Humanitarian Data Cube (HDC) API""" + import logging from os import getenv import requests +from fastapi import HTTPException logger = logging.getLogger(__name__) @@ -10,12 +12,17 @@ if GOOGLE_FLOODS_API_KEY == "": logger.warning("Missing backend parameter: GOOGLE_FLOODS_API_KEY") -def format_to_geojson(data): + +def format_gauge_to_geojson(data): + """Format Gauge data to GeoJSON""" geojson = { "type": "Feature", "geometry": { "type": "Point", - "coordinates": [data["gaugeLocation"]["longitude"], data["gaugeLocation"]["latitude"]] + "coordinates": [ + data["gaugeLocation"]["longitude"], + data["gaugeLocation"]["latitude"], + ], }, "properties": { "gaugeId": data["gaugeId"], @@ -25,8 +32,8 @@ def format_to_geojson(data): # "forecastTrend": data["forecastTrend"], "severity": data["severity"], "source": data["source"], - "qualityVerified": data["qualityVerified"] - } + "qualityVerified": data["qualityVerified"], + }, } if "inundationMapSet" in data: geojson["properties"]["inundationMapSet"] = data["inundationMapSet"] @@ -35,23 +42,33 @@ def format_to_geojson(data): def get_google_floods_gauges( iso2: str, - asGeojson: bool = True, + as_geojson: bool = True, ): """Get statistical charts data""" - logging.info(GOOGLE_FLOODS_API_KEY) - - URL = f'https://floodforecasting.googleapis.com/v1/floodStatus:searchLatestFloodStatusByArea?key={GOOGLE_FLOODS_API_KEY}' - response = requests.post( - URL, - json={'regionCode': iso2} - ).json().get('floodStatuses', []) - - if asGeojson: + # Retry 3 times due to intermittent API errors + flood_status_url = f"https://floodforecasting.googleapis.com/v1/floodStatus:searchLatestFloodStatusByArea?key={GOOGLE_FLOODS_API_KEY}" + for _ in range(3): + try: + response = requests.post( + flood_status_url, json={"regionCode": iso2}, timeout=2 + ).json() + break + except requests.RequestException as e: + logger.warning("Request failed: %s", e) + response = {} + + if "error" in response: + logger.error("Error in response: %s", response["error"]) + raise HTTPException( + status_code=500, detail="Error fetching flood status data from Google API" + ) + + gauges = response.get("floodStatuses", []) + + if as_geojson: geojson_feature_collection = { "type": "FeatureCollection", - "features": [format_to_geojson(data) for data in response] + "features": [format_gauge_to_geojson(gauge) for gauge in gauges], } return geojson_feature_collection - return response - - + return gauges diff --git a/api/app/main.py b/api/app/main.py index 96b84b021..265b05b72 100644 --- a/api/app/main.py +++ b/api/app/main.py @@ -415,8 +415,11 @@ def post_raster_geotiff(raster_geotiff: RasterGeotiffModel): ) -@app.get("/google-floods-gauges") -def get_google_floods_gauges_api( - iso2: str, -): - return get_google_floods_gauges(iso2) \ No newline at end of file +@app.get("/google-floods/gauges/") +def get_google_floods_gauges_api(region_code: str): + if len(region_code) != 2: + raise HTTPException( + status_code=400, detail="region code must be exactly two characters (iso2)." + ) + iso2 = region_code.upper() + return get_google_floods_gauges(iso2) diff --git a/api/app/tests/test_google_floods_api.py b/api/app/tests/test_google_floods_api.py index a6335a539..ab5d38b22 100644 --- a/api/app/tests/test_google_floods_api.py +++ b/api/app/tests/test_google_floods_api.py @@ -1,14 +1,17 @@ +import json +import logging + from app.googleflood import get_google_floods_gauges from app.main import app from fastapi.testclient import TestClient -import logging, json client = TestClient(app) + def test_get_google_floods_gauges(): gauges = get_google_floods_gauges("BD") assert len(gauges) > 0 - + def test_get_google_floods_gauges_api(): response = client.get("/google-floods-gauges?iso2=BD") @@ -16,5 +19,3 @@ def test_get_google_floods_gauges_api(): logging.info(json.dumps(response.json())) # logging.info(response.json()) assert len(response.json()) > 0 - - \ No newline at end of file diff --git a/frontend/src/config/mozambique/layers.json b/frontend/src/config/mozambique/layers.json index ef05d1bdc..004f3c1e7 100644 --- a/frontend/src/config/mozambique/layers.json +++ b/frontend/src/config/mozambique/layers.json @@ -2954,5 +2954,46 @@ "start_date": "2020-12-01", "end_date": "2021-07-31", "opacity": 0.7 + }, + "google_flood_gauges": { + "title": "Google Flood Gauges", + "type": "point_data", + "hex_display": false, + "data": "http://0.0.0.0:80/google-floods/gauges/?region_code=MZ", + "data_field": "severity", + "opacity": 0.7, + "legend_text": "Google Flood Gauges", + "legend": [ + { + "label": "Extreme", + "value": "EXTREME", + "color": "#fa1a18" + }, + { + "label": "Severe", + "value": "SEVERE", + "color": "#fba12e" + }, + { + "label": "Above Normal", + "value": "ABOVE_NORMAL", + "color": "#ffff43" + }, + { + "label": "No Flooding", + "value": "NO_FLOODING", + "color": "#c5c5c5" + }, + { + "label": "Unknown", + "value": "UNKNOWN", + "color": "#cefdba" + }, + { + "label": "Severity Unspecified", + "value": "SEVERITY_UNSPECIFIED", + "color": "#91e038" + } + ] } } diff --git a/frontend/src/config/mozambique/prism.json b/frontend/src/config/mozambique/prism.json index 290d3b7c4..8160835de 100644 --- a/frontend/src/config/mozambique/prism.json +++ b/frontend/src/config/mozambique/prism.json @@ -20,7 +20,8 @@ "risk": "icon_impact.png", "tropical_storms": "icon_tropical_storm.png", "vulnerability": "icon_vulnerable.png", - "exposure": "icon_basemap.png" + "exposure": "icon_basemap.png", + "flood": "icon_basemap.png" }, "defaultDisplayBoundaries": [ "admin_boundaries", @@ -454,6 +455,9 @@ }, "exposure": { "population": ["census"] + }, + "flood": { + "flood_gauges": ["google_flood_gauges"] } } } From bc92d38f5ba5f1afd56ec3c2b2618ea42c2a37dc Mon Sep 17 00:00:00 2001 From: Will Gislason <8203830+gislawill@users.noreply.github.com> Date: Sun, 11 Aug 2024 22:27:16 -0700 Subject: [PATCH 03/19] Update comment --- api/app/googleflood.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/app/googleflood.py b/api/app/googleflood.py index 740f77cb1..cf57dd6f5 100644 --- a/api/app/googleflood.py +++ b/api/app/googleflood.py @@ -1,4 +1,4 @@ -"""Get data from Humanitarian Data Cube (HDC) API""" +"""Get data from Google Floods API""" import logging from os import getenv From 08a449968084cfc38889c558e49f3fc9e18ee1af Mon Sep 17 00:00:00 2001 From: Will Gislason <8203830+gislawill@users.noreply.github.com> Date: Mon, 12 Aug 2024 14:00:30 -0700 Subject: [PATCH 04/19] Updates to support tooltip content --- api/app/googleflood.py | 54 +++++++++++--- .../MapView/Layers/ImpactLayer/index.tsx | 1 + .../components/MapView/Layers/layer-utils.tsx | 2 + .../components/MapView/MapTooltip/index.tsx | 20 +++-- frontend/src/components/MapView/utils.ts | 54 +++++++++++--- frontend/src/config/mozambique/layers.json | 74 +++++++++++-------- frontend/src/config/mozambique/prism.json | 6 +- frontend/src/config/types.ts | 20 ++++- 8 files changed, 170 insertions(+), 61 deletions(-) diff --git a/api/app/googleflood.py b/api/app/googleflood.py index cf57dd6f5..1f1f95ba9 100644 --- a/api/app/googleflood.py +++ b/api/app/googleflood.py @@ -2,6 +2,7 @@ import logging from os import getenv +from urllib.parse import urlencode import requests from fastapi import HTTPException @@ -27,9 +28,10 @@ def format_gauge_to_geojson(data): "properties": { "gaugeId": data["gaugeId"], "issuedTime": data["issuedTime"], - # "forecastTimeRange": data["forecastTimeRange"], - # "forecastChange": data["forecastChange"], - # "forecastTrend": data["forecastTrend"], + "siteName": data["siteName"], + "river": ( + data["river"] if "river" in data and len(data["river"]) > 1 else None + ), "severity": data["severity"], "source": data["source"], "qualityVerified": data["qualityVerified"], @@ -49,26 +51,56 @@ def get_google_floods_gauges( flood_status_url = f"https://floodforecasting.googleapis.com/v1/floodStatus:searchLatestFloodStatusByArea?key={GOOGLE_FLOODS_API_KEY}" for _ in range(3): try: - response = requests.post( + status_response = requests.post( flood_status_url, json={"regionCode": iso2}, timeout=2 ).json() break except requests.RequestException as e: - logger.warning("Request failed: %s", e) - response = {} + logger.warning("Request failed at url %s: %s", flood_status_url, e) + status_response = {} - if "error" in response: - logger.error("Error in response: %s", response["error"]) + if "error" in status_response: + logger.error("Error in response: %s", status_response["error"]) raise HTTPException( status_code=500, detail="Error fetching flood status data from Google API" ) - gauges = response.get("floodStatuses", []) + initial_gauges = status_response.get("floodStatuses", []) + + gauge_params = urlencode( + {"names": [f"gauges/{gauge['gaugeId']}" for gauge in initial_gauges]}, + doseq=True, + ) + gauges_details_url = f"https://floodforecasting.googleapis.com/v1/gauges:batchGet?key={GOOGLE_FLOODS_API_KEY}&{gauge_params}" + + try: + details_response = requests.get(gauges_details_url, timeout=2).json() + except requests.RequestException as e: + logger.warning("Request failed at url %s: %s", gauges_details_url, e) + details_response = {} + + if "error" in details_response: + logger.error("Error in response: %s", details_response["error"]) + raise HTTPException( + status_code=500, detail="Error fetching gauges details from Google API" + ) + + # Create a map for quick lookup + gauge_details_map = { + item["gaugeId"]: item for item in details_response.get("gauges", []) + } + + gauges_details = [] + for gauge in initial_gauges: + gauge_id = gauge["gaugeId"] + detail = gauge_details_map.get(gauge_id, {}) + merged_gauge = {**gauge, **detail} + gauges_details.append(merged_gauge) if as_geojson: geojson_feature_collection = { "type": "FeatureCollection", - "features": [format_gauge_to_geojson(gauge) for gauge in gauges], + "features": [format_gauge_to_geojson(gauge) for gauge in gauges_details], } return geojson_feature_collection - return gauges + return gauges_details diff --git a/frontend/src/components/MapView/Layers/ImpactLayer/index.tsx b/frontend/src/components/MapView/Layers/ImpactLayer/index.tsx index d7274c47d..12f96b406 100644 --- a/frontend/src/components/MapView/Layers/ImpactLayer/index.tsx +++ b/frontend/src/components/MapView/Layers/ImpactLayer/index.tsx @@ -74,6 +74,7 @@ const onClick = dispatch( addPopupData( getFeatureInfoPropsData( + layer.featureInfoTitle || {}, layer.featureInfoProps || {}, coordinates, feature, diff --git a/frontend/src/components/MapView/Layers/layer-utils.tsx b/frontend/src/components/MapView/Layers/layer-utils.tsx index 99f08eca8..be7a6674f 100644 --- a/frontend/src/components/MapView/Layers/layer-utils.tsx +++ b/frontend/src/components/MapView/Layers/layer-utils.tsx @@ -86,6 +86,7 @@ export const addPopupParams = ( const { dataField, + featureInfoTitle, featureInfoProps, title, dataLabel, @@ -153,6 +154,7 @@ export const addPopupParams = ( : {}; const featureInfoPropsData = getFeatureInfoPropsData( + featureInfoTitle, featureInfoPropsWithFallback || {}, coordinates, feature, diff --git a/frontend/src/components/MapView/MapTooltip/index.tsx b/frontend/src/components/MapView/MapTooltip/index.tsx index 351b9230d..26f1683c2 100644 --- a/frontend/src/components/MapView/MapTooltip/index.tsx +++ b/frontend/src/components/MapView/MapTooltip/index.tsx @@ -1,4 +1,5 @@ import { memo, useCallback, useMemo, useState } from 'react'; +import { omit } from 'lodash'; import { useDispatch, useSelector } from 'react-redux'; import { Popup } from 'react-map-gl/maplibre'; import { @@ -7,7 +8,12 @@ import { IconButton, makeStyles, } from '@material-ui/core'; -import { hidePopup, tooltipSelector } from 'context/tooltipStateSlice'; +import { + hidePopup, + PopupData, + PopupMetaData, + tooltipSelector, +} from 'context/tooltipStateSlice'; import { isEnglishLanguageSelected, useSafeTranslation } from 'i18n'; import { AdminLevelType } from 'config/types'; import { appConfig } from 'config'; @@ -80,15 +86,19 @@ const MapTooltip = memo(() => { ); const { dataset, isLoading } = usePointDataChart(); - + const providedPopupTitle = popup.data.title; + const popupData = providedPopupTitle + ? (omit(popup.data, 'title') as PopupData & PopupMetaData) + : popup.data; const defaultPopupTitle = useMemo(() => { + if (providedPopupTitle) { + return providedPopupTitle.data; + } if (isEnglishLanguageSelected(i18n)) { return popup.locationName; } return popup.locationLocalName; - }, [i18n, popup.locationLocalName, popup.locationName]); - - const popupData = popup.data; + }, [i18n, popup.locationLocalName, popup.locationName, providedPopupTitle]); // TODO - simplify logic once we revamp admin levels object const adminLevelsNames = useCallback(() => { diff --git a/frontend/src/components/MapView/utils.ts b/frontend/src/components/MapView/utils.ts index 295850393..fac4bd430 100644 --- a/frontend/src/components/MapView/utils.ts +++ b/frontend/src/components/MapView/utils.ts @@ -6,7 +6,10 @@ import { formatFeatureInfo } from 'utils/server-utils'; import { AvailableDates, FeatureInfoObject, + FeatureInfoProps, + FeatureInfoTitle, FeatureInfoType, + FeatureInfoVisibility, LayerType, LegendDefinitionItem, WMSLayerProps, @@ -115,6 +118,30 @@ const sortKeys = (featureInfoProps: FeatureInfoObject): string[][] => { return [dataKeys, metaDataKeys]; }; +const getTitle = ( + featureInfoTitle: FeatureInfoTitle | undefined, + featureInfoProps: FeatureInfoObject, + properties: any, +): PopupData | {} => { + if (!featureInfoTitle) { + return {}; + } + const titleField = featureInfoTitle?.fields?.find( + (field: string) => !!properties[field], + ); + return titleField + ? { + title: { + data: formatFeatureInfo( + properties[titleField], + featureInfoProps[titleField].type, + featureInfoProps[titleField].labelMap, + ), + }, + } + : {}; +}; + const getMetaData = ( featureInfoProps: FeatureInfoObject, metaDataKeys: string[], @@ -136,24 +163,32 @@ const getData = ( coordinates: any, ) => Object.keys(properties) - .filter(prop => keys.includes(prop)) - .reduce( - (obj, item) => ({ + .filter(prop => keys.includes(prop) && prop !== 'title') + .reduce((obj, item) => { + const itemProps = featureInfoProps[item] as FeatureInfoProps; + if ( + itemProps.visibility === FeatureInfoVisibility.IfDefined && + !properties[item] + ) { + return obj; + } + + return { ...obj, - [featureInfoProps[item].dataTitle]: { + [itemProps.dataTitle]: { data: formatFeatureInfo( properties[item], - featureInfoProps[item].type, - featureInfoProps[item].labelMap, + itemProps.type, + itemProps.labelMap, ), coordinates, }, - }), - {}, - ); + }; + }, {}); // TODO: maplibre: fix feature export function getFeatureInfoPropsData( + featureInfoTitle: FeatureInfoTitle | undefined, featureInfoProps: FeatureInfoObject, coordinates: number[], feature: any, @@ -162,6 +197,7 @@ export function getFeatureInfoPropsData( const { properties } = feature; return { + ...getTitle(featureInfoTitle, featureInfoProps, properties), ...getMetaData(featureInfoProps, metaDataKeys, properties), ...getData(featureInfoProps, keys, properties, coordinates), }; diff --git a/frontend/src/config/mozambique/layers.json b/frontend/src/config/mozambique/layers.json index 004f3c1e7..aee847ea1 100644 --- a/frontend/src/config/mozambique/layers.json +++ b/frontend/src/config/mozambique/layers.json @@ -2955,45 +2955,59 @@ "end_date": "2021-07-31", "opacity": 0.7 }, - "google_flood_gauges": { - "title": "Google Flood Gauges", + "google_flood_status_at_gauges": { + "title": "Current Flood Status (Google AI)", "type": "point_data", "hex_display": false, "data": "http://0.0.0.0:80/google-floods/gauges/?region_code=MZ", "data_field": "severity", - "opacity": 0.7, - "legend_text": "Google Flood Gauges", + "data_field_type": "text", + "opacity": 0.9, + "legend_text": "Current flood status at verified gauges. Visit [Google Research](https://sites.research.google/floodforecasting/) about Google's AI Forecasting models.", "legend": [ - { - "label": "Extreme", - "value": "EXTREME", - "color": "#fa1a18" - }, - { - "label": "Severe", - "value": "SEVERE", - "color": "#fba12e" + { "label": "Extreme", "value": "EXTREME", "color": "#a70606" }, + { "label": "Danger", "value": "SEVERE", "color": "#ea250a" }, + { "label": "Warning", "value": "ABOVE_NORMAL", "color": "#fba705" }, + { "label": "Normal", "value": "NO_FLOODING", "color": "#089180" }, + { "label": "Unknown", "value": "UNKNOWN", "color": "#858585" } + ], + "feature_info_title": { + "fields": ["siteName", "river", "gaugeId"] + }, + "feature_info_props": { + "siteName": { + "type": "text", + "dataTitle": "Site", + "visibility": "if-defined" }, - { - "label": "Above Normal", - "value": "ABOVE_NORMAL", - "color": "#ffff43" + "river": { + "type": "text", + "dataTitle": "River", + "visibility": "if-defined" + }, + "severity": { + "type": "labelMapping", + "dataTitle": "Severity", + "labelMap": { + "EXTREME": "Extreme", + "SEVERE": "Danger", + "ABOVE_NORMAL": "Warning", + "NO_FLOODING": "Normal", + "UNKNOWN": "Unknown" + } }, - { - "label": "No Flooding", - "value": "NO_FLOODING", - "color": "#c5c5c5" + "gaugeId": { + "type": "text", + "dataTitle": "Gauge ID" }, - { - "label": "Unknown", - "value": "UNKNOWN", - "color": "#cefdba" + "source": { + "type": "text", + "dataTitle": "Data source" }, - { - "label": "Severity Unspecified", - "value": "SEVERITY_UNSPECIFIED", - "color": "#91e038" + "issuedTime": { + "type": "date", + "dataTitle": "Status issued" } - ] + } } } diff --git a/frontend/src/config/mozambique/prism.json b/frontend/src/config/mozambique/prism.json index 8160835de..cba3a6478 100644 --- a/frontend/src/config/mozambique/prism.json +++ b/frontend/src/config/mozambique/prism.json @@ -21,7 +21,7 @@ "tropical_storms": "icon_tropical_storm.png", "vulnerability": "icon_vulnerable.png", "exposure": "icon_basemap.png", - "flood": "icon_basemap.png" + "flooding": "icon_basemap.png" }, "defaultDisplayBoundaries": [ "admin_boundaries", @@ -456,8 +456,8 @@ "exposure": { "population": ["census"] }, - "flood": { - "flood_gauges": ["google_flood_gauges"] + "flooding": { + "flood_status": ["google_flood_status_at_gauges"] } } } diff --git a/frontend/src/config/types.ts b/frontend/src/config/types.ts index b029086c2..69fa5fdea 100644 --- a/frontend/src/config/types.ts +++ b/frontend/src/config/types.ts @@ -267,7 +267,9 @@ export enum Interval { ONE_YEAR = '1-year', } -export type FeatureInfoObject = { [key: string]: FeatureInfoProps }; +export type FeatureInfoObject = { + [key: string]: FeatureInfoProps; +}; export class CommonLayerProps { id: LayerKey; @@ -297,7 +299,9 @@ export class CommonLayerProps { contentPath?: string; @optional - featureInfoProps?: { [key: string]: FeatureInfoProps }; + featureInfoTitle?: FeatureInfoTitle; + @optional + featureInfoProps?: FeatureInfoObject; /* * only for layer that has grouped menu and always assigned to main layer of group (../components/Navbar/utils.ts) @@ -396,13 +400,23 @@ export enum DataType { LabelMapping = 'labelMapping', } +export enum FeatureInfoVisibility { + Always = 'always', // Default + IfDefined = 'if-defined', +} + type PopupMetaDataKeys = keyof PopupMetaData; -interface FeatureInfoProps { +export interface FeatureInfoTitle { + fields: string[]; +} + +export interface FeatureInfoProps { type: DataType; dataTitle: string; labelMap?: { [key: string]: string }; metadata?: PopupMetaDataKeys; + visibility?: FeatureInfoVisibility; } export enum DatesPropagation { From 0653f1ed71a4055f2783c8e24d143e3a7e542feb Mon Sep 17 00:00:00 2001 From: Will Gislason <8203830+gislawill@users.noreply.github.com> Date: Mon, 12 Aug 2024 14:05:04 -0700 Subject: [PATCH 05/19] copy update --- frontend/src/config/mozambique/layers.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/config/mozambique/layers.json b/frontend/src/config/mozambique/layers.json index aee847ea1..ed62d8648 100644 --- a/frontend/src/config/mozambique/layers.json +++ b/frontend/src/config/mozambique/layers.json @@ -2987,7 +2987,7 @@ }, "severity": { "type": "labelMapping", - "dataTitle": "Severity", + "dataTitle": "Flood Status", "labelMap": { "EXTREME": "Extreme", "SEVERE": "Danger", From 7cd866dcf4b6f8e1b63c295d7e543ce3849c1bdc Mon Sep 17 00:00:00 2001 From: Will Gislason <8203830+gislawill@users.noreply.github.com> Date: Mon, 12 Aug 2024 14:38:45 -0700 Subject: [PATCH 06/19] Refactor title state management --- .../components/MapView/MapTooltip/index.tsx | 7 +++-- frontend/src/components/MapView/utils.ts | 21 ++++++------- frontend/src/config/mozambique/layers.json | 16 +++++++++- frontend/src/config/types.ts | 11 +++++-- frontend/src/context/tooltipStateSlice.ts | 9 +++++- frontend/src/utils/server-utils.ts | 30 +++++++++++++++++++ 6 files changed, 77 insertions(+), 17 deletions(-) diff --git a/frontend/src/components/MapView/MapTooltip/index.tsx b/frontend/src/components/MapView/MapTooltip/index.tsx index 26f1683c2..3e018b453 100644 --- a/frontend/src/components/MapView/MapTooltip/index.tsx +++ b/frontend/src/components/MapView/MapTooltip/index.tsx @@ -12,6 +12,7 @@ import { hidePopup, PopupData, PopupMetaData, + PopupTitleData, tooltipSelector, } from 'context/tooltipStateSlice'; import { isEnglishLanguageSelected, useSafeTranslation } from 'i18n'; @@ -86,9 +87,9 @@ const MapTooltip = memo(() => { ); const { dataset, isLoading } = usePointDataChart(); - const providedPopupTitle = popup.data.title; - const popupData = providedPopupTitle - ? (omit(popup.data, 'title') as PopupData & PopupMetaData) + const providedPopupTitle = (popup.data as PopupTitleData).title; + const popupData: PopupData & PopupMetaData = providedPopupTitle + ? omit(popup.data, 'title', providedPopupTitle.prop) : popup.data; const defaultPopupTitle = useMemo(() => { if (providedPopupTitle) { diff --git a/frontend/src/components/MapView/utils.ts b/frontend/src/components/MapView/utils.ts index fac4bd430..69136c647 100644 --- a/frontend/src/components/MapView/utils.ts +++ b/frontend/src/components/MapView/utils.ts @@ -2,14 +2,14 @@ import { orderBy, snakeCase, values } from 'lodash'; import { TFunction } from 'i18next'; import { Dispatch } from 'redux'; import { LayerDefinitions } from 'config/utils'; -import { formatFeatureInfo } from 'utils/server-utils'; +import { formatFeatureInfo, formatFeatureTitle } from 'utils/server-utils'; import { AvailableDates, FeatureInfoObject, FeatureInfoProps, - FeatureInfoTitle, FeatureInfoType, FeatureInfoVisibility, + FeatureTitleObject, LayerType, LegendDefinitionItem, WMSLayerProps, @@ -119,23 +119,24 @@ const sortKeys = (featureInfoProps: FeatureInfoObject): string[][] => { }; const getTitle = ( - featureInfoTitle: FeatureInfoTitle | undefined, - featureInfoProps: FeatureInfoObject, + featureInfoTitle: FeatureTitleObject | undefined, properties: any, ): PopupData | {} => { if (!featureInfoTitle) { return {}; } - const titleField = featureInfoTitle?.fields?.find( + const titleField = Object.keys(featureInfoTitle).find( (field: string) => !!properties[field], ); return titleField ? { title: { - data: formatFeatureInfo( + prop: titleField, + data: formatFeatureTitle( properties[titleField], - featureInfoProps[titleField].type, - featureInfoProps[titleField].labelMap, + featureInfoTitle[titleField].type, + featureInfoTitle[titleField].template, + featureInfoTitle[titleField].labelMap, ), }, } @@ -188,7 +189,7 @@ const getData = ( // TODO: maplibre: fix feature export function getFeatureInfoPropsData( - featureInfoTitle: FeatureInfoTitle | undefined, + featureInfoTitle: FeatureTitleObject | undefined, featureInfoProps: FeatureInfoObject, coordinates: number[], feature: any, @@ -197,7 +198,7 @@ export function getFeatureInfoPropsData( const { properties } = feature; return { - ...getTitle(featureInfoTitle, featureInfoProps, properties), + ...getTitle(featureInfoTitle, properties), ...getMetaData(featureInfoProps, metaDataKeys, properties), ...getData(featureInfoProps, keys, properties, coordinates), }; diff --git a/frontend/src/config/mozambique/layers.json b/frontend/src/config/mozambique/layers.json index ed62d8648..917b65089 100644 --- a/frontend/src/config/mozambique/layers.json +++ b/frontend/src/config/mozambique/layers.json @@ -2972,7 +2972,21 @@ { "label": "Unknown", "value": "UNKNOWN", "color": "#858585" } ], "feature_info_title": { - "fields": ["siteName", "river", "gaugeId"] + "siteName": { + "type": "text", + "template": "Site: %s", + "visibility": "if-defined" + }, + "river": { + "type": "text", + "template": "River: %s", + "visibility": "if-defined" + }, + "gaugeId": { + "type": "text", + "template": "Gauge ID: %s", + "visibility": "if-defined" + } }, "feature_info_props": { "siteName": { diff --git a/frontend/src/config/types.ts b/frontend/src/config/types.ts index 69fa5fdea..508949c9a 100644 --- a/frontend/src/config/types.ts +++ b/frontend/src/config/types.ts @@ -267,6 +267,10 @@ export enum Interval { ONE_YEAR = '1-year', } +export type FeatureTitleObject = { + [key: string]: FeatureInfoTitle; +}; + export type FeatureInfoObject = { [key: string]: FeatureInfoProps; }; @@ -299,7 +303,7 @@ export class CommonLayerProps { contentPath?: string; @optional - featureInfoTitle?: FeatureInfoTitle; + featureInfoTitle?: FeatureTitleObject; @optional featureInfoProps?: FeatureInfoObject; @@ -408,7 +412,10 @@ export enum FeatureInfoVisibility { type PopupMetaDataKeys = keyof PopupMetaData; export interface FeatureInfoTitle { - fields: string[]; + type: DataType; + template: string; + labelMap?: { [key: string]: string }; + visibility?: FeatureInfoVisibility; } export interface FeatureInfoProps { diff --git a/frontend/src/context/tooltipStateSlice.ts b/frontend/src/context/tooltipStateSlice.ts index 471b697bc..dce6dab52 100644 --- a/frontend/src/context/tooltipStateSlice.ts +++ b/frontend/src/context/tooltipStateSlice.ts @@ -3,6 +3,13 @@ import { merge } from 'lodash'; import { AdminCodeString } from 'config/types'; import type { RootState } from './store'; +export interface PopupTitleData { + title: { + prop: string; + data: number | string | null; + }; +} + export interface PopupData { [key: string]: { data: number | string | null; @@ -22,7 +29,7 @@ export interface MapTooltipState { locationSelectorKey: string; locationName: string; locationLocalName: string; - data: PopupData & PopupMetaData; + data: (PopupData & PopupMetaData) | PopupTitleData; showing: boolean; wmsGetFeatureInfoLoading: boolean; } diff --git a/frontend/src/utils/server-utils.ts b/frontend/src/utils/server-utils.ts index 54d0c9d52..05662d0bf 100644 --- a/frontend/src/utils/server-utils.ts +++ b/frontend/src/utils/server-utils.ts @@ -767,6 +767,36 @@ export function formatFeatureInfo( return value; } +/** + * Format value into feature title response based on DataType and template provided + * + * @return a formatted string + */ +export function formatFeatureTitle( + value: string, + type: DataType, + template: string, + labelMap?: { [key: string]: string }, +): string { + let formattedValue = value; + + if (type === DataType.Date) { + // eslint-disable-next-line fp/no-mutation + formattedValue = getFormattedDate(value, 'locale') as string; + } + + if (type === DataType.LabelMapping) { + if (!labelMap) { + throw new Error('labelMap not defined.'); + } + + // eslint-disable-next-line fp/no-mutation + formattedValue = labelMap[value]; + } + + return template.replace('%s', formattedValue); +} + /** * Executes a getFeatureInfo request * From 94e15882f1b3fae0f0cbc1c4febdb486cdcbc768 Mon Sep 17 00:00:00 2001 From: Will Gislason <8203830+gislawill@users.noreply.github.com> Date: Mon, 12 Aug 2024 14:56:53 -0700 Subject: [PATCH 07/19] Fixing and adding server tests --- api/app/main.py | 3 +- api/app/tests/test_google_floods_api.py | 51 ++++++++++++++++++++---- frontend/src/components/MapView/utils.ts | 4 +- 3 files changed, 48 insertions(+), 10 deletions(-) diff --git a/api/app/main.py b/api/app/main.py index 265b05b72..067091110 100644 --- a/api/app/main.py +++ b/api/app/main.py @@ -419,7 +419,8 @@ def post_raster_geotiff(raster_geotiff: RasterGeotiffModel): def get_google_floods_gauges_api(region_code: str): if len(region_code) != 2: raise HTTPException( - status_code=400, detail="region code must be exactly two characters (iso2)." + status_code=400, + detail="region code must be provided and exactly two characters (iso2).", ) iso2 = region_code.upper() return get_google_floods_gauges(iso2) diff --git a/api/app/tests/test_google_floods_api.py b/api/app/tests/test_google_floods_api.py index ab5d38b22..1e1595b28 100644 --- a/api/app/tests/test_google_floods_api.py +++ b/api/app/tests/test_google_floods_api.py @@ -1,6 +1,3 @@ -import json -import logging - from app.googleflood import get_google_floods_gauges from app.main import app from fastapi.testclient import TestClient @@ -9,13 +6,51 @@ def test_get_google_floods_gauges(): + """ + This test is not used in the API, but is used to test the get_google_floods_gauges function + It is used to ensure that the get_google_floods_gauges function returns a valid GeoJSON object + """ gauges = get_google_floods_gauges("BD") - assert len(gauges) > 0 + assert gauges["type"] == "FeatureCollection" + for feature in gauges["features"]: + assert feature["geometry"]["type"] == "Point" + assert len(feature["geometry"]["coordinates"]) == 2 + assert "gaugeId" in feature["properties"] + assert "issuedTime" in feature["properties"] + assert "severity" in feature["properties"] def test_get_google_floods_gauges_api(): - response = client.get("/google-floods-gauges?iso2=BD") + """ + This test is used to test the API endpoint for getting Google Floods gauges + """ + response = client.get("/google-floods/gauges/?region_code=BD") + assert response.status_code == 200 + + response_geojson = response.json() + assert response_geojson["type"] == "FeatureCollection" + assert len(response_geojson["features"]) > 0 + + +def test_get_google_floods_gauges_api_case_insensitive(): + """ + This test is used to test the API endpoint for getting Google Floods gauges with a case insensitive region code + """ + response = client.get("/google-floods/gauges/?region_code=bd") assert response.status_code == 200 - logging.info(json.dumps(response.json())) - # logging.info(response.json()) - assert len(response.json()) > 0 + + response_geojson = response.json() + assert response_geojson["type"] == "FeatureCollection" + assert len(response_geojson["features"]) > 0 + + +def test_get_google_floods_gauges_api_requires_valid_region_code(): + """ + This test is used to test the API endpoint for getting Google Floods gauges with an invalid region code + """ + response = client.get("/google-floods/gauges/?region_code=usa") + assert response.status_code == 400 + assert ( + response.json()["detail"] + == "region code must be provided and exactly two characters (iso2)." + ) diff --git a/frontend/src/components/MapView/utils.ts b/frontend/src/components/MapView/utils.ts index 69136c647..822fd4087 100644 --- a/frontend/src/components/MapView/utils.ts +++ b/frontend/src/components/MapView/utils.ts @@ -126,7 +126,9 @@ const getTitle = ( return {}; } const titleField = Object.keys(featureInfoTitle).find( - (field: string) => !!properties[field], + (field: string) => + featureInfoTitle[field].visibility !== FeatureInfoVisibility.IfDefined || + !!properties[field], ); return titleField ? { From 6ac3aad96c771d67c87b0ce3f1b7f145ec284d20 Mon Sep 17 00:00:00 2001 From: ericboucher Date: Tue, 13 Aug 2024 14:19:53 +0200 Subject: [PATCH 08/19] update set_env --- api/set_envs.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/api/set_envs.sh b/api/set_envs.sh index 450536e89..b67113051 100644 --- a/api/set_envs.sh +++ b/api/set_envs.sh @@ -18,5 +18,8 @@ export HDC_TOKEN=$(aws secretsmanager get-secret-value --secret-id HDC_TOKEN export ACLED_API_KEY=$(aws secretsmanager get-secret-value --secret-id ACLED_CREDENTIALS | jq .SecretString | jq fromjson | jq -r .ACLED_API_KEY) export ACLED_API_EMAIL=$(aws secretsmanager get-secret-value --secret-id ACLED_CREDENTIALS | jq .SecretString | jq fromjson | jq -r .ACLED_API_EMAIL) +# Google Flood +export GOOGLE_FLOODS_API_KEY=$(aws secretsmanager get-secret-value --secret-id GOOGLE_FLOODS_API_KEY | jq .SecretString | jq fromjson | jq -r .GOOGLE_FLOODS_API_KEY) + export HOSTNAME=prism-api.ovio.org export INFO_EMAIL=info@ovio.org From 6be26d7cb5a18f537ef1fd1858622d95f803a5ae Mon Sep 17 00:00:00 2001 From: ericboucher Date: Tue, 13 Aug 2024 19:56:18 +0200 Subject: [PATCH 09/19] update snapshots --- .../MapView/__snapshots__/index.test.tsx.snap | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/frontend/src/components/MapView/__snapshots__/index.test.tsx.snap b/frontend/src/components/MapView/__snapshots__/index.test.tsx.snap index 945ea39ae..85c77fb86 100644 --- a/frontend/src/components/MapView/__snapshots__/index.test.tsx.snap +++ b/frontend/src/components/MapView/__snapshots__/index.test.tsx.snap @@ -306,6 +306,52 @@ exports[`renders as expected 1`] = ` +
+ +
Date: Tue, 20 Aug 2024 17:29:06 -0700 Subject: [PATCH 10/19] Adding support for multi country deployments and adding google flood api key to docker compose --- api/app/googleflood.py | 42 ++++++++----- api/app/main.py | 21 +++++-- api/docker-compose.deploy.yml | 1 + api/docker-compose.develop.yml | 1 + frontend/src/config/mozambique/layers.json | 2 +- frontend/src/config/rbd/layers.json | 69 ++++++++++++++++++++++ frontend/src/config/rbd/prism.json | 6 +- 7 files changed, 120 insertions(+), 22 deletions(-) diff --git a/api/app/googleflood.py b/api/app/googleflood.py index 1f1f95ba9..d00bf108a 100644 --- a/api/app/googleflood.py +++ b/api/app/googleflood.py @@ -1,6 +1,7 @@ """Get data from Google Floods API""" import logging +from concurrent.futures import ThreadPoolExecutor, as_completed from os import getenv from urllib.parse import urlencode @@ -42,30 +43,41 @@ def format_gauge_to_geojson(data): return geojson -def get_google_floods_gauges( - iso2: str, - as_geojson: bool = True, -): - """Get statistical charts data""" - # Retry 3 times due to intermittent API errors +def fetch_flood_status(region_code): + """Fetch flood status for a region code""" flood_status_url = f"https://floodforecasting.googleapis.com/v1/floodStatus:searchLatestFloodStatusByArea?key={GOOGLE_FLOODS_API_KEY}" for _ in range(3): try: status_response = requests.post( - flood_status_url, json={"regionCode": iso2}, timeout=2 + flood_status_url, json={"regionCode": region_code}, timeout=2 ).json() - break + return status_response except requests.RequestException as e: logger.warning("Request failed at url %s: %s", flood_status_url, e) - status_response = {} + return {} - if "error" in status_response: - logger.error("Error in response: %s", status_response["error"]) - raise HTTPException( - status_code=500, detail="Error fetching flood status data from Google API" - ) - initial_gauges = status_response.get("floodStatuses", []) +def get_google_floods_gauges( + region_codes: list[str], + as_geojson: bool = True, +): + """Get statistical charts data""" + initial_gauges = [] + + # Retry 3 times due to intermittent API errors + with ThreadPoolExecutor() as executor: + future_to_region = { + executor.submit(fetch_flood_status, code): code for code in region_codes + } + for future in as_completed(future_to_region): + status_response = future.result() + if "error" in status_response: + logger.error("Error in response: %s", status_response["error"]) + raise HTTPException( + status_code=500, + detail="Error fetching flood status data from Google API", + ) + initial_gauges.extend(status_response.get("floodStatuses", [])) gauge_params = urlencode( {"names": [f"gauges/{gauge['gaugeId']}" for gauge in initial_gauges]}, diff --git a/api/app/main.py b/api/app/main.py index 067091110..4a866cf74 100644 --- a/api/app/main.py +++ b/api/app/main.py @@ -416,11 +416,22 @@ def post_raster_geotiff(raster_geotiff: RasterGeotiffModel): @app.get("/google-floods/gauges/") -def get_google_floods_gauges_api(region_code: str): - if len(region_code) != 2: +def get_google_floods_gauges_api(region_codes: list[str] = Query(...)): + """ + Get the Google Floods gauges for a list of regions. + """ + if not region_codes: raise HTTPException( status_code=400, - detail="region code must be provided and exactly two characters (iso2).", + detail="At least one region code must be provided.", ) - iso2 = region_code.upper() - return get_google_floods_gauges(iso2) + + for region_code in region_codes: + if len(region_code) != 2: + raise HTTPException( + status_code=400, + detail=f"Region code '{region_code}' must be exactly two characters (iso2).", + ) + + iso2_codes = [region_code.upper() for region_code in region_codes] + return get_google_floods_gauges(iso2_codes) diff --git a/api/docker-compose.deploy.yml b/api/docker-compose.deploy.yml index b1427ec32..eebedd784 100644 --- a/api/docker-compose.deploy.yml +++ b/api/docker-compose.deploy.yml @@ -52,6 +52,7 @@ services: - HDC_TOKEN=${HDC_TOKEN:?"Provide a token to access HDC chart data."} - STAC_AWS_ACCESS_KEY_ID=${STAC_AWS_ACCESS_KEY_ID:?"Provide the AWS access key for the stac api."} - STAC_AWS_SECRET_ACCESS_KEY=${STAC_AWS_SECRET_ACCESS_KEY:?"Provide the AWS secret key for the stac api."} + - GOOGLE_FLOODS_API_KEY=${GOOGLE_FLOODS_API_KEY:?"Provide the Google Floods API key."} command: uvicorn app.main:app --host 0.0.0.0 --port 80 restart: always # adding a DNS to allow self lookup of the api diff --git a/api/docker-compose.develop.yml b/api/docker-compose.develop.yml index b74eff683..50c729cc2 100644 --- a/api/docker-compose.develop.yml +++ b/api/docker-compose.develop.yml @@ -23,6 +23,7 @@ services: - KOBO_USERNAME=${KOBO_USERNAME:?"Add a user to access KOBO data."} - STAC_AWS_ACCESS_KEY_ID=${STAC_AWS_ACCESS_KEY_ID} - STAC_AWS_SECRET_ACCESS_KEY=${STAC_AWS_SECRET_ACCESS_KEY} + - GOOGLE_FLOODS_API_KEY=${GOOGLE_FLOODS_API_KEY} command: uvicorn app.main:app --host 0.0.0.0 --port 80 --reload # Infinite loop, to keep it alive, for debugging # command: bash -c "while true; do echo 'sleeping...' && sleep 10; done" diff --git a/frontend/src/config/mozambique/layers.json b/frontend/src/config/mozambique/layers.json index 917b65089..216f636e3 100644 --- a/frontend/src/config/mozambique/layers.json +++ b/frontend/src/config/mozambique/layers.json @@ -2959,7 +2959,7 @@ "title": "Current Flood Status (Google AI)", "type": "point_data", "hex_display": false, - "data": "http://0.0.0.0:80/google-floods/gauges/?region_code=MZ", + "data": "http://0.0.0.0:80/google-floods/gauges/?region_codes=MZ", "data_field": "severity", "data_field_type": "text", "opacity": 0.9, diff --git a/frontend/src/config/rbd/layers.json b/frontend/src/config/rbd/layers.json index e4de325a5..728a7d4d9 100644 --- a/frontend/src/config/rbd/layers.json +++ b/frontend/src/config/rbd/layers.json @@ -6531,5 +6531,74 @@ } ], "legend_text": "Joint Food Security & Nutrition Hotspot Analysis conducted by WFP, UNICEF, and partners based on SMART surveys and Cadre Harmonisé (CH) & Integrated Food Security Phase Classification (IPC) analyses" + }, + "google_flood_status_at_gauges": { + "title": "Current Flood Status (Google AI)", + "type": "point_data", + "hex_display": false, + "data": "http://0.0.0.0:80/google-floods/gauges/?region_codes=BF®ion_codes=CM®ion_codes=TD®ion_codes=GH®ion_codes=ML®ion_codes=MR®ion_codes=NE®ion_codes=SL®ion_codes=CI®ion_codes=GN®ion_codes=SN®ion_codes=GM®ion_codes=GW®ion_codes=LR®ion_codes=TG®ion_codes=BJ®ion_codes=NG®ion_codes=CF", + "data_field": "severity", + "data_field_type": "text", + "opacity": 0.9, + "legend_text": "Current flood status at verified gauges. Visit [Google Research](https://sites.research.google/floodforecasting/) about Google's AI Forecasting models.", + "legend": [ + { "label": "Extreme", "value": "EXTREME", "color": "#a70606" }, + { "label": "Danger", "value": "SEVERE", "color": "#ea250a" }, + { "label": "Warning", "value": "ABOVE_NORMAL", "color": "#fba705" }, + { "label": "Normal", "value": "NO_FLOODING", "color": "#089180" }, + { "label": "Unknown", "value": "UNKNOWN", "color": "#858585" } + ], + "feature_info_title": { + "siteName": { + "type": "text", + "template": "Site: %s", + "visibility": "if-defined" + }, + "river": { + "type": "text", + "template": "River: %s", + "visibility": "if-defined" + }, + "gaugeId": { + "type": "text", + "template": "Gauge ID: %s", + "visibility": "if-defined" + } + }, + "feature_info_props": { + "siteName": { + "type": "text", + "dataTitle": "Site", + "visibility": "if-defined" + }, + "river": { + "type": "text", + "dataTitle": "River", + "visibility": "if-defined" + }, + "severity": { + "type": "labelMapping", + "dataTitle": "Flood Status", + "labelMap": { + "EXTREME": "Extreme", + "SEVERE": "Danger", + "ABOVE_NORMAL": "Warning", + "NO_FLOODING": "Normal", + "UNKNOWN": "Unknown" + } + }, + "gaugeId": { + "type": "text", + "dataTitle": "Gauge ID" + }, + "source": { + "type": "text", + "dataTitle": "Data source" + }, + "issuedTime": { + "type": "date", + "dataTitle": "Status issued" + } + } } } diff --git a/frontend/src/config/rbd/prism.json b/frontend/src/config/rbd/prism.json index e656b0013..6ff161149 100644 --- a/frontend/src/config/rbd/prism.json +++ b/frontend/src/config/rbd/prism.json @@ -11,7 +11,8 @@ "risk_analysis": "icon_table.png", "rainfall": "icon_rain.png", "vegetation": "icon_veg.png", - "temperature": "icon_climate.png" + "temperature": "icon_climate.png", + "flooding": "icon_basemap.png" }, "alertFormActive": false, "serversUrls": { @@ -439,6 +440,9 @@ "mdr_fsn_outcomes", "mdr_index" ] + }, + "flooding": { + "flood_status": ["google_flood_status_at_gauges"] } } } From efdf2c92f5b93e95e61430835d2e97630c58d450 Mon Sep 17 00:00:00 2001 From: Will Gislason <8203830+gislawill@users.noreply.github.com> Date: Tue, 20 Aug 2024 17:51:01 -0700 Subject: [PATCH 11/19] Use interpolation for popup titles --- .../components/MapView/MapTooltip/index.tsx | 14 +++++++-- frontend/src/components/MapView/utils.ts | 12 ++++---- frontend/src/config/mozambique/layers.json | 6 ++-- frontend/src/config/rbd/layers.json | 6 ++-- frontend/src/context/tooltipStateSlice.ts | 3 ++ frontend/src/utils/server-utils.ts | 30 ------------------- 6 files changed, 25 insertions(+), 46 deletions(-) diff --git a/frontend/src/components/MapView/MapTooltip/index.tsx b/frontend/src/components/MapView/MapTooltip/index.tsx index 3e018b453..9e7057b59 100644 --- a/frontend/src/components/MapView/MapTooltip/index.tsx +++ b/frontend/src/components/MapView/MapTooltip/index.tsx @@ -80,26 +80,34 @@ const MapTooltip = memo(() => { const classes = useStyles(); const dispatch = useDispatch(); const popup = useSelector(tooltipSelector); - const { i18n } = useSafeTranslation(); + const { t, i18n } = useSafeTranslation(); const [popupTitle, setPopupTitle] = useState(''); const [adminLevel, setAdminLevel] = useState( undefined, ); const { dataset, isLoading } = usePointDataChart(); + const providedPopupTitle = (popup.data as PopupTitleData).title; const popupData: PopupData & PopupMetaData = providedPopupTitle ? omit(popup.data, 'title', providedPopupTitle.prop) : popup.data; const defaultPopupTitle = useMemo(() => { if (providedPopupTitle) { - return providedPopupTitle.data; + // Title can be a template requiring interpolation + return t(providedPopupTitle.data as string, providedPopupTitle.context); } if (isEnglishLanguageSelected(i18n)) { return popup.locationName; } return popup.locationLocalName; - }, [i18n, popup.locationLocalName, popup.locationName, providedPopupTitle]); + }, [ + i18n, + popup.locationLocalName, + popup.locationName, + providedPopupTitle, + t, + ]); // TODO - simplify logic once we revamp admin levels object const adminLevelsNames = useCallback(() => { diff --git a/frontend/src/components/MapView/utils.ts b/frontend/src/components/MapView/utils.ts index 822fd4087..94c870eeb 100644 --- a/frontend/src/components/MapView/utils.ts +++ b/frontend/src/components/MapView/utils.ts @@ -2,7 +2,7 @@ import { orderBy, snakeCase, values } from 'lodash'; import { TFunction } from 'i18next'; import { Dispatch } from 'redux'; import { LayerDefinitions } from 'config/utils'; -import { formatFeatureInfo, formatFeatureTitle } from 'utils/server-utils'; +import { formatFeatureInfo } from 'utils/server-utils'; import { AvailableDates, FeatureInfoObject, @@ -134,12 +134,10 @@ const getTitle = ( ? { title: { prop: titleField, - data: formatFeatureTitle( - properties[titleField], - featureInfoTitle[titleField].type, - featureInfoTitle[titleField].template, - featureInfoTitle[titleField].labelMap, - ), + data: featureInfoTitle[titleField].template, + context: { + [titleField]: properties[titleField], + }, }, } : {}; diff --git a/frontend/src/config/mozambique/layers.json b/frontend/src/config/mozambique/layers.json index 216f636e3..b92b46157 100644 --- a/frontend/src/config/mozambique/layers.json +++ b/frontend/src/config/mozambique/layers.json @@ -2974,17 +2974,17 @@ "feature_info_title": { "siteName": { "type": "text", - "template": "Site: %s", + "template": "Site: {{siteName}}", "visibility": "if-defined" }, "river": { "type": "text", - "template": "River: %s", + "template": "River: {{riverName}}", "visibility": "if-defined" }, "gaugeId": { "type": "text", - "template": "Gauge ID: %s", + "template": "Gauge ID: {{gaugeId}}", "visibility": "if-defined" } }, diff --git a/frontend/src/config/rbd/layers.json b/frontend/src/config/rbd/layers.json index 728a7d4d9..570811ccc 100644 --- a/frontend/src/config/rbd/layers.json +++ b/frontend/src/config/rbd/layers.json @@ -6551,17 +6551,17 @@ "feature_info_title": { "siteName": { "type": "text", - "template": "Site: %s", + "template": "Site: {{siteName}}", "visibility": "if-defined" }, "river": { "type": "text", - "template": "River: %s", + "template": "River: {{riverName}}", "visibility": "if-defined" }, "gaugeId": { "type": "text", - "template": "Gauge ID: %s", + "template": "Gauge ID: {{gaugeId}}", "visibility": "if-defined" } }, diff --git a/frontend/src/context/tooltipStateSlice.ts b/frontend/src/context/tooltipStateSlice.ts index dce6dab52..265b7da8e 100644 --- a/frontend/src/context/tooltipStateSlice.ts +++ b/frontend/src/context/tooltipStateSlice.ts @@ -7,6 +7,9 @@ export interface PopupTitleData { title: { prop: string; data: number | string | null; + context?: { + [key: string]: string; + }; }; } diff --git a/frontend/src/utils/server-utils.ts b/frontend/src/utils/server-utils.ts index 05662d0bf..54d0c9d52 100644 --- a/frontend/src/utils/server-utils.ts +++ b/frontend/src/utils/server-utils.ts @@ -767,36 +767,6 @@ export function formatFeatureInfo( return value; } -/** - * Format value into feature title response based on DataType and template provided - * - * @return a formatted string - */ -export function formatFeatureTitle( - value: string, - type: DataType, - template: string, - labelMap?: { [key: string]: string }, -): string { - let formattedValue = value; - - if (type === DataType.Date) { - // eslint-disable-next-line fp/no-mutation - formattedValue = getFormattedDate(value, 'locale') as string; - } - - if (type === DataType.LabelMapping) { - if (!labelMap) { - throw new Error('labelMap not defined.'); - } - - // eslint-disable-next-line fp/no-mutation - formattedValue = labelMap[value]; - } - - return template.replace('%s', formattedValue); -} - /** * Executes a getFeatureInfo request * From 8fa327c117e5561990179c5f8b92c1850165f638 Mon Sep 17 00:00:00 2001 From: Will Gislason <8203830+gislawill@users.noreply.github.com> Date: Tue, 20 Aug 2024 18:20:08 -0700 Subject: [PATCH 12/19] Adding pytest-recording --- .../test_get_google_floods_gauges.yaml | 213 +++++++++++++++ .../test_get_google_floods_gauges_api.yaml | 258 ++++++++++++++++++ ...le_floods_gauges_api_case_insensitive.yaml | 258 ++++++++++++++++++ ...gauges_api_requires_valid_region_code.yaml | 28 ++ api/app/tests/test_google_floods_api.py | 17 +- api/poetry.lock | 122 ++++++++- api/pyproject.toml | 1 + 7 files changed, 889 insertions(+), 8 deletions(-) create mode 100644 api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges.yaml create mode 100644 api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api.yaml create mode 100644 api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api_case_insensitive.yaml create mode 100644 api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api_requires_valid_region_code.yaml diff --git a/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges.yaml b/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges.yaml new file mode 100644 index 000000000..103eaa121 --- /dev/null +++ b/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges.yaml @@ -0,0 +1,213 @@ +interactions: +- request: + body: '{"regionCode": "BD"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '20' + Content-Type: + - application/json + User-Agent: + - python-requests/2.32.0 + method: POST + uri: https://floodforecasting.googleapis.com/v1/floodStatus:searchLatestFloodStatusByArea + response: + body: + string: !!binary | + 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 + headers: + Alt-Svc: + - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 + Cache-Control: + - private + Content-Encoding: + - gzip + Content-Type: + - application/json; charset=UTF-8 + Date: + - Wed, 21 Aug 2024 01:18:30 GMT + Server: + - ESF + Server-Timing: + - gfet4t7; dur=404 + Transfer-Encoding: + - chunked + Vary: + - Origin + - X-Origin + - Referer + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-XSS-Protection: + - '0' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.32.0 + method: GET + uri: https://floodforecasting.googleapis.com/v1/gauges:batchGet?names=gauges%2FBWDB_SW101&names=gauges%2FBWDB_SW110&names=gauges%2FBWDB_SW117&names=gauges%2FBWDB_SW119.1&names=gauges%2FBWDB_SW131.5&names=gauges%2FBWDB_SW132.2&names=gauges%2FBWDB_SW133&names=gauges%2FBWDB_SW137A&names=gauges%2FBWDB_SW14.5&names=gauges%2FBWDB_SW140&names=gauges%2FBWDB_SW142.1&names=gauges%2FBWDB_SW145&names=gauges%2FBWDB_SW147.5&names=gauges%2FBWDB_SW157&names=gauges%2FBWDB_SW159&names=gauges%2FBWDB_SW15J&names=gauges%2FBWDB_SW162&names=gauges%2FBWDB_SW172&names=gauges%2FBWDB_SW173&names=gauges%2FBWDB_SW175.5&names=gauges%2FBWDB_SW177&names=gauges%2FBWDB_SW179&names=gauges%2FBWDB_SW201&names=gauges%2FBWDB_SW202&names=gauges%2FBWDB_SW203&names=gauges%2FBWDB_SW204&names=gauges%2FBWDB_SW206&names=gauges%2FBWDB_SW207&names=gauges%2FBWDB_SW211.5&names=gauges%2FBWDB_SW212&names=gauges%2FBWDB_SW225&names=gauges%2FBWDB_SW228&names=gauges%2FBWDB_SW236&names=gauges%2FBWDB_SW238&names=gauges%2FBWDB_SW247&names=gauges%2FBWDB_SW248&names=gauges%2FBWDB_SW251&names=gauges%2FBWDB_SW263&names=gauges%2FBWDB_SW263.1&names=gauges%2FBWDB_SW266&names=gauges%2FBWDB_SW267&names=gauges%2FBWDB_SW269&names=gauges%2FBWDB_SW269.5&names=gauges%2FBWDB_SW270&names=gauges%2FBWDB_SW273&names=gauges%2FBWDB_SW274&names=gauges%2FBWDB_SW275.5&names=gauges%2FBWDB_SW277&names=gauges%2FBWDB_SW285&names=gauges%2FBWDB_SW291.5R&names=gauges%2FBWDB_SW294&names=gauges%2FBWDB_SW299&names=gauges%2FBWDB_SW302&names=gauges%2FBWDB_SW36&names=gauges%2FBWDB_SW3A&names=gauges%2FBWDB_SW42&names=gauges%2FBWDB_SW45&names=gauges%2FBWDB_SW45.5&names=gauges%2FBWDB_SW46.9L&names=gauges%2FBWDB_SW49&names=gauges%2FBWDB_SW49A&names=gauges%2FBWDB_SW5&names=gauges%2FBWDB_SW50.6&names=gauges%2FBWDB_SW62&names=gauges%2FBWDB_SW63&names=gauges%2FBWDB_SW65&names=gauges%2FBWDB_SW67&names=gauges%2FBWDB_SW68.5&names=gauges%2FBWDB_SW71A&names=gauges%2FBWDB_SW72&names=gauges%2FBWDB_SW77&names=gauges%2FBWDB_SW84&names=gauges%2FBWDB_SW88&names=gauges%2FBWDB_SW88A&names=gauges%2FBWDB_SW90&names=gauges%2FBWDB_SW91.9R&names=gauges%2FBWDB_SW93.4L&names=gauges%2FBWDB_SW93.5L&names=gauges%2FBWDB_SW95&names=gauges%2FBWDB_SW99&names=gauges%2FCWC_012-MDSIL + response: + body: + string: !!binary | + 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 + 6aEmTTd+LkvDf//54o8X/wHapSYWR04AAA== + headers: + Alt-Svc: + - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 + Cache-Control: + - private + Content-Encoding: + - gzip + Content-Type: + - application/json; charset=UTF-8 + Date: + - Wed, 21 Aug 2024 01:18:31 GMT + Server: + - ESF + Server-Timing: + - gfet4t7; dur=132 + Transfer-Encoding: + - chunked + Vary: + - Origin + - X-Origin + - Referer + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-XSS-Protection: + - '0' + status: + code: 200 + message: OK +version: 1 diff --git a/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api.yaml b/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api.yaml new file mode 100644 index 000000000..b7627b870 --- /dev/null +++ b/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api.yaml @@ -0,0 +1,258 @@ +interactions: +- request: + body: '{"regionCode": "BD"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '20' + Content-Type: + - application/json + User-Agent: + - python-requests/2.32.0 + method: POST + uri: https://floodforecasting.googleapis.com/v1/floodStatus:searchLatestFloodStatusByArea + response: + body: + string: !!binary | + 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 + headers: + Alt-Svc: + - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 + Cache-Control: + - private + Content-Encoding: + - gzip + Content-Type: + - application/json; charset=UTF-8 + Date: + - Wed, 21 Aug 2024 01:18:31 GMT + Server: + - ESF + Server-Timing: + - gfet4t7; dur=361 + Transfer-Encoding: + - chunked + Vary: + - Origin + - X-Origin + - Referer + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-XSS-Protection: + - '0' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.32.0 + method: GET + uri: https://floodforecasting.googleapis.com/v1/gauges:batchGet?names=gauges%2FBWDB_SW101&names=gauges%2FBWDB_SW110&names=gauges%2FBWDB_SW117&names=gauges%2FBWDB_SW119.1&names=gauges%2FBWDB_SW131.5&names=gauges%2FBWDB_SW132.2&names=gauges%2FBWDB_SW133&names=gauges%2FBWDB_SW137A&names=gauges%2FBWDB_SW14.5&names=gauges%2FBWDB_SW140&names=gauges%2FBWDB_SW142.1&names=gauges%2FBWDB_SW145&names=gauges%2FBWDB_SW147.5&names=gauges%2FBWDB_SW157&names=gauges%2FBWDB_SW159&names=gauges%2FBWDB_SW15J&names=gauges%2FBWDB_SW162&names=gauges%2FBWDB_SW172&names=gauges%2FBWDB_SW173&names=gauges%2FBWDB_SW175.5&names=gauges%2FBWDB_SW177&names=gauges%2FBWDB_SW179&names=gauges%2FBWDB_SW201&names=gauges%2FBWDB_SW202&names=gauges%2FBWDB_SW203&names=gauges%2FBWDB_SW204&names=gauges%2FBWDB_SW206&names=gauges%2FBWDB_SW207&names=gauges%2FBWDB_SW211.5&names=gauges%2FBWDB_SW212&names=gauges%2FBWDB_SW225&names=gauges%2FBWDB_SW228&names=gauges%2FBWDB_SW236&names=gauges%2FBWDB_SW238&names=gauges%2FBWDB_SW247&names=gauges%2FBWDB_SW248&names=gauges%2FBWDB_SW251&names=gauges%2FBWDB_SW263&names=gauges%2FBWDB_SW263.1&names=gauges%2FBWDB_SW266&names=gauges%2FBWDB_SW267&names=gauges%2FBWDB_SW269&names=gauges%2FBWDB_SW269.5&names=gauges%2FBWDB_SW270&names=gauges%2FBWDB_SW273&names=gauges%2FBWDB_SW274&names=gauges%2FBWDB_SW275.5&names=gauges%2FBWDB_SW277&names=gauges%2FBWDB_SW285&names=gauges%2FBWDB_SW291.5R&names=gauges%2FBWDB_SW294&names=gauges%2FBWDB_SW299&names=gauges%2FBWDB_SW302&names=gauges%2FBWDB_SW36&names=gauges%2FBWDB_SW3A&names=gauges%2FBWDB_SW42&names=gauges%2FBWDB_SW45&names=gauges%2FBWDB_SW45.5&names=gauges%2FBWDB_SW46.9L&names=gauges%2FBWDB_SW49&names=gauges%2FBWDB_SW49A&names=gauges%2FBWDB_SW5&names=gauges%2FBWDB_SW50.6&names=gauges%2FBWDB_SW62&names=gauges%2FBWDB_SW63&names=gauges%2FBWDB_SW65&names=gauges%2FBWDB_SW67&names=gauges%2FBWDB_SW68.5&names=gauges%2FBWDB_SW71A&names=gauges%2FBWDB_SW72&names=gauges%2FBWDB_SW77&names=gauges%2FBWDB_SW84&names=gauges%2FBWDB_SW88&names=gauges%2FBWDB_SW88A&names=gauges%2FBWDB_SW90&names=gauges%2FBWDB_SW91.9R&names=gauges%2FBWDB_SW93.4L&names=gauges%2FBWDB_SW93.5L&names=gauges%2FBWDB_SW95&names=gauges%2FBWDB_SW99&names=gauges%2FCWC_012-MDSIL + response: + body: + string: !!binary | + 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 + 6aEmTTd+LkvDf//54o8X/wHapSYWR04AAA== + headers: + Alt-Svc: + - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 + Cache-Control: + - private + Content-Encoding: + - gzip + Content-Type: + - application/json; charset=UTF-8 + Date: + - Wed, 21 Aug 2024 01:18:32 GMT + Server: + - ESF + Server-Timing: + - gfet4t7; dur=126 + Transfer-Encoding: + - chunked + Vary: + - Origin + - X-Origin + - Referer + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-XSS-Protection: + - '0' + status: + code: 200 + message: OK +- request: + body: '' + headers: + accept: + - '*/*' + accept-encoding: + - gzip, deflate + connection: + - keep-alive + host: + - testserver + user-agent: + - testclient + method: GET + uri: http://testserver/google-floods/gauges/?region_codes=BD + response: + body: + string: '{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[91.389698,24.691644]},"properties":{"gaugeId":"BWDB_SW270","issuedTime":"2024-08-21T01:11:04.800016Z","siteName":"Markuli","river":"Surma-Meghna","severity":"SEVERE","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"f618d9d0b41047e5a73e0352c54737cb"},{"level":"MEDIUM","serializedPolygonId":"5ac17564f96c416aa65622210f7be455"},{"level":"LOW","serializedPolygonId":"3d8b39f6fc0b45df9d6ac2945a8a57b2"}],"inundationMapsTimeRange":{"start":"2024-08-22T09:00:00Z","end":"2024-08-22T09:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.431068,24.737208]},"properties":{"gaugeId":"BWDB_SW228","issuedTime":"2024-08-21T01:09:48.625563Z","siteName":"Mymensingh","river":"Old + Brahmaputra","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.553699,24.368824]},"properties":{"gaugeId":"BWDB_SW88","issuedTime":"2024-08-21T01:02:43.741872Z","siteName":"Rajshahi","river":"Ganges","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.438231,23.221259]},"properties":{"gaugeId":"BWDB_SW212","issuedTime":"2024-08-21T01:02:43.741974Z","siteName":"Parshuram","river":"Muhuri","severity":"SEVERE","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"3047087919894a6b8fdce086515cc171"},{"level":"MEDIUM","serializedPolygonId":"84c6899783e149eeabcdc05c6ec149e0"},{"level":"LOW","serializedPolygonId":"6544a995d4fd4ff5b5de00c8f261dd1b"}],"inundationMapsTimeRange":{"start":"2024-08-20T09:00:00Z","end":"2024-08-20T09:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.485642,24.872495]},"properties":{"gaugeId":"BWDB_SW172","issuedTime":"2024-08-21T01:02:43.752334Z","siteName":"Amalshid","river":"Kushiyara","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.119442,23.956966]},"properties":{"gaugeId":"BWDB_SW3A","issuedTime":"2024-08-21T01:02:43.753813Z","siteName":"B. + Baria","river":"Titas","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.774876,24.496424]},"properties":{"gaugeId":"BWDB_SW202","issuedTime":"2024-08-21T01:02:43.747282Z","siteName":"Moulvibazar","river":"Manu","severity":"ABOVE_NORMAL","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"0bca00b745534e5d9f97637c845445af"},{"level":"MEDIUM","serializedPolygonId":"d6d0fa09a1fb472ebc33248431455131"},{"level":"LOW","serializedPolygonId":"4c3976049e454c608c082f9ebfbd9b2a"}],"inundationMapsTimeRange":{"start":"2024-08-20T06:00:00Z","end":"2024-08-20T06:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.063472,22.15791]},"properties":{"gaugeId":"BWDB_SW248","issuedTime":"2024-08-21T01:02:44.639650Z","siteName":"Dohazari","river":"Sangu","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.703954,22.968128]},"properties":{"gaugeId":"BWDB_SW84","issuedTime":"2024-08-21T01:02:43.752323Z","siteName":"Ramgarh","river":"Feni","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.580654,24.891637]},"properties":{"gaugeId":"BWDB_SW15J","issuedTime":"2024-08-21T01:02:43.751949Z","siteName":"Sariakandi + (Mathurapara)","river":"Jamuna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.265191,25.004479]},"properties":{"gaugeId":"BWDB_SW266","issuedTime":"2024-08-21T01:11:03.131730Z","siteName":"Kanaighat","river":"Surma","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.618762,25.689237]},"properties":{"gaugeId":"BWDB_SW236","issuedTime":"2024-08-21T01:02:43.752832Z","siteName":"Dinajpur","river":"Punarbhaba","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.460897,26.03796]},"properties":{"gaugeId":"BWDB_SW285","issuedTime":"2024-08-21T01:10:48.136382Z","siteName":"Thakurgaon","river":"Tangon","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.744249,24.916416]},"properties":{"gaugeId":"BWDB_SW145","issuedTime":"2024-08-21T01:02:43.750317Z","siteName":"Mohadebpur","river":"Atrai","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.096763,23.101868]},"properties":{"gaugeId":"BWDB_SW162","issuedTime":"2024-08-21T01:02:44.417982Z","siteName":"Jhikargacha","river":"Kobadak","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.19839,23.471078]},"properties":{"gaugeId":"BWDB_SW110","issuedTime":"2024-08-21T01:02:43.751995Z","siteName":"Cumilla","river":"Gumti","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.778872,23.768642]},"properties":{"gaugeId":"BWDB_SW91.9R","issuedTime":"2024-08-21T01:02:43.753415Z","siteName":"Goalondo + (Transit)","river":"Padma","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.073729,26.125276]},"properties":{"gaugeId":"BWDB_SW291.5R","issuedTime":"2024-08-21T01:02:43.742990Z","siteName":"Dalia","river":"Teesta","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.336562,23.784904]},"properties":{"gaugeId":"BWDB_SW302","issuedTime":"2024-08-21T01:02:43.742314Z","siteName":"Mirpur","river":"Turag","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.516256,23.539828]},"properties":{"gaugeId":"BWDB_SW101","issuedTime":"2024-08-21T01:02:43.747180Z","siteName":"Kamarkhali + (Transit)","river":"Gorai","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.48001,23.56269]},"properties":{"gaugeId":"BWDB_SW71A","issuedTime":"2024-08-21T01:02:43.751997Z","siteName":"Rekabi-Bazar","river":"Dhaleswari","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.638969,23.58457]},"properties":{"gaugeId":"BWDB_SW275.5","issuedTime":"2024-08-21T01:02:43.752988Z","siteName":"Meghna + Bridge","river":"Meghna","severity":"ABOVE_NORMAL","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"c131d800f16b4e1091db58bc2c1843ae"},{"level":"MEDIUM","serializedPolygonId":"28fcb2013d574375bcf045dbdd93e8cd"},{"level":"LOW","serializedPolygonId":"f3eae83263644992857b356dd7f06c4e"}],"inundationMapsTimeRange":{"start":"2024-08-20T09:00:00Z","end":"2024-08-20T09:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.26666666666668,23.473055555555554]},"properties":{"gaugeId":"CWC_012-MDSIL","issuedTime":"2024-08-21T01:03:39.394447Z","siteName":"Sonamura + (II)","river":null,"severity":"ABOVE_NORMAL","source":"CWC","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.079743,21.773552]},"properties":{"gaugeId":"BWDB_SW204","issuedTime":"2024-08-21T01:12:06.279121Z","siteName":"Chiringa","river":"Matamuhuri","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.439032,23.320123]},"properties":{"gaugeId":"BWDB_SW95","issuedTime":"2024-08-21T01:02:44.441009Z","siteName":"Sureshswar","river":"Padma","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.661579,25.123256]},"properties":{"gaugeId":"BWDB_SW263","issuedTime":"2024-08-21T01:02:43.752847Z","siteName":"Durgapur","river":"Someswari","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.249526,24.599517]},"properties":{"gaugeId":"BWDB_SW211.5","issuedTime":"2024-08-21T01:09:59.760859Z","siteName":"Chapai-Nawabganj","river":"Mohananda","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.991206,24.045541]},"properties":{"gaugeId":"BWDB_SW273","issuedTime":"2024-08-21T01:02:43.750627Z","siteName":"Bhairab + Bazar","river":"Upper Meghna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.842925,23.645365]},"properties":{"gaugeId":"BWDB_SW207","issuedTime":"2024-08-21T01:02:43.751180Z","siteName":"Chuadanga","river":"Mathabhanga","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.138756,24.497782]},"properties":{"gaugeId":"BWDB_SW147.5","issuedTime":"2024-08-21T01:02:43.750599Z","siteName":"Singra","river":"Atrai + Gur","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.391511,24.831299]},"properties":{"gaugeId":"BWDB_SW65","issuedTime":"2024-08-21T01:02:43.751897Z","siteName":"Bogura","river":"Karatoa","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.689858,24.635869]},"properties":{"gaugeId":"BWDB_SW49A","issuedTime":"2024-08-21T01:02:43.749730Z","siteName":"Kazipur","river":"Jamuna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.72653,23.918646]},"properties":{"gaugeId":"BWDB_SW274","issuedTime":"2024-08-21T01:08:08.803288Z","siteName":"Narsingdi","river":"Meghna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.206392,23.511165]},"properties":{"gaugeId":"BWDB_SW93.4L","issuedTime":"2024-08-21T01:02:43.751012Z","siteName":"Bhagyakul","river":"Padma","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.686153,25.544273]},"properties":{"gaugeId":"BWDB_SW45.5","issuedTime":"2024-08-21T01:12:38.287522Z","siteName":"Chilmari","river":"Brahmaputra","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.772772,23.881297]},"properties":{"gaugeId":"BWDB_SW50.6","issuedTime":"2024-08-21T01:02:43.752637Z","siteName":"Aricha","river":"Jamuna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.667595,25.82041]},"properties":{"gaugeId":"BWDB_SW77","issuedTime":"2024-08-21T01:02:43.747425Z","siteName":"Kurigram","river":"Dharla","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.062548,25.675475]},"properties":{"gaugeId":"BWDB_SW62","issuedTime":"2024-08-21T01:02:44.614160Z","siteName":"Badarganj","river":"Jamuneswari","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.889765,25.073472]},"properties":{"gaugeId":"BWDB_SW263.1","issuedTime":"2024-08-21T01:02:43.741605Z","siteName":"Kalmakanda","river":"Someswari","severity":"UNKNOWN","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.718387,24.470952]},"properties":{"gaugeId":"BWDB_SW49","issuedTime":"2024-08-21T01:02:43.741341Z","siteName":"Serajganj","river":"Jamuna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.967658,24.923502]},"properties":{"gaugeId":"BWDB_SW225","issuedTime":"2024-08-21T01:02:44.513328Z","siteName":"Jamalpur","river":"Old + Brahmaputra","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.857085,23.787087]},"properties":{"gaugeId":"BWDB_SW206","issuedTime":"2024-08-21T01:02:43.741928Z","siteName":"Hatboalia","river":"Mathabhanga","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.544405,26.330021]},"properties":{"gaugeId":"BWDB_SW140","issuedTime":"2024-08-21T01:02:43.751230Z","siteName":"Panchagarh","river":"Upper + Karatoa","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.849452,24.888834]},"properties":{"gaugeId":"BWDB_SW267","issuedTime":"2024-08-21T01:02:43.742505Z","siteName":"Sylhet","river":"Surma","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.419454,23.696849]},"properties":{"gaugeId":"BWDB_SW42","issuedTime":"2024-08-21T01:02:43.750274Z","siteName":"Dhaka + (MilBarack)","river":"Buriganga","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.84582,24.352029]},"properties":{"gaugeId":"BWDB_SW67","issuedTime":"2024-08-21T01:02:43.746795Z","siteName":"Kamalganj","river":"Dhalai","severity":"SEVERE","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"db6f4ad7e66841bca99a730de855e901"},{"level":"MEDIUM","serializedPolygonId":"0f14f753676647f6bbfccf2962f91723"},{"level":"LOW","serializedPolygonId":"3a88c77589164db4bfc280a5e94360f7"}],"inundationMapsTimeRange":{"start":"2024-08-20T09:00:00Z","end":"2024-08-20T09:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.318746,24.820982]},"properties":{"gaugeId":"BWDB_SW238","issuedTime":"2024-08-21T01:02:43.742372Z","siteName":"Rohanpur","river":"Punarvaba","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.377776,25.146083]},"properties":{"gaugeId":"BWDB_SW63","issuedTime":"2024-08-21T01:02:43.752743Z","siteName":"Chakrahimpur","river":"Karatoa","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.110489,24.70217]},"properties":{"gaugeId":"BWDB_SW72","issuedTime":"2024-08-21T01:02:43.752141Z","siteName":"Khaliajuri","river":"Dhanu","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.681667,24.628307]},"properties":{"gaugeId":"BWDB_SW175.5","issuedTime":"2024-08-21T01:02:43.747298Z","siteName":"Sherpur-Sylhet","river":"Kushiyara","severity":"ABOVE_NORMAL","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"e8278d924c20403199eb8f112356d454"},{"level":"MEDIUM","serializedPolygonId":"76ad2fc7b9e540a79943200e10224160"},{"level":"LOW","serializedPolygonId":"56b85a8803b94a9387ce8dbab72c26f5"}],"inundationMapsTimeRange":{"start":"2024-08-22T06:00:00Z","end":"2024-08-22T06:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.191013,24.890721]},"properties":{"gaugeId":"BWDB_SW173","issuedTime":"2024-08-21T01:02:43.752905Z","siteName":"Sheola","river":"Kushiyara","severity":"SEVERE","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"9c03e0c5c52b45d1bf6a6170ad74117a"},{"level":"MEDIUM","serializedPolygonId":"3ff908a6701c49b3867d546c89ac2a87"},{"level":"LOW","serializedPolygonId":"287018525e2e4c2fa16360708d5e5dc4"}],"inundationMapsTimeRange":{"start":"2024-08-21T20:00:00Z","end":"2024-08-21T20:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.209356,21.793554]},"properties":{"gaugeId":"BWDB_SW203","issuedTime":"2024-08-21T01:02:43.753321Z","siteName":"Lama","river":"Matamuhuri","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.496305,23.732784]},"properties":{"gaugeId":"BWDB_SW179","issuedTime":"2024-08-21T01:02:43.751669Z","siteName":"Demra","river":"Balu","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.719765,22.807724]},"properties":{"gaugeId":"BWDB_SW117","issuedTime":"2024-08-21T01:02:43.747064Z","siteName":"Narayanhat","river":"Halda","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.937553,24.428089]},"properties":{"gaugeId":"BWDB_SW201","issuedTime":"2024-08-21T01:10:01.557770Z","siteName":"Manu-RB","river":"Manu","severity":"ABOVE_NORMAL","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"c35c936946cd4050971396eee52c57fc"},{"level":"MEDIUM","serializedPolygonId":"6b0a2e86bb704b9580dd81671a099132"},{"level":"LOW","serializedPolygonId":"e4cb9c9127af45e9beaf316fe104c2b2"}],"inundationMapsTimeRange":{"start":"2024-08-20T06:00:00Z","end":"2024-08-20T06:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.260002,23.4704]},"properties":{"gaugeId":"BWDB_SW93.5L","issuedTime":"2024-08-21T01:09:51.850328Z","siteName":"Mawa","river":"Padma","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.216246,22.194878]},"properties":{"gaugeId":"BWDB_SW247","issuedTime":"2024-08-21T01:09:25.330476Z","siteName":"Bandarban","river":"Sangu","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.250119,25.191499]},"properties":{"gaugeId":"BWDB_SW131.5","issuedTime":"2024-08-21T01:02:43.741552Z","siteName":"Lorergorh","river":"Jadukata","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.702683,26.030516]},"properties":{"gaugeId":"BWDB_SW132.2","issuedTime":"2024-08-21T01:02:43.750057Z","siteName":"Phulbari","river":"Ichamati-Jamuna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.03352,24.06764]},"properties":{"gaugeId":"BWDB_SW90","issuedTime":"2024-08-21T01:02:43.752829Z","siteName":"Hardinge-RB","river":"Ganges","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.405531,25.071634]},"properties":{"gaugeId":"BWDB_SW269","issuedTime":"2024-08-21T01:02:44.605627Z","siteName":"Sunamganj","river":"Surma","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.230264,23.911094]},"properties":{"gaugeId":"BWDB_SW14.5","issuedTime":"2024-08-21T01:02:43.741257Z","siteName":"Nayarhat","river":"Bangshi","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.437306,25.787864]},"properties":{"gaugeId":"BWDB_SW294","issuedTime":"2024-08-21T01:02:43.742417Z","siteName":"Kaunia","river":"Teesta","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.958068,23.862486]},"properties":{"gaugeId":"BWDB_SW137A","issuedTime":"2024-08-21T01:02:45.009553Z","siteName":"Taraghat","river":"Kaliganga","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.182899,23.883877]},"properties":{"gaugeId":"BWDB_SW99","issuedTime":"2024-08-21T01:02:43.749961Z","siteName":"Gorai-RB","river":"Gorai","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.209848,23.187806]},"properties":{"gaugeId":"BWDB_SW5","issuedTime":"2024-08-21T01:02:43.752147Z","siteName":"Madaripur","river":"Arialkhan","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.76646,25.920668]},"properties":{"gaugeId":"BWDB_SW45","issuedTime":"2024-08-21T01:02:43.741370Z","siteName":"Noonkhawa","river":"Brahmaputra","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.410342,24.392752]},"properties":{"gaugeId":"BWDB_SW159","issuedTime":"2024-08-21T01:02:43.750462Z","siteName":"Habiganj","river":"Khowai","severity":"ABOVE_NORMAL","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"50e66b72ecb64b4786ed2d2b5f7c05db"},{"level":"MEDIUM","serializedPolygonId":"a6aedce476b747d4905ce6a5a269aec7"},{"level":"LOW","serializedPolygonId":"15cd641a589746b882ada11e7c74dc70"}],"inundationMapsTimeRange":{"start":"2024-08-20T06:00:00Z","end":"2024-08-20T06:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.639487,23.23169]},"properties":{"gaugeId":"BWDB_SW277","issuedTime":"2024-08-21T01:02:43.752489Z","siteName":"Chandpur","river":"Lower + Meghna","severity":"ABOVE_NORMAL","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"661a4c6448fa49c7aec78f52b6c64d87"},{"level":"MEDIUM","serializedPolygonId":"b4c5af47cbb94fb2bd65ff49616d861f"},{"level":"LOW","serializedPolygonId":"bc8d872d9673474294e5cc6f4d68a206"}],"inundationMapsTimeRange":{"start":"2024-08-22T00:00:00Z","end":"2024-08-22T00:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.70111,25.104949]},"properties":{"gaugeId":"BWDB_SW46.9L","issuedTime":"2024-08-21T01:02:43.750700Z","siteName":"Bahadurabad + (Transit)","river":"Jamuna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.025397,23.878853]},"properties":{"gaugeId":"BWDB_SW68.5","issuedTime":"2024-08-21T01:02:43.742212Z","siteName":"Jagir","river":"Old + Dhaleswari","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.068931,24.644253]},"properties":{"gaugeId":"BWDB_SW88A","issuedTime":"2024-08-21T01:07:50.480790Z","siteName":"Pankha","river":"Ganges","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.652813,25.009779]},"properties":{"gaugeId":"BWDB_SW36","issuedTime":"2024-08-21T01:02:43.741671Z","siteName":"Jariajanjail","river":"Kangsha","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.59615,24.098525]},"properties":{"gaugeId":"BWDB_SW157","issuedTime":"2024-08-21T01:02:43.741786Z","siteName":"Ballah","river":"Khowai","severity":"EXTREME","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"705c9b71897a4c40ad740b65b22b7429"},{"level":"MEDIUM","serializedPolygonId":"b1fed2465d3d4de48c4c405e5821138b"},{"level":"LOW","serializedPolygonId":"e919a50ee20b4c00a6f8cd91572eefe3"}],"inundationMapsTimeRange":{"start":"2024-08-20T09:00:00Z","end":"2024-08-20T09:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.932033,24.844091]},"properties":{"gaugeId":"BWDB_SW133","issuedTime":"2024-08-21T01:08:28.891683Z","siteName":"Naogaon","river":"Little + Jamuna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.650532,24.040344]},"properties":{"gaugeId":"BWDB_SW177","issuedTime":"2024-08-21T01:02:43.742057Z","siteName":"Lakhpur","river":"Lakhya","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.4013,23.881792]},"properties":{"gaugeId":"BWDB_SW299","issuedTime":"2024-08-21T01:02:43.742395Z","siteName":"Tongi","river":"Tongi + Khal","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.846427,22.56086]},"properties":{"gaugeId":"BWDB_SW119.1","issuedTime":"2024-08-21T01:02:43.752413Z","siteName":"Panchpukuria","river":"Halda","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.731861,25.767523]},"properties":{"gaugeId":"BWDB_SW142.1","issuedTime":"2024-08-21T01:02:43.753367Z","siteName":"Bhusirbandar","river":"Upper + Atrai","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.11833,25.087706]},"properties":{"gaugeId":"BWDB_SW251","issuedTime":"2024-08-21T01:02:43.747689Z","siteName":"Sarighat","river":"Sarigowain","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.379531,24.785555]},"properties":{"gaugeId":"BWDB_SW269.5","issuedTime":"2024-08-21T01:02:43.750692Z","siteName":"Derai","river":"Surma + Old Course","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}}]}' + headers: + content-length: + - '26138' + content-type: + - application/json + status: + code: 200 + message: OK +version: 1 diff --git a/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api_case_insensitive.yaml b/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api_case_insensitive.yaml new file mode 100644 index 000000000..541092747 --- /dev/null +++ b/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api_case_insensitive.yaml @@ -0,0 +1,258 @@ +interactions: +- request: + body: '{"regionCode": "BD"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '20' + Content-Type: + - application/json + User-Agent: + - python-requests/2.32.0 + method: POST + uri: https://floodforecasting.googleapis.com/v1/floodStatus:searchLatestFloodStatusByArea + response: + body: + string: !!binary | + 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 + headers: + Alt-Svc: + - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 + Cache-Control: + - private + Content-Encoding: + - gzip + Content-Type: + - application/json; charset=UTF-8 + Date: + - Wed, 21 Aug 2024 01:18:32 GMT + Server: + - ESF + Server-Timing: + - gfet4t7; dur=382 + Transfer-Encoding: + - chunked + Vary: + - Origin + - X-Origin + - Referer + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-XSS-Protection: + - '0' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.32.0 + method: GET + uri: https://floodforecasting.googleapis.com/v1/gauges:batchGet?names=gauges%2FBWDB_SW101&names=gauges%2FBWDB_SW110&names=gauges%2FBWDB_SW117&names=gauges%2FBWDB_SW119.1&names=gauges%2FBWDB_SW131.5&names=gauges%2FBWDB_SW132.2&names=gauges%2FBWDB_SW133&names=gauges%2FBWDB_SW137A&names=gauges%2FBWDB_SW14.5&names=gauges%2FBWDB_SW140&names=gauges%2FBWDB_SW142.1&names=gauges%2FBWDB_SW145&names=gauges%2FBWDB_SW147.5&names=gauges%2FBWDB_SW157&names=gauges%2FBWDB_SW159&names=gauges%2FBWDB_SW15J&names=gauges%2FBWDB_SW162&names=gauges%2FBWDB_SW172&names=gauges%2FBWDB_SW173&names=gauges%2FBWDB_SW175.5&names=gauges%2FBWDB_SW177&names=gauges%2FBWDB_SW179&names=gauges%2FBWDB_SW201&names=gauges%2FBWDB_SW202&names=gauges%2FBWDB_SW203&names=gauges%2FBWDB_SW204&names=gauges%2FBWDB_SW206&names=gauges%2FBWDB_SW207&names=gauges%2FBWDB_SW211.5&names=gauges%2FBWDB_SW212&names=gauges%2FBWDB_SW225&names=gauges%2FBWDB_SW228&names=gauges%2FBWDB_SW236&names=gauges%2FBWDB_SW238&names=gauges%2FBWDB_SW247&names=gauges%2FBWDB_SW248&names=gauges%2FBWDB_SW251&names=gauges%2FBWDB_SW263&names=gauges%2FBWDB_SW263.1&names=gauges%2FBWDB_SW266&names=gauges%2FBWDB_SW267&names=gauges%2FBWDB_SW269&names=gauges%2FBWDB_SW269.5&names=gauges%2FBWDB_SW270&names=gauges%2FBWDB_SW273&names=gauges%2FBWDB_SW274&names=gauges%2FBWDB_SW275.5&names=gauges%2FBWDB_SW277&names=gauges%2FBWDB_SW285&names=gauges%2FBWDB_SW291.5R&names=gauges%2FBWDB_SW294&names=gauges%2FBWDB_SW299&names=gauges%2FBWDB_SW302&names=gauges%2FBWDB_SW36&names=gauges%2FBWDB_SW3A&names=gauges%2FBWDB_SW42&names=gauges%2FBWDB_SW45&names=gauges%2FBWDB_SW45.5&names=gauges%2FBWDB_SW46.9L&names=gauges%2FBWDB_SW49&names=gauges%2FBWDB_SW49A&names=gauges%2FBWDB_SW5&names=gauges%2FBWDB_SW50.6&names=gauges%2FBWDB_SW62&names=gauges%2FBWDB_SW63&names=gauges%2FBWDB_SW65&names=gauges%2FBWDB_SW67&names=gauges%2FBWDB_SW68.5&names=gauges%2FBWDB_SW71A&names=gauges%2FBWDB_SW72&names=gauges%2FBWDB_SW77&names=gauges%2FBWDB_SW84&names=gauges%2FBWDB_SW88&names=gauges%2FBWDB_SW88A&names=gauges%2FBWDB_SW90&names=gauges%2FBWDB_SW91.9R&names=gauges%2FBWDB_SW93.4L&names=gauges%2FBWDB_SW93.5L&names=gauges%2FBWDB_SW95&names=gauges%2FBWDB_SW99&names=gauges%2FCWC_012-MDSIL + response: + body: + string: !!binary | + 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 + 6aEmTTd+LkvDf//54o8X/wHapSYWR04AAA== + headers: + Alt-Svc: + - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 + Cache-Control: + - private + Content-Encoding: + - gzip + Content-Type: + - application/json; charset=UTF-8 + Date: + - Wed, 21 Aug 2024 01:18:32 GMT + Server: + - ESF + Server-Timing: + - gfet4t7; dur=124 + Transfer-Encoding: + - chunked + Vary: + - Origin + - X-Origin + - Referer + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-XSS-Protection: + - '0' + status: + code: 200 + message: OK +- request: + body: '' + headers: + accept: + - '*/*' + accept-encoding: + - gzip, deflate + connection: + - keep-alive + host: + - testserver + user-agent: + - testclient + method: GET + uri: http://testserver/google-floods/gauges/?region_codes=bd + response: + body: + string: '{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[91.389698,24.691644]},"properties":{"gaugeId":"BWDB_SW270","issuedTime":"2024-08-21T01:11:04.800016Z","siteName":"Markuli","river":"Surma-Meghna","severity":"SEVERE","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"f618d9d0b41047e5a73e0352c54737cb"},{"level":"MEDIUM","serializedPolygonId":"5ac17564f96c416aa65622210f7be455"},{"level":"LOW","serializedPolygonId":"3d8b39f6fc0b45df9d6ac2945a8a57b2"}],"inundationMapsTimeRange":{"start":"2024-08-22T09:00:00Z","end":"2024-08-22T09:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.431068,24.737208]},"properties":{"gaugeId":"BWDB_SW228","issuedTime":"2024-08-21T01:09:48.625563Z","siteName":"Mymensingh","river":"Old + Brahmaputra","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.553699,24.368824]},"properties":{"gaugeId":"BWDB_SW88","issuedTime":"2024-08-21T01:02:43.741872Z","siteName":"Rajshahi","river":"Ganges","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.438231,23.221259]},"properties":{"gaugeId":"BWDB_SW212","issuedTime":"2024-08-21T01:02:43.741974Z","siteName":"Parshuram","river":"Muhuri","severity":"SEVERE","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"3047087919894a6b8fdce086515cc171"},{"level":"MEDIUM","serializedPolygonId":"84c6899783e149eeabcdc05c6ec149e0"},{"level":"LOW","serializedPolygonId":"6544a995d4fd4ff5b5de00c8f261dd1b"}],"inundationMapsTimeRange":{"start":"2024-08-20T09:00:00Z","end":"2024-08-20T09:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.485642,24.872495]},"properties":{"gaugeId":"BWDB_SW172","issuedTime":"2024-08-21T01:02:43.752334Z","siteName":"Amalshid","river":"Kushiyara","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.119442,23.956966]},"properties":{"gaugeId":"BWDB_SW3A","issuedTime":"2024-08-21T01:02:43.753813Z","siteName":"B. + Baria","river":"Titas","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.774876,24.496424]},"properties":{"gaugeId":"BWDB_SW202","issuedTime":"2024-08-21T01:02:43.747282Z","siteName":"Moulvibazar","river":"Manu","severity":"ABOVE_NORMAL","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"0bca00b745534e5d9f97637c845445af"},{"level":"MEDIUM","serializedPolygonId":"d6d0fa09a1fb472ebc33248431455131"},{"level":"LOW","serializedPolygonId":"4c3976049e454c608c082f9ebfbd9b2a"}],"inundationMapsTimeRange":{"start":"2024-08-20T06:00:00Z","end":"2024-08-20T06:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.063472,22.15791]},"properties":{"gaugeId":"BWDB_SW248","issuedTime":"2024-08-21T01:02:44.639650Z","siteName":"Dohazari","river":"Sangu","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.703954,22.968128]},"properties":{"gaugeId":"BWDB_SW84","issuedTime":"2024-08-21T01:02:43.752323Z","siteName":"Ramgarh","river":"Feni","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.580654,24.891637]},"properties":{"gaugeId":"BWDB_SW15J","issuedTime":"2024-08-21T01:02:43.751949Z","siteName":"Sariakandi + (Mathurapara)","river":"Jamuna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.265191,25.004479]},"properties":{"gaugeId":"BWDB_SW266","issuedTime":"2024-08-21T01:11:03.131730Z","siteName":"Kanaighat","river":"Surma","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.618762,25.689237]},"properties":{"gaugeId":"BWDB_SW236","issuedTime":"2024-08-21T01:02:43.752832Z","siteName":"Dinajpur","river":"Punarbhaba","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.460897,26.03796]},"properties":{"gaugeId":"BWDB_SW285","issuedTime":"2024-08-21T01:10:48.136382Z","siteName":"Thakurgaon","river":"Tangon","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.744249,24.916416]},"properties":{"gaugeId":"BWDB_SW145","issuedTime":"2024-08-21T01:02:43.750317Z","siteName":"Mohadebpur","river":"Atrai","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.096763,23.101868]},"properties":{"gaugeId":"BWDB_SW162","issuedTime":"2024-08-21T01:02:44.417982Z","siteName":"Jhikargacha","river":"Kobadak","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.19839,23.471078]},"properties":{"gaugeId":"BWDB_SW110","issuedTime":"2024-08-21T01:02:43.751995Z","siteName":"Cumilla","river":"Gumti","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.778872,23.768642]},"properties":{"gaugeId":"BWDB_SW91.9R","issuedTime":"2024-08-21T01:02:43.753415Z","siteName":"Goalondo + (Transit)","river":"Padma","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.073729,26.125276]},"properties":{"gaugeId":"BWDB_SW291.5R","issuedTime":"2024-08-21T01:02:43.742990Z","siteName":"Dalia","river":"Teesta","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.336562,23.784904]},"properties":{"gaugeId":"BWDB_SW302","issuedTime":"2024-08-21T01:02:43.742314Z","siteName":"Mirpur","river":"Turag","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.516256,23.539828]},"properties":{"gaugeId":"BWDB_SW101","issuedTime":"2024-08-21T01:02:43.747180Z","siteName":"Kamarkhali + (Transit)","river":"Gorai","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.48001,23.56269]},"properties":{"gaugeId":"BWDB_SW71A","issuedTime":"2024-08-21T01:02:43.751997Z","siteName":"Rekabi-Bazar","river":"Dhaleswari","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.638969,23.58457]},"properties":{"gaugeId":"BWDB_SW275.5","issuedTime":"2024-08-21T01:02:43.752988Z","siteName":"Meghna + Bridge","river":"Meghna","severity":"ABOVE_NORMAL","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"c131d800f16b4e1091db58bc2c1843ae"},{"level":"MEDIUM","serializedPolygonId":"28fcb2013d574375bcf045dbdd93e8cd"},{"level":"LOW","serializedPolygonId":"f3eae83263644992857b356dd7f06c4e"}],"inundationMapsTimeRange":{"start":"2024-08-20T09:00:00Z","end":"2024-08-20T09:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.26666666666668,23.473055555555554]},"properties":{"gaugeId":"CWC_012-MDSIL","issuedTime":"2024-08-21T01:03:39.394447Z","siteName":"Sonamura + (II)","river":null,"severity":"ABOVE_NORMAL","source":"CWC","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.079743,21.773552]},"properties":{"gaugeId":"BWDB_SW204","issuedTime":"2024-08-21T01:12:06.279121Z","siteName":"Chiringa","river":"Matamuhuri","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.439032,23.320123]},"properties":{"gaugeId":"BWDB_SW95","issuedTime":"2024-08-21T01:02:44.441009Z","siteName":"Sureshswar","river":"Padma","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.661579,25.123256]},"properties":{"gaugeId":"BWDB_SW263","issuedTime":"2024-08-21T01:02:43.752847Z","siteName":"Durgapur","river":"Someswari","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.249526,24.599517]},"properties":{"gaugeId":"BWDB_SW211.5","issuedTime":"2024-08-21T01:09:59.760859Z","siteName":"Chapai-Nawabganj","river":"Mohananda","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.991206,24.045541]},"properties":{"gaugeId":"BWDB_SW273","issuedTime":"2024-08-21T01:02:43.750627Z","siteName":"Bhairab + Bazar","river":"Upper Meghna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.842925,23.645365]},"properties":{"gaugeId":"BWDB_SW207","issuedTime":"2024-08-21T01:02:43.751180Z","siteName":"Chuadanga","river":"Mathabhanga","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.138756,24.497782]},"properties":{"gaugeId":"BWDB_SW147.5","issuedTime":"2024-08-21T01:02:43.750599Z","siteName":"Singra","river":"Atrai + Gur","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.391511,24.831299]},"properties":{"gaugeId":"BWDB_SW65","issuedTime":"2024-08-21T01:02:43.751897Z","siteName":"Bogura","river":"Karatoa","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.689858,24.635869]},"properties":{"gaugeId":"BWDB_SW49A","issuedTime":"2024-08-21T01:02:43.749730Z","siteName":"Kazipur","river":"Jamuna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.72653,23.918646]},"properties":{"gaugeId":"BWDB_SW274","issuedTime":"2024-08-21T01:08:08.803288Z","siteName":"Narsingdi","river":"Meghna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.206392,23.511165]},"properties":{"gaugeId":"BWDB_SW93.4L","issuedTime":"2024-08-21T01:02:43.751012Z","siteName":"Bhagyakul","river":"Padma","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.686153,25.544273]},"properties":{"gaugeId":"BWDB_SW45.5","issuedTime":"2024-08-21T01:12:38.287522Z","siteName":"Chilmari","river":"Brahmaputra","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.772772,23.881297]},"properties":{"gaugeId":"BWDB_SW50.6","issuedTime":"2024-08-21T01:02:43.752637Z","siteName":"Aricha","river":"Jamuna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.667595,25.82041]},"properties":{"gaugeId":"BWDB_SW77","issuedTime":"2024-08-21T01:02:43.747425Z","siteName":"Kurigram","river":"Dharla","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.062548,25.675475]},"properties":{"gaugeId":"BWDB_SW62","issuedTime":"2024-08-21T01:02:44.614160Z","siteName":"Badarganj","river":"Jamuneswari","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.889765,25.073472]},"properties":{"gaugeId":"BWDB_SW263.1","issuedTime":"2024-08-21T01:02:43.741605Z","siteName":"Kalmakanda","river":"Someswari","severity":"UNKNOWN","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.718387,24.470952]},"properties":{"gaugeId":"BWDB_SW49","issuedTime":"2024-08-21T01:02:43.741341Z","siteName":"Serajganj","river":"Jamuna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.967658,24.923502]},"properties":{"gaugeId":"BWDB_SW225","issuedTime":"2024-08-21T01:02:44.513328Z","siteName":"Jamalpur","river":"Old + Brahmaputra","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.857085,23.787087]},"properties":{"gaugeId":"BWDB_SW206","issuedTime":"2024-08-21T01:02:43.741928Z","siteName":"Hatboalia","river":"Mathabhanga","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.544405,26.330021]},"properties":{"gaugeId":"BWDB_SW140","issuedTime":"2024-08-21T01:02:43.751230Z","siteName":"Panchagarh","river":"Upper + Karatoa","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.849452,24.888834]},"properties":{"gaugeId":"BWDB_SW267","issuedTime":"2024-08-21T01:02:43.742505Z","siteName":"Sylhet","river":"Surma","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.419454,23.696849]},"properties":{"gaugeId":"BWDB_SW42","issuedTime":"2024-08-21T01:02:43.750274Z","siteName":"Dhaka + (MilBarack)","river":"Buriganga","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.84582,24.352029]},"properties":{"gaugeId":"BWDB_SW67","issuedTime":"2024-08-21T01:02:43.746795Z","siteName":"Kamalganj","river":"Dhalai","severity":"SEVERE","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"db6f4ad7e66841bca99a730de855e901"},{"level":"MEDIUM","serializedPolygonId":"0f14f753676647f6bbfccf2962f91723"},{"level":"LOW","serializedPolygonId":"3a88c77589164db4bfc280a5e94360f7"}],"inundationMapsTimeRange":{"start":"2024-08-20T09:00:00Z","end":"2024-08-20T09:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.318746,24.820982]},"properties":{"gaugeId":"BWDB_SW238","issuedTime":"2024-08-21T01:02:43.742372Z","siteName":"Rohanpur","river":"Punarvaba","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.377776,25.146083]},"properties":{"gaugeId":"BWDB_SW63","issuedTime":"2024-08-21T01:02:43.752743Z","siteName":"Chakrahimpur","river":"Karatoa","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.110489,24.70217]},"properties":{"gaugeId":"BWDB_SW72","issuedTime":"2024-08-21T01:02:43.752141Z","siteName":"Khaliajuri","river":"Dhanu","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.681667,24.628307]},"properties":{"gaugeId":"BWDB_SW175.5","issuedTime":"2024-08-21T01:02:43.747298Z","siteName":"Sherpur-Sylhet","river":"Kushiyara","severity":"ABOVE_NORMAL","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"e8278d924c20403199eb8f112356d454"},{"level":"MEDIUM","serializedPolygonId":"76ad2fc7b9e540a79943200e10224160"},{"level":"LOW","serializedPolygonId":"56b85a8803b94a9387ce8dbab72c26f5"}],"inundationMapsTimeRange":{"start":"2024-08-22T06:00:00Z","end":"2024-08-22T06:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.191013,24.890721]},"properties":{"gaugeId":"BWDB_SW173","issuedTime":"2024-08-21T01:02:43.752905Z","siteName":"Sheola","river":"Kushiyara","severity":"SEVERE","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"9c03e0c5c52b45d1bf6a6170ad74117a"},{"level":"MEDIUM","serializedPolygonId":"3ff908a6701c49b3867d546c89ac2a87"},{"level":"LOW","serializedPolygonId":"287018525e2e4c2fa16360708d5e5dc4"}],"inundationMapsTimeRange":{"start":"2024-08-21T20:00:00Z","end":"2024-08-21T20:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.209356,21.793554]},"properties":{"gaugeId":"BWDB_SW203","issuedTime":"2024-08-21T01:02:43.753321Z","siteName":"Lama","river":"Matamuhuri","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.496305,23.732784]},"properties":{"gaugeId":"BWDB_SW179","issuedTime":"2024-08-21T01:02:43.751669Z","siteName":"Demra","river":"Balu","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.719765,22.807724]},"properties":{"gaugeId":"BWDB_SW117","issuedTime":"2024-08-21T01:02:43.747064Z","siteName":"Narayanhat","river":"Halda","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.937553,24.428089]},"properties":{"gaugeId":"BWDB_SW201","issuedTime":"2024-08-21T01:10:01.557770Z","siteName":"Manu-RB","river":"Manu","severity":"ABOVE_NORMAL","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"c35c936946cd4050971396eee52c57fc"},{"level":"MEDIUM","serializedPolygonId":"6b0a2e86bb704b9580dd81671a099132"},{"level":"LOW","serializedPolygonId":"e4cb9c9127af45e9beaf316fe104c2b2"}],"inundationMapsTimeRange":{"start":"2024-08-20T06:00:00Z","end":"2024-08-20T06:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.260002,23.4704]},"properties":{"gaugeId":"BWDB_SW93.5L","issuedTime":"2024-08-21T01:09:51.850328Z","siteName":"Mawa","river":"Padma","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.216246,22.194878]},"properties":{"gaugeId":"BWDB_SW247","issuedTime":"2024-08-21T01:09:25.330476Z","siteName":"Bandarban","river":"Sangu","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.250119,25.191499]},"properties":{"gaugeId":"BWDB_SW131.5","issuedTime":"2024-08-21T01:02:43.741552Z","siteName":"Lorergorh","river":"Jadukata","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.702683,26.030516]},"properties":{"gaugeId":"BWDB_SW132.2","issuedTime":"2024-08-21T01:02:43.750057Z","siteName":"Phulbari","river":"Ichamati-Jamuna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.03352,24.06764]},"properties":{"gaugeId":"BWDB_SW90","issuedTime":"2024-08-21T01:02:43.752829Z","siteName":"Hardinge-RB","river":"Ganges","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.405531,25.071634]},"properties":{"gaugeId":"BWDB_SW269","issuedTime":"2024-08-21T01:02:44.605627Z","siteName":"Sunamganj","river":"Surma","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.230264,23.911094]},"properties":{"gaugeId":"BWDB_SW14.5","issuedTime":"2024-08-21T01:02:43.741257Z","siteName":"Nayarhat","river":"Bangshi","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.437306,25.787864]},"properties":{"gaugeId":"BWDB_SW294","issuedTime":"2024-08-21T01:02:43.742417Z","siteName":"Kaunia","river":"Teesta","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.958068,23.862486]},"properties":{"gaugeId":"BWDB_SW137A","issuedTime":"2024-08-21T01:02:45.009553Z","siteName":"Taraghat","river":"Kaliganga","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.182899,23.883877]},"properties":{"gaugeId":"BWDB_SW99","issuedTime":"2024-08-21T01:02:43.749961Z","siteName":"Gorai-RB","river":"Gorai","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.209848,23.187806]},"properties":{"gaugeId":"BWDB_SW5","issuedTime":"2024-08-21T01:02:43.752147Z","siteName":"Madaripur","river":"Arialkhan","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.76646,25.920668]},"properties":{"gaugeId":"BWDB_SW45","issuedTime":"2024-08-21T01:02:43.741370Z","siteName":"Noonkhawa","river":"Brahmaputra","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.410342,24.392752]},"properties":{"gaugeId":"BWDB_SW159","issuedTime":"2024-08-21T01:02:43.750462Z","siteName":"Habiganj","river":"Khowai","severity":"ABOVE_NORMAL","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"50e66b72ecb64b4786ed2d2b5f7c05db"},{"level":"MEDIUM","serializedPolygonId":"a6aedce476b747d4905ce6a5a269aec7"},{"level":"LOW","serializedPolygonId":"15cd641a589746b882ada11e7c74dc70"}],"inundationMapsTimeRange":{"start":"2024-08-20T06:00:00Z","end":"2024-08-20T06:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.639487,23.23169]},"properties":{"gaugeId":"BWDB_SW277","issuedTime":"2024-08-21T01:02:43.752489Z","siteName":"Chandpur","river":"Lower + Meghna","severity":"ABOVE_NORMAL","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"661a4c6448fa49c7aec78f52b6c64d87"},{"level":"MEDIUM","serializedPolygonId":"b4c5af47cbb94fb2bd65ff49616d861f"},{"level":"LOW","serializedPolygonId":"bc8d872d9673474294e5cc6f4d68a206"}],"inundationMapsTimeRange":{"start":"2024-08-22T00:00:00Z","end":"2024-08-22T00:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.70111,25.104949]},"properties":{"gaugeId":"BWDB_SW46.9L","issuedTime":"2024-08-21T01:02:43.750700Z","siteName":"Bahadurabad + (Transit)","river":"Jamuna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.025397,23.878853]},"properties":{"gaugeId":"BWDB_SW68.5","issuedTime":"2024-08-21T01:02:43.742212Z","siteName":"Jagir","river":"Old + Dhaleswari","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.068931,24.644253]},"properties":{"gaugeId":"BWDB_SW88A","issuedTime":"2024-08-21T01:07:50.480790Z","siteName":"Pankha","river":"Ganges","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.652813,25.009779]},"properties":{"gaugeId":"BWDB_SW36","issuedTime":"2024-08-21T01:02:43.741671Z","siteName":"Jariajanjail","river":"Kangsha","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.59615,24.098525]},"properties":{"gaugeId":"BWDB_SW157","issuedTime":"2024-08-21T01:02:43.741786Z","siteName":"Ballah","river":"Khowai","severity":"EXTREME","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"705c9b71897a4c40ad740b65b22b7429"},{"level":"MEDIUM","serializedPolygonId":"b1fed2465d3d4de48c4c405e5821138b"},{"level":"LOW","serializedPolygonId":"e919a50ee20b4c00a6f8cd91572eefe3"}],"inundationMapsTimeRange":{"start":"2024-08-20T09:00:00Z","end":"2024-08-20T09:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.932033,24.844091]},"properties":{"gaugeId":"BWDB_SW133","issuedTime":"2024-08-21T01:08:28.891683Z","siteName":"Naogaon","river":"Little + Jamuna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.650532,24.040344]},"properties":{"gaugeId":"BWDB_SW177","issuedTime":"2024-08-21T01:02:43.742057Z","siteName":"Lakhpur","river":"Lakhya","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.4013,23.881792]},"properties":{"gaugeId":"BWDB_SW299","issuedTime":"2024-08-21T01:02:43.742395Z","siteName":"Tongi","river":"Tongi + Khal","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.846427,22.56086]},"properties":{"gaugeId":"BWDB_SW119.1","issuedTime":"2024-08-21T01:02:43.752413Z","siteName":"Panchpukuria","river":"Halda","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.731861,25.767523]},"properties":{"gaugeId":"BWDB_SW142.1","issuedTime":"2024-08-21T01:02:43.753367Z","siteName":"Bhusirbandar","river":"Upper + Atrai","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.11833,25.087706]},"properties":{"gaugeId":"BWDB_SW251","issuedTime":"2024-08-21T01:02:43.747689Z","siteName":"Sarighat","river":"Sarigowain","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.379531,24.785555]},"properties":{"gaugeId":"BWDB_SW269.5","issuedTime":"2024-08-21T01:02:43.750692Z","siteName":"Derai","river":"Surma + Old Course","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}}]}' + headers: + content-length: + - '26138' + content-type: + - application/json + status: + code: 200 + message: OK +version: 1 diff --git a/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api_requires_valid_region_code.yaml b/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api_requires_valid_region_code.yaml new file mode 100644 index 000000000..13abcf9b7 --- /dev/null +++ b/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api_requires_valid_region_code.yaml @@ -0,0 +1,28 @@ +interactions: +- request: + body: '' + headers: + accept: + - '*/*' + accept-encoding: + - gzip, deflate + connection: + - keep-alive + host: + - testserver + user-agent: + - testclient + method: GET + uri: http://testserver/google-floods/gauges/?region_codes=usa + response: + body: + string: '{"detail":"Region code ''usa'' must be exactly two characters (iso2)."}' + headers: + content-length: + - '69' + content-type: + - application/json + status: + code: 400 + message: Bad Request +version: 1 diff --git a/api/app/tests/test_google_floods_api.py b/api/app/tests/test_google_floods_api.py index 1e1595b28..1d464fb74 100644 --- a/api/app/tests/test_google_floods_api.py +++ b/api/app/tests/test_google_floods_api.py @@ -1,3 +1,4 @@ +import pytest from app.googleflood import get_google_floods_gauges from app.main import app from fastapi.testclient import TestClient @@ -5,12 +6,13 @@ client = TestClient(app) +@pytest.mark.vcr(match_on=['uri', 'method'], filter_headers=['Authorization'], filter_query_parameters=['key']) def test_get_google_floods_gauges(): """ This test is not used in the API, but is used to test the get_google_floods_gauges function It is used to ensure that the get_google_floods_gauges function returns a valid GeoJSON object """ - gauges = get_google_floods_gauges("BD") + gauges = get_google_floods_gauges(["BD"]) assert gauges["type"] == "FeatureCollection" for feature in gauges["features"]: assert feature["geometry"]["type"] == "Point" @@ -20,11 +22,12 @@ def test_get_google_floods_gauges(): assert "severity" in feature["properties"] +@pytest.mark.vcr(match_on=['uri', 'method'], filter_headers=['Authorization'], filter_query_parameters=['key']) def test_get_google_floods_gauges_api(): """ This test is used to test the API endpoint for getting Google Floods gauges """ - response = client.get("/google-floods/gauges/?region_code=BD") + response = client.get("/google-floods/gauges/?region_codes=BD") assert response.status_code == 200 response_geojson = response.json() @@ -32,11 +35,12 @@ def test_get_google_floods_gauges_api(): assert len(response_geojson["features"]) > 0 +@pytest.mark.vcr(match_on=['uri', 'method'], filter_headers=['Authorization'], filter_query_parameters=['key']) def test_get_google_floods_gauges_api_case_insensitive(): """ This test is used to test the API endpoint for getting Google Floods gauges with a case insensitive region code """ - response = client.get("/google-floods/gauges/?region_code=bd") + response = client.get("/google-floods/gauges/?region_codes=bd") assert response.status_code == 200 response_geojson = response.json() @@ -44,13 +48,14 @@ def test_get_google_floods_gauges_api_case_insensitive(): assert len(response_geojson["features"]) > 0 +@pytest.mark.vcr(match_on=['uri', 'method'], filter_headers=['Authorization'], filter_query_parameters=['key']) def test_get_google_floods_gauges_api_requires_valid_region_code(): """ This test is used to test the API endpoint for getting Google Floods gauges with an invalid region code """ - response = client.get("/google-floods/gauges/?region_code=usa") + response = client.get("/google-floods/gauges/?region_codes=usa") assert response.status_code == 400 assert ( response.json()["detail"] - == "region code must be provided and exactly two characters (iso2)." - ) + == "Region code 'usa' must be exactly two characters (iso2)." + ) \ No newline at end of file diff --git a/api/poetry.lock b/api/poetry.lock index 341d641ad..eaa030ce2 100644 --- a/api/poetry.lock +++ b/api/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "affine" @@ -1750,6 +1750,25 @@ pytest = ">=6.2.4,<8.0.0" pytest-base-url = ">=1.0.0,<3.0.0" python-slugify = ">=6.0.0,<9.0.0" +[[package]] +name = "pytest-recording" +version = "0.13.2" +description = "A pytest plugin that allows you recording of network interactions via VCR.py" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest_recording-0.13.2-py3-none-any.whl", hash = "sha256:3820fe5743d1ac46e807989e11d073cb776a60bdc544cf43ebca454051b22d13"}, + {file = "pytest_recording-0.13.2.tar.gz", hash = "sha256:000c3babbb466681457fd65b723427c1779a0c6c17d9e381c3142a701e124877"}, +] + +[package.dependencies] +pytest = ">=3.5.0" +vcrpy = ">=2.0.1" + +[package.extras] +dev = ["pytest-httpbin", "pytest-mock", "requests", "werkzeug (==3.0.3)"] +tests = ["pytest-httpbin", "pytest-mock", "requests", "werkzeug (==3.0.3)"] + [[package]] name = "pytest-subtests" version = "0.7.0" @@ -2689,6 +2708,26 @@ files = [ docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"] test = ["Cython (>=0.29.36,<0.30.0)", "aiohttp (==3.9.0b0)", "aiohttp (>=3.8.1)", "flake8 (>=5.0,<6.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=23.0.0,<23.1.0)", "pycodestyle (>=2.9.0,<2.10.0)"] +[[package]] +name = "vcrpy" +version = "6.0.1" +description = "Automatically mock your HTTP interactions to simplify and speed up testing" +optional = false +python-versions = ">=3.8" +files = [ + {file = "vcrpy-6.0.1-py2.py3-none-any.whl", hash = "sha256:621c3fb2d6bd8aa9f87532c688e4575bcbbde0c0afeb5ebdb7e14cac409edfdd"}, + {file = "vcrpy-6.0.1.tar.gz", hash = "sha256:9e023fee7f892baa0bbda2f7da7c8ac51165c1c6e38ff8688683a12a4bde9278"}, +] + +[package.dependencies] +PyYAML = "*" +urllib3 = {version = "<2", markers = "platform_python_implementation == \"PyPy\""} +wrapt = "*" +yarl = "*" + +[package.extras] +tests = ["Werkzeug (==2.0.3)", "aiohttp", "boto3", "httplib2", "httpx", "pytest", "pytest-aiohttp", "pytest-asyncio", "pytest-cov", "pytest-httpbin", "requests (>=2.22.0)", "tornado", "urllib3"] + [[package]] name = "watchfiles" version = "0.21.0" @@ -2872,6 +2911,85 @@ MarkupSafe = ">=2.1.1" [package.extras] watchdog = ["watchdog (>=2.3)"] +[[package]] +name = "wrapt" +version = "1.16.0" +description = "Module for decorators, wrappers and monkey patching." +optional = false +python-versions = ">=3.6" +files = [ + {file = "wrapt-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4"}, + {file = "wrapt-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136"}, + {file = "wrapt-1.16.0-cp310-cp310-win32.whl", hash = "sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d"}, + {file = "wrapt-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d"}, + {file = "wrapt-1.16.0-cp311-cp311-win32.whl", hash = "sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362"}, + {file = "wrapt-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c"}, + {file = "wrapt-1.16.0-cp312-cp312-win32.whl", hash = "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc"}, + {file = "wrapt-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8"}, + {file = "wrapt-1.16.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465"}, + {file = "wrapt-1.16.0-cp36-cp36m-win32.whl", hash = "sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e"}, + {file = "wrapt-1.16.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966"}, + {file = "wrapt-1.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c"}, + {file = "wrapt-1.16.0-cp37-cp37m-win32.whl", hash = "sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c"}, + {file = "wrapt-1.16.0-cp37-cp37m-win_amd64.whl", hash = "sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00"}, + {file = "wrapt-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0"}, + {file = "wrapt-1.16.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6"}, + {file = "wrapt-1.16.0-cp38-cp38-win32.whl", hash = "sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b"}, + {file = "wrapt-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41"}, + {file = "wrapt-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2"}, + {file = "wrapt-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537"}, + {file = "wrapt-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3"}, + {file = "wrapt-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35"}, + {file = "wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1"}, + {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"}, +] + [[package]] name = "xarray" version = "2023.1.0" @@ -3001,4 +3119,4 @@ test = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-it [metadata] lock-version = "2.0" python-versions = ">=3.10,<3.11" -content-hash = "d72c32d0bb241fe01323ba3758b9002d66ba348d2633d1b2b36d0de6a277e714" +content-hash = "df68cc98d18f738f802ed3de16c1c29dcdecf6808da9e5cc001fc987dfc640d8" diff --git a/api/pyproject.toml b/api/pyproject.toml index d11968ec2..ec556935c 100644 --- a/api/pyproject.toml +++ b/api/pyproject.toml @@ -29,6 +29,7 @@ pytest-asyncio = "^0.21.1" pytest-playwright = "^0.4.3" rasterio = "^1.3.9" rioxarray = "^0.17.0" +pytest-recording = "^0.13.2" [tool.poetry.group.dev.dependencies] black = "^24.3.0" From 438ee04b45cbc071bafd13e2147aa0e2e0e15208 Mon Sep 17 00:00:00 2001 From: ericboucher Date: Wed, 21 Aug 2024 10:48:51 +0200 Subject: [PATCH 13/19] Update test_google_floods_api.py --- api/app/tests/test_google_floods_api.py | 26 ++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/api/app/tests/test_google_floods_api.py b/api/app/tests/test_google_floods_api.py index 1d464fb74..764dc13a6 100644 --- a/api/app/tests/test_google_floods_api.py +++ b/api/app/tests/test_google_floods_api.py @@ -6,7 +6,11 @@ client = TestClient(app) -@pytest.mark.vcr(match_on=['uri', 'method'], filter_headers=['Authorization'], filter_query_parameters=['key']) +@pytest.mark.vcr( + match_on=["uri", "method"], + filter_headers=["Authorization"], + filter_query_parameters=["key"], +) def test_get_google_floods_gauges(): """ This test is not used in the API, but is used to test the get_google_floods_gauges function @@ -22,7 +26,11 @@ def test_get_google_floods_gauges(): assert "severity" in feature["properties"] -@pytest.mark.vcr(match_on=['uri', 'method'], filter_headers=['Authorization'], filter_query_parameters=['key']) +@pytest.mark.vcr( + match_on=["uri", "method"], + filter_headers=["Authorization"], + filter_query_parameters=["key"], +) def test_get_google_floods_gauges_api(): """ This test is used to test the API endpoint for getting Google Floods gauges @@ -35,7 +43,11 @@ def test_get_google_floods_gauges_api(): assert len(response_geojson["features"]) > 0 -@pytest.mark.vcr(match_on=['uri', 'method'], filter_headers=['Authorization'], filter_query_parameters=['key']) +@pytest.mark.vcr( + match_on=["uri", "method"], + filter_headers=["Authorization"], + filter_query_parameters=["key"], +) def test_get_google_floods_gauges_api_case_insensitive(): """ This test is used to test the API endpoint for getting Google Floods gauges with a case insensitive region code @@ -48,7 +60,11 @@ def test_get_google_floods_gauges_api_case_insensitive(): assert len(response_geojson["features"]) > 0 -@pytest.mark.vcr(match_on=['uri', 'method'], filter_headers=['Authorization'], filter_query_parameters=['key']) +@pytest.mark.vcr( + match_on=["uri", "method"], + filter_headers=["Authorization"], + filter_query_parameters=["key"], +) def test_get_google_floods_gauges_api_requires_valid_region_code(): """ This test is used to test the API endpoint for getting Google Floods gauges with an invalid region code @@ -58,4 +74,4 @@ def test_get_google_floods_gauges_api_requires_valid_region_code(): assert ( response.json()["detail"] == "Region code 'usa' must be exactly two characters (iso2)." - ) \ No newline at end of file + ) From 6547f3b3052bdd19917f1d6327d5ea75c8ed16d9 Mon Sep 17 00:00:00 2001 From: Will Gislason <8203830+gislawill@users.noreply.github.com> Date: Wed, 21 Aug 2024 21:31:06 -0700 Subject: [PATCH 14/19] Fixing river template --- api/app/googleflood.py | 2 +- frontend/src/config/mozambique/layers.json | 2 +- frontend/src/config/rbd/layers.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/api/app/googleflood.py b/api/app/googleflood.py index d00bf108a..40d4b7a7e 100644 --- a/api/app/googleflood.py +++ b/api/app/googleflood.py @@ -30,7 +30,7 @@ def format_gauge_to_geojson(data): "gaugeId": data["gaugeId"], "issuedTime": data["issuedTime"], "siteName": data["siteName"], - "river": ( + "riverName": ( data["river"] if "river" in data and len(data["river"]) > 1 else None ), "severity": data["severity"], diff --git a/frontend/src/config/mozambique/layers.json b/frontend/src/config/mozambique/layers.json index b92b46157..5d595957e 100644 --- a/frontend/src/config/mozambique/layers.json +++ b/frontend/src/config/mozambique/layers.json @@ -2977,7 +2977,7 @@ "template": "Site: {{siteName}}", "visibility": "if-defined" }, - "river": { + "riverName": { "type": "text", "template": "River: {{riverName}}", "visibility": "if-defined" diff --git a/frontend/src/config/rbd/layers.json b/frontend/src/config/rbd/layers.json index 570811ccc..0fdf61575 100644 --- a/frontend/src/config/rbd/layers.json +++ b/frontend/src/config/rbd/layers.json @@ -6554,7 +6554,7 @@ "template": "Site: {{siteName}}", "visibility": "if-defined" }, - "river": { + "riverName": { "type": "text", "template": "River: {{riverName}}", "visibility": "if-defined" From ac58dca9a63ce01e1492cb3e6a446488e40f33ef Mon Sep 17 00:00:00 2001 From: Will Gislason <8203830+gislawill@users.noreply.github.com> Date: Wed, 21 Aug 2024 21:45:44 -0700 Subject: [PATCH 15/19] More selective with pytest recording --- .../test_get_google_floods_gauges.yaml | 156 +++++++------- .../test_get_google_floods_gauges_api.yaml | 201 +++++++----------- ...le_floods_gauges_api_case_insensitive.yaml | 201 +++++++----------- ...gauges_api_requires_valid_region_code.yaml | 28 --- api/app/tests/test_google_floods_api.py | 3 + 5 files changed, 249 insertions(+), 340 deletions(-) delete mode 100644 api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api_requires_valid_region_code.yaml diff --git a/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges.yaml b/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges.yaml index 103eaa121..27d717428 100644 --- a/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges.yaml +++ b/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges.yaml @@ -19,76 +19,84 @@ interactions: response: body: string: !!binary | - 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 + AA== headers: Alt-Svc: - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 @@ -99,11 +107,11 @@ interactions: Content-Type: - application/json; charset=UTF-8 Date: - - Wed, 21 Aug 2024 01:18:30 GMT + - Thu, 22 Aug 2024 04:44:11 GMT Server: - ESF Server-Timing: - - gfet4t7; dur=404 + - gfet4t7; dur=572 Transfer-Encoding: - chunked Vary: @@ -190,11 +198,11 @@ interactions: Content-Type: - application/json; charset=UTF-8 Date: - - Wed, 21 Aug 2024 01:18:31 GMT + - Thu, 22 Aug 2024 04:44:11 GMT Server: - ESF Server-Timing: - - gfet4t7; dur=132 + - gfet4t7; dur=311 Transfer-Encoding: - chunked Vary: diff --git a/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api.yaml b/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api.yaml index b7627b870..c7643ec4c 100644 --- a/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api.yaml +++ b/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api.yaml @@ -19,76 +19,84 @@ interactions: response: body: string: !!binary | - H4sIAAAAAAAC/+1dbXPUSJL+Pr+C4POgyMrKysr0NwOeGd8B3gB2uNuLDUKvHBEs5oy9F3Mb898v - ZWxsjy2hskpNd08rHA6wqltSKV+efP/XDw8ePOw+HB83r07L07PP7eeHew/+y/744MG/zn/b6Xfl - 2bv2sLETDx+/efr47as3GOHhj5en33/+fNY2r9//o+1XICA9AnmE7jW4Pef2gAoBAMd/u/pId3zS - 1uXn0/5DL8uP7/pPXl7OTn8+LU9Ob3wZvgbdA7Cfq2+xhe3HZnDZxarfb130yX/fvuI/yw9n7R0n - 7NSH4/9tTx4fn51fCn68furs06drpwoMX0/+fu0mT9quPWk/1u3dT3vn88Kdz3vHE8PtJ7arDz77 - 65OLL3h5+Org6n38o/x0+PHyLn/7dP4inx89PXh2teRz+8/25P3pb/2pVwe/Hry89vH3H20LytP3 - xx+fl59etac39/bG2Svy+nJc34d+s+0qH/pL/HL48y83nvz8Fk7elx/e/1/b/OX4w2/vjj9+ocmO - nTTaQEUOKLahjL4FH7AOFH2sq4fXvuX3Hydc+/nB08O/Pp949VDWLgamTrkmx2XJgRHRQRerlkJI - vvqzozcTL+0bqbx23NX27KHptOGyRqVQShlihTcu/fXff/9x6NUk0Ofd/DiNI29yx41buKS9v7w8 - erz/+PDZ4ev/vM3Hn4/PTur2UhpdUeG5mHp2XJ9/2U0S/GB/Oz1r+g8hFayOia7dw4fjj+8uz6sr - vCir3Lru/5zZOzj97Vd7Gd37tn/M05Oz9odri8YkJso0iWnbRVIwhsB+2yXm5ojLF0dvn/yy/+Ln - g7sFop3+6dnR0dPDFz8/zEenJr0QZIhOoSDvgDPTqUwlU9wjX0RyEnEbyPRRr76HSdVOQ4AvR6QA - QYA3h3p/2n82oMmXIVzPIjgkYEWKEDyrZhawDhMpVyP9bRwCHT7f//ng7ZNn+69eHf50+GT/9eHR - i01ARN5wEEhUp6JUciVdU7cgHFyoDa24ZRGRUM2iGsW3jrRty6puagg1t3X/f1gQEXEgKlVDQ539 - dKEKTQtQS4fsmsZVCyKimUz8PRGRLwyvYtBhRERe0Lu8DOtiGsMG9P46wy4vxky1kYahXcGCxHA/ - 5t0Vv5+2KV7cdsDEwl3o16AMZPhcbnDRH0xtT3p+EHgNPgS8k5PWUhnftLyXpmJfaGBlHuZt55Ry - U7FtUpoyjij4DWU84o/Yf3z068HbF0cvn+8/WxcdDFVdAlQGFoOnNjTaaWQfayHTUaHsltXBDTfQ - laCl6yrb3LaqvUcSsxjsfpxPRwDTdTDV3p4UTNPbk9YMUoNgp23VVY1WWC6rg3kq7/J66WAqSE2Z - jHglYiSJfOu68/iUEsw9KtgrB1ihDkbTCgZjh1UwsDfyzrspQqm4BGepYPsynKCCry9bRAWbjTtu - AbsLA9hQPDjHboOU7motYCyUxeGg68aYucctlBlQh39LI1xT/LoN2PFRGnjcUe2gwaPOIMqQ30aL - 3uuVm2qReXoo0ReGXaJfpQoKBQBRHDSOsUA2TspsHKOfuCtflZD4WX7YdVFCu3DBvemURXGYe6Vg - Z/gxt6EnYSL3Qh/Wcp69zKRTFybR6dWyHZ2uE51yAT7qkD/CyJTMZNSYGRrRRDK9FKdgamZLoBFe - oHZUATNVrpuYd2D8XZRrMlrqswjcCCFHMns+c5TLcYJjjQpyUefKW3ST5O3VspXL29vof3OIdtXe - YAdOeMgwNYgPypF9ZqJ1E7MFrwxTDSuE+L6g6CCOmOtOxWfmZPtWfZkY6yEXtkUp7TxNFwvmkm5k - YcJhho5RJLeHFI14QxrxEqrCNhDveAbwH7HW5tDtahURFw4DxkH0ZIqoz37LLHN9algSvVtlyoFd - UkziDQaBoPC+Ty/OrJ7BJQZrnWwFK9+laLbCrF+1DgrerIwRUBnMbAmZQ5fRJWbKGKicZdKvjYc0 - xaKHgmBB22hOtH3dVJKRMSMP+vltJ8XkRGYgFUOR6Jmyly7Z0lbXMXGmdt41ttWd44paB+qaKkhV - Y+2EfNkumziD0tUVgvNNiORjqOoOKDRV06hvpW4WTJzpfFu24pG9sakqSoiVD9w0sQOuqd0lr37d - 3JtsKxSGwh7GtnxezpOJb5+8efIWHD56/vTV4bOJjOv3vBZeiWiu/qFp+oe+mwGUUbegbdskgrxa - mKJbvhH5uFswXpGq0cG93EwewtdjJNcL+dqRuxINJuY3OcMxXGBUh26FRlCf6dZn9A7tDpppqCab - 8+6KJqhhKojMcJiVO7NGaHLEFWeg50uitYhtOkQHWT0a2wUfvcEG9CP40Sv43J449ql5Ije00PJZ - CbYlZvuNqGfuUzwz74pzk2G17gUtIoOEbcmFu1UbMepq32CX5aoDvkE1uJEEm75aCHNnaMdEBgfG - VTI4FWYeBRpM0YZCDT9A7l2BmOj82RKX5S7t6N7qmSl4HqrmM+4VQv3awSVb3lFM9e+ASZltoNSd - c/1iwfy6oBhlJMDrvMTcznVOJFonc33rOM0awqWtoRSaLTa239MKSgm8Qx1ypkvvD3OmlPNSLWla - SMg4y28FKkjL8tzJ2kGqZR9kMARkVMuiEnL74+LUekOxn0LA440I0H2o9g7Hy11U+0e3yxa5nrZJ - 2vpCnTCNOFkicsjtMPUFTY2AXKIEcFvRK2pnhN0/VucMVA22VOnVGHvN7COlyTF2h3teCjQ8jTtC - /TMTqlEMEcYhZ/45EmCXW6QGKFKrPtlvS5nSroI7h3wVMbNrpII7Roy5s8Fjmi+WIuFWlDHspOu9 - pasgDIYMeuHKMWhmV2xa4Rw7cjzXNwDTqBS+G5XuCucSqutjoDgYPtACGAPldg2wLxJz841qh0rn - /vri318cvXmRcU8g9t2XhtG8iEbOzMekiRviyW2DttlVci/F21RQBB1MOOtRkxMvmVsSICZlnAXn - Pc51+60LIe+KPy8WzG5BgD7ACOH2xdzZ/dWQZqSS03mEu2v5ctfjbhDe78sa+37kQ3QqhQQ7nz33 - IrXrAM6LBm5Gq4zNFa6rrlD23qDWoJUqvYuQIDPRIic6UzDAXGfKepiptwsVt0Lcrjzvwg4/Ulki - pBRyB1gSG/kDxtVW1bOyPfewnWoQhXL3tUxlZI43et5s0ziSpuKOyia2bK/BVXWpWkYPTSshtKaG - lq3ohM5RF4M3KMwUO66qrq47VMZOXUS/5IC2UqSOMfR9VampyK6MAqU9NHmGLu4qOr9u7s35QcFu - b2QciVCQ3IU0PnHwFfo/y+CrDYaMK2+gjKDDubpSeCcm6TMrmtQKsEhbMTEmudJp5xCdXrTXN2Ed - yX7w0Y7cDV1Sx0G5eY79tTHXbxPmmAG/uUOGVzAw0+z1wU4Q/aQjIMndkDW5gwtF1O3I391OMt2C - 2VOtYJRGkWoE041Ota2kcw77djJm6S5rcEUuG+zqWGkbCMpo+tkjQOsAsY9PL2hwBa4kmNEFvlIq - 1UusW2mqsopYI3dhQYPrbq6cxpff3eBiFA8jkpPFMefuyZ5a2Yw6z9VpmnyKq/P6soUU/p/B1Zko - RtfLY6U1+BbqUAesKDSu6rhkF6FsIjkXy2UFqO86BSk5gqtJKy8cm0Bci5Y1lhIXFKAodlEJGFps - TXt0pWPPEEGa0IampgUF6N3sOY1Bv7sAFYU4GCtSLJw6cJnTxRESBaj3ONNiAj9JgF4tW0SA7jJI - chGuK6L6kU5kWCDYgsyWvotpOXzBwMfcnghTWufh4q3z0srL/cVap/YWUHSDHFarLoCM3iyekb7Z - pOxzx+oNCCQa/sCrjHtiIRDj6EhZlz8/F6d2E3dGVa4IIcYI2QKf62iN1z7U6lkNwTUEATQ6r9y2 - bcA6xK5eFkxyBSW2wlUVgSoNAk1j1lx0Jag6jwuCSUOQldbqMJYdhVartuy84651YNiywmXDnxs8 - CRoFZCT8qT6GBcq5w9Rybt0LrpAAMxOS16ahbVLt4QZ7NlcxR2lseAVyX7yQWd3QVCWsexj6nD6K - vNoJ5koyPFvKELZjzB0Tdn56A8zLLO0QcIX7EnqTmAY7BPU9kEOPfHPvi+13YrIahFX2U+zHY0IY - HSsIyJJb+iemSqPgtjSp2zVOygFZgCMPSf6+ONL73EmnyAlOBCoYws3GqLtM6TUj2VUX9EJ0PJYp - baZa8Jk71DlKVssY5nZW3MQsl11hekLvLwc6hrq9AYbMye2oU3vWXWbL0rx52m4aYHBLA4ZdDeC9 - 5W00K2gMI5CPPnefcOdjQktQ0wmgJvS3Adnu2n58WTC7oZIZ5zIyprR3qOae0KOJLS5UedfiYpfR - /Y3GYF7iSGMwJyia2duSOtnQzR6QthbpCbv66y8L5pKsM8AAI01t+1qb3B2XKNU88zeClxsrene4 - 9t64VhGYR4Yf92WnuWFtSEygMZSH34ixb1iKe4CWuYrY1hVTRWZatA02WIUu1hCaatmgesll29Qt - RbsFio3J8lC3XIYSWcu2XjJD04W6YXJlEI3ElQiWTelcG+tITR1hF1T/urk3a4oV4/BQSVeQA0+5 - fdSJrVGD2Rpz4yo7H/W6privoxhldiXV/fvpStI69sJLuoAV2x+be6SaJ4nRiupQdhTrqlLqKqwa - Dl1HZs5yI+y6BcVoVYs9HjbKfQ9LQqU21DV31LCUfYuz5cTo3Uw6jU2/sxj1BXo3OCDlfNh2n+2Q - GZNzoYmTJiDCDpavjdT8LrDcAelgz58elpv5nTm6x5Ia3UPc/okomzxhduXe5igSRkZIAwavmcWr - yNQQSdwLBuzOxzHNDElP89Ph4mVEu843lwtmVxAT4SDlihTAormzKXxqI1qOc+vfpjWihYUb0e6m - VF4smJ0DBBrjGJwNKLnLNl1ILBtyUfgbzrvpBTIH//H65cHztSm0jhBqrWI/P9bsUDovsIaKQ4VY - 9VbZwvan69oGiUPjG2pakrq/h9AGQee8pDsRE2pj1GkZoG0RzAoGKLmTulEjDmyNM/2ybrzNbQ0I - 2lenD7vxgrLLXefnp9ZZyx5K0Td7lK3IIdllR18smN0dgAh0pJO0egSfW82kjuVCmJdpui5Uu/OZ - 3F+4EngaSSXlAMHnjpGkZjuh16EJR4vN1Is6MuWIsnf2cE4T5z4FJOdXuCtYBIbBvLjzFr1MmLtj - FGHqtnjPc4XaWvTau8sZsRVybtWdTSMbr4z4KaJ3wpn9FBgSh7hFvhEGXoEdLDEOp1oZ1znJjU+Q - NdFbHoB1rrd8LZh51wZmsQawEuwY1ko+ampNl/3++w+///D/CL4NZijRAAA= + H4sIAAAAAAAC/+1dW48Ux5J+96+weDalyIzIyAjeAGOf2eVyBBx716sjK6sy04vEAS+Xs/Ie+b9v + 1BiGGTPV7qSzhp52ty0YUTVdXdVx+b64/uuLL7+8UZ+/fJmfvElv3r4ur2/c+vK/7B+//PJfp3/a + 4Z/S25/KSbYDN+58//WdH5987yPc+Or94WevX78t+emzf5T5DA+eboLc9P4p0C3Pt5wfAiqi/+HD + r9SXr8qUXr+Zf+lxevHT/JvvL2eHX79Jr95ceDN8CnoLwP7/8C52YnmRF097d9avH1307n9/fMV/ + pudvyyUH7NDzl/9bXt15+fb0UvDV+UNvf/753KGzI7+e+4SvSi2vyoupXH6rl96su/RmL7ld9/Ht + 2tUXb/zpq3dv8PDRj3f/cvvht/c+fCP/SD+fvHj/UX/5+fSrfPDo63v3P5zyuvyzvHr25pf50JN7 + 3917fO7Xn72wh5DePHv54kH6+Ul5c/HpXjj6QcB+e51/GPPjtqs8ny/xl5Nv/3Lh9k8/wqtn6fmz + /yv5ry+f//LTyxe/SSU6qihAPtpPJTrNOKWRpKijcYJ649y7/PrVFtd+cO/rk7892PLqwbsQMjpI + xZHmOhKO3tn3HpRDdtp89fuPvt/y0jDlav/lzMCEoSbvo3gmqFGdKl249NnPf/9q6atpENLLNXI7 + nbyoIhc+wnvZ++vjR3du3zm5f/L0Pz/W5Ncv376aynt79EEKTw3V/ZfT6ZtdFMHn9m9v3ub5lzwN + rI6Jzn2G5y9f/PT+uLoBRVnlo+v+z1v7Dt788p19GfVZmW/zzau35YtzJ22ymV6abCbZi3exmf6p + 91vYzPOnrWMzBwe/vUw9wDl2foMVHcL1saOPT57cu9w+moX95v6jR1+fPPz2Rj+xjRg9yJLYwkBm + hLiz2Eqb1JoZhp2kdl88/U0YfFiW05uXSPX1Edxvbt9fcOzrCC6yiF+ytyJDCMiqne2t842Saz7z + h82I6OTB7W/v/Xj3/u0nT06+Obl7++nJo4fXASBF4SSxaC0+kCSVFAWK947As8t5XYA0cqaJq0we + K7kQpUSOI6SKfowU44oASSqzJuZxmkYCAnGOQhxxjGnyFMOKAGlHJf6cAAkHEw0fdBkgEYpH11dh + XWxWWJbdAJLbxtWcP+0IkHYASNebYyJ55TKWSY06UFGjXGbUTE80JFibY0bSItXJCC4aw9WUNFAY + a6ph8qapa3JMzoVTnEYf7bYxJ7Pmagw3oRHdMPGKJvRyBd1ORT87x5ToScOSCfUDSWDyH113JxOK + t9soZjB3uCNY5+3AOq9sQTdh9T+Pybx959F39358+Ojxg9v398Vwah19ASyJvKdMIrEiwegQDZfV + OK5rOFP2RShHnZBoKkUkiw8cOQTR+gnId3vDmdSFoIiifiQfx5SKM9ypfqpcEdbEnpfr5Xaa+dmx + pwZW5mXs6ZxSb8NpD6QRe6r/I7J4baCNQp0KhOwdK3E0ohbSaHzdlwBJ08rQBiSPGhzXMQYC8KlO + joMmlMQp1/arb6+hZHA7pAnsakKjmsImyhIn8GPJBniO7PDs4V6ANmQQeDGcYxoaIxk366yh1BiI + VI/4w+Xq97eH//7w0ffnIze7PRE/uBDVLWM9YKTY2WQJtWE9BMIDDW+Z2XA4U7JoKCMIaHYOlRMX + QufErWvAquCYAc2CuGCgPqRqiEcxG7wInKUd4GxvwIJmjdUVKMlRlCB21/YZ7LPEglDKugZsO4jh + 9g5i+EFZnF9MpJgBAzR+3VdfXfi3NgMWmfSYSdlzunbVmRRRxxiXMik6mPXj3pLrmdtcTVR/rPbZ + GxHdvdpnH8MKVUpKUo2uIBradCo5RBlDpeph8u1JpcaUVhmr6QW56CjjaL5+Ih6jCKLjac14rKjd + 5mREJWUgnfOmlT2D5wAu+PGY0vrwcM9ZzjAAkBmmZYxuD9Bp55SWxzbLiQoCC6RlDX8SBhbjSYv+ + RAZ2xuR6B1skNIapfYg7JvrCdom+cPQnSze+yZ+sLac8AEZdigmamBKD2cXOgJ0axZS97iSm+wJ7 + ZkQefkPkQRmIieQgJPeqwfpcZeo2SG0k8tS57MlxaySb3E5g3T/1brsyU/fZjOvH8nx9hPZqi0zR + yLgTXoqNGMME5cjYWWhdYz9JFD7UYGYFhym6kGtAqrkKAU5VpRQwlqG8LrHJKlyJjc5IIQwysk8R + Exqp906crElsED2UqkknIvSTms5q1WmsRXn6XY3LkdicKSxFB3FDMNOoMXZ2Mvau+rgNHAnIQcSE + 5mjmu3ClVwGP/nwm7Peex86Gd64HIgWYw3PXx/VcLV7CIbIw+WXXE6NI7zSaN1kObbKMGuNBROY3 + QqaPpPz6yO3VQiYenA8+LuJ8g0xz405nE4ytFSsaQrjC0JJps5DCYpUADIgceoeWDLw2sh/HcAiq + fOTs707YVWpNUWQxNTwn2Ixgh861LdG11e1ijBeqzz5FardpDT1/2pU7oJ4iukulwh+L6GcIiJqc + sufFbAYMhrehdzIjhqExIhrtQ3aj6fuYhYzJFxjLSEiJ/JTGOs19GYg5BHZh5SxkCDlNAJTGEaho + kBqzC6VCzhnGTyitbugKiRVL5cqcM2lGTZ4yU8iG0GeudyTrZw/3otoKhaV0m6ktn04e6KS3d7+/ + +yM4f/PB109O7m+puHILw8Dgw4XiyU8ICkPcKij84bTr62DsLvAWbtWm9OHEjg7m9/HLD0JqEvBJ + ASWEcPbaUOfr+dyr97gMaKtvRWGlBX7Tu953rnDGEJYiFXPBb9RInYPk2uh8idyukxi2SeycP+36 + 6vBhgkT0Zv9xA0pEBewdUGNsrhZcUtx1al7skRiF2+CEZ+TWfRqFawfPhxFlvAkDvqvvdepBvZyv + 5Pi9Sl8WyOip5YcUraAhqAa3oXxrbkH2vTtxYpuCo2KUK1RwGoAMtiy248Cg6jz0fioQW/EKhUNQ + 72NR2ye7Z5MA5KURAaa9Ql596CunjmKrI+JIB1PX1jBo5foI71V7HdIYZUOe1qHE3jFybhNaczm4 + 4/TE43CgQ8rS0iDovC6FzE1qUV1wnWPmpK2ZnSA7Bd72yNYem/7en7DzuFoMspjsMcllUQm942+x + Nf4mble6ui+zhLav74KB4NqS1auuLFZnnGdD3CV6Dr1jpjjQtqmPs8kufBBo98jLPj1J58whLY5u + mw0Eo3YOm1Jzcp2D7loEsheC2lZRe41k92phQphTPj4uRftPYQK73gY2wNDY4ioRD8K+HhFuR4tr + 4NHrhrEWMfrYu/I7NgZso+hB5GOOwOCTLax4WMwrzAaWY9DO8drmds4Au5pX2E5K4bNJ6eCPYa5F + GTUZpLiYVNABeN4B0FdIPePQXHhPfiEp2LtcJ8wNGBQXy3XA3I9G7qy4pM3uZddZzHvhXo4Ncmvp + Ng0UQRfLzmaY5MTwdWfd9o2ZF9HD2AB0zLy8P2HnORgeA2wQ23miQPf4NbSOXnK8k/3dlyFDxyz3 + uxN271+MIBtqqyTY8e7VGa2LVUPYcQfONZjecmxF3roVGdEe0yJFldOycOgstJ5bS9+UDyLJfYyk + fHoxhr1wQ2uJkFLonWJpnoylSxR1pXpAZbvmMk0lZw+l83DfVt2NdAEmHdLkpRKrY6Ohph6eRgVx + MsWUR4quJKkX10F8tcW12yYvieY8jg5TysS1pgzJLuzmhVsQ45p7MIIb86SGmGtFYrt3Qo8uVw6x + +Nm6n7/02c9/9mZOGjDYx9uwJVEoSO/uGmzdx6twEL72mG7r6X096HIBrwzoxOx8Z0fT2DUicuyP + 2B8J/SzpNjeP9d1Q0IDRXr1nsbSBRELctVN+Twh4W7Tzo46+6yPKVx39jEbIF0c+zOvsgKT3EODm + US0owR3EIKyDNbfXesUgBI7V5zSx0alSNLGTUOo4L8icnLSPlW2iVigJKkyjkKuUxzRGDZNLGY3a + BTe1j9Tdnlp5GMXUf+JQjdU5VZcAUxw9IoyZ6Uitzh7uxZYHLwgbrCaLY+498L+xsXlecrgrt9pm + Sg6uPiXnT5LpvNYmNOSYRohpClDIFR2TGVXhwtOo9i8rm1C7AASXJkrJUQVKZsJzMJNOxdXq22Nj + DXuUx0AEBerplDMMKbKrpYYpB6xktHI9E3q5gm6nop/dhIpCXEwFqR+cOnCdy8E9tA5/CXyVU2nd + EBU3zLTyg9EZ7N277GJrLVjcLfZhb7ZdLQKsvPCoaSjtgKSnL5rXb84Dtq6ro7mC4gT0UTYMVyZl + 7J3nda41zwvSb0vHvf94+vjeg71xxyLO7IQmTKkQEYtMhaOBffaqMOHKySKUrGFePBwmYlBj73Pp + n3L1o3Ca1pz8GXAaeYKQYSIdSaeUYj4d3V+pcDoymrOHe2HnsECMG5emu/41yL55HDqxHqrGTlRH + 4/0kFZhUnPqg1QeQyXs0ELuuxqqbqrqq7BiphmSvIEC1qJZAud1ebK+xUzZDHIinWgxAm9+IHLMZ + KRwnyk6PGvvh4V6stvb23DakdxVjWKFhPTQ3rMeDiNweVxi8O2H3hVCb1m54nispO/sZakOGFPlC + L+Xaz2QmuyTLS7KM9jn2vTPeDltnfqIajLvaWajqaHEo0jziOcw5vt7PxZ53Y5aVr3R5zbxvFsLG + 1Z3gWXrb/rbab+J4GCm7Y2lPx2wzcOQl6z93fyL2Lqv13BjdUk+7LhfYZlKUX39S1DFt8v4z7vue + Fp5KgIRa00h5QokxcIk+BZ2bS8q63K+KkzhFMMaHxMkpOhaXJjDe6dMnrHRtSJ7EElwClSpzoGiS + MPpYI1XibIxwXJH7Xa6m2ynqZ+Z+c8f4zNOXcRGBUb/OwyIdtY+Aop1GQO1P8dlHTeCbLOk1HhB/ + 9TP3HOgmNogGZDu3lHhtHB2pGHZsvd0KyPrPWXt2FNrtjW80qr4JxBJG7D2/32FsG9VrnPQw9nMc + W29/O2HnGWbsSTZsAdbZrXWecqBt1IsQ9biF/Thk5g9m8c30aFmOnXjRziHB1uH+ga9yZRTaPccL + mPTjibAqvYdqUfPGg50nv+2Fbh9sBf/6wGnu4eUNy6sjc/ckR2h0QRHgj0oMNgSX9qymAM2VIINM + UxJSlDFIdk4riBRJU165KLcmX7hGKa7S5JLYlxHQO8clBhzX3P9b/OQKOEreTPGUJik1E+YENFZN + smZc6VrXFBj+isuLQ91ADpB6B+gbJ93OTTF4pe7Vo9u0zJxxzt529q48aGuhBcifcOD6ETy3eGAH + pIsjXGYPDK73jiGW5l5PjgfBAhvDxsdYxvYcMIqEDYuD5wXx2tkii7TuylLYMWzscbvsB65ujzfX + PxwN8PaNo0R+UXJFBmDR3ok7bF2BQReAxPpeyShXjJsAVvDSuxXMhfZukYOtPfdVUhoZcvRMWXD0 + wljSFEZJNU1pXZ7oQ85lNKo25520TJLELlrROKsvWmhFnuiduikwFO8jzdOyXNSUU3E+Z00IR554 + 9nAvlnGpBL+4gsoNQdn1bu/C1glNUY8Bx71xtJ9njCcR6IZxs4oesLdjaQ1nUJCDnyR2XImyyZgS + IG0ogmED1dg76NaYmsW5KPBKg24i5os3LEWh7tMBnNPmNTEArhso3MfKVINidczF8LcyhamI/TVG + HaOMUB20x/DbuhKTn8bZPuaE5HRuSqwEwUVIdTKkuGYfMcz4TwOIz5RrGSOeZpbBh8L+d0OZjsjw + rJPJwPRilcnpzFkm33swEvlGvSUS3mkvwb5sgz5u03h3ws41fRyD3xCXmbWfO8dlfGj0NgrxKtvM + wgAS43JdiWmdk97w2bM2dyV6PpB8QVPDznG1+/YzTiXYa9krYdTWdgn78+9f/PrF/wO9GU7codwA + AA== headers: Alt-Svc: - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 @@ -99,11 +107,11 @@ interactions: Content-Type: - application/json; charset=UTF-8 Date: - - Wed, 21 Aug 2024 01:18:31 GMT + - Thu, 22 Aug 2024 04:44:12 GMT Server: - ESF Server-Timing: - - gfet4t7; dur=361 + - gfet4t7; dur=589 Transfer-Encoding: - chunked Vary: @@ -190,11 +198,11 @@ interactions: Content-Type: - application/json; charset=UTF-8 Date: - - Wed, 21 Aug 2024 01:18:32 GMT + - Thu, 22 Aug 2024 04:44:12 GMT Server: - ESF Server-Timing: - - gfet4t7; dur=126 + - gfet4t7; dur=399 Transfer-Encoding: - chunked Vary: @@ -210,49 +218,4 @@ interactions: status: code: 200 message: OK -- request: - body: '' - headers: - accept: - - '*/*' - accept-encoding: - - gzip, deflate - connection: - - keep-alive - host: - - testserver - user-agent: - - testclient - method: GET - uri: http://testserver/google-floods/gauges/?region_codes=BD - response: - body: - string: '{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[91.389698,24.691644]},"properties":{"gaugeId":"BWDB_SW270","issuedTime":"2024-08-21T01:11:04.800016Z","siteName":"Markuli","river":"Surma-Meghna","severity":"SEVERE","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"f618d9d0b41047e5a73e0352c54737cb"},{"level":"MEDIUM","serializedPolygonId":"5ac17564f96c416aa65622210f7be455"},{"level":"LOW","serializedPolygonId":"3d8b39f6fc0b45df9d6ac2945a8a57b2"}],"inundationMapsTimeRange":{"start":"2024-08-22T09:00:00Z","end":"2024-08-22T09:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.431068,24.737208]},"properties":{"gaugeId":"BWDB_SW228","issuedTime":"2024-08-21T01:09:48.625563Z","siteName":"Mymensingh","river":"Old - Brahmaputra","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.553699,24.368824]},"properties":{"gaugeId":"BWDB_SW88","issuedTime":"2024-08-21T01:02:43.741872Z","siteName":"Rajshahi","river":"Ganges","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.438231,23.221259]},"properties":{"gaugeId":"BWDB_SW212","issuedTime":"2024-08-21T01:02:43.741974Z","siteName":"Parshuram","river":"Muhuri","severity":"SEVERE","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"3047087919894a6b8fdce086515cc171"},{"level":"MEDIUM","serializedPolygonId":"84c6899783e149eeabcdc05c6ec149e0"},{"level":"LOW","serializedPolygonId":"6544a995d4fd4ff5b5de00c8f261dd1b"}],"inundationMapsTimeRange":{"start":"2024-08-20T09:00:00Z","end":"2024-08-20T09:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.485642,24.872495]},"properties":{"gaugeId":"BWDB_SW172","issuedTime":"2024-08-21T01:02:43.752334Z","siteName":"Amalshid","river":"Kushiyara","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.119442,23.956966]},"properties":{"gaugeId":"BWDB_SW3A","issuedTime":"2024-08-21T01:02:43.753813Z","siteName":"B. - Baria","river":"Titas","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.774876,24.496424]},"properties":{"gaugeId":"BWDB_SW202","issuedTime":"2024-08-21T01:02:43.747282Z","siteName":"Moulvibazar","river":"Manu","severity":"ABOVE_NORMAL","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"0bca00b745534e5d9f97637c845445af"},{"level":"MEDIUM","serializedPolygonId":"d6d0fa09a1fb472ebc33248431455131"},{"level":"LOW","serializedPolygonId":"4c3976049e454c608c082f9ebfbd9b2a"}],"inundationMapsTimeRange":{"start":"2024-08-20T06:00:00Z","end":"2024-08-20T06:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.063472,22.15791]},"properties":{"gaugeId":"BWDB_SW248","issuedTime":"2024-08-21T01:02:44.639650Z","siteName":"Dohazari","river":"Sangu","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.703954,22.968128]},"properties":{"gaugeId":"BWDB_SW84","issuedTime":"2024-08-21T01:02:43.752323Z","siteName":"Ramgarh","river":"Feni","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.580654,24.891637]},"properties":{"gaugeId":"BWDB_SW15J","issuedTime":"2024-08-21T01:02:43.751949Z","siteName":"Sariakandi - (Mathurapara)","river":"Jamuna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.265191,25.004479]},"properties":{"gaugeId":"BWDB_SW266","issuedTime":"2024-08-21T01:11:03.131730Z","siteName":"Kanaighat","river":"Surma","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.618762,25.689237]},"properties":{"gaugeId":"BWDB_SW236","issuedTime":"2024-08-21T01:02:43.752832Z","siteName":"Dinajpur","river":"Punarbhaba","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.460897,26.03796]},"properties":{"gaugeId":"BWDB_SW285","issuedTime":"2024-08-21T01:10:48.136382Z","siteName":"Thakurgaon","river":"Tangon","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.744249,24.916416]},"properties":{"gaugeId":"BWDB_SW145","issuedTime":"2024-08-21T01:02:43.750317Z","siteName":"Mohadebpur","river":"Atrai","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.096763,23.101868]},"properties":{"gaugeId":"BWDB_SW162","issuedTime":"2024-08-21T01:02:44.417982Z","siteName":"Jhikargacha","river":"Kobadak","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.19839,23.471078]},"properties":{"gaugeId":"BWDB_SW110","issuedTime":"2024-08-21T01:02:43.751995Z","siteName":"Cumilla","river":"Gumti","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.778872,23.768642]},"properties":{"gaugeId":"BWDB_SW91.9R","issuedTime":"2024-08-21T01:02:43.753415Z","siteName":"Goalondo - (Transit)","river":"Padma","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.073729,26.125276]},"properties":{"gaugeId":"BWDB_SW291.5R","issuedTime":"2024-08-21T01:02:43.742990Z","siteName":"Dalia","river":"Teesta","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.336562,23.784904]},"properties":{"gaugeId":"BWDB_SW302","issuedTime":"2024-08-21T01:02:43.742314Z","siteName":"Mirpur","river":"Turag","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.516256,23.539828]},"properties":{"gaugeId":"BWDB_SW101","issuedTime":"2024-08-21T01:02:43.747180Z","siteName":"Kamarkhali - (Transit)","river":"Gorai","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.48001,23.56269]},"properties":{"gaugeId":"BWDB_SW71A","issuedTime":"2024-08-21T01:02:43.751997Z","siteName":"Rekabi-Bazar","river":"Dhaleswari","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.638969,23.58457]},"properties":{"gaugeId":"BWDB_SW275.5","issuedTime":"2024-08-21T01:02:43.752988Z","siteName":"Meghna - Bridge","river":"Meghna","severity":"ABOVE_NORMAL","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"c131d800f16b4e1091db58bc2c1843ae"},{"level":"MEDIUM","serializedPolygonId":"28fcb2013d574375bcf045dbdd93e8cd"},{"level":"LOW","serializedPolygonId":"f3eae83263644992857b356dd7f06c4e"}],"inundationMapsTimeRange":{"start":"2024-08-20T09:00:00Z","end":"2024-08-20T09:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.26666666666668,23.473055555555554]},"properties":{"gaugeId":"CWC_012-MDSIL","issuedTime":"2024-08-21T01:03:39.394447Z","siteName":"Sonamura - (II)","river":null,"severity":"ABOVE_NORMAL","source":"CWC","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.079743,21.773552]},"properties":{"gaugeId":"BWDB_SW204","issuedTime":"2024-08-21T01:12:06.279121Z","siteName":"Chiringa","river":"Matamuhuri","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.439032,23.320123]},"properties":{"gaugeId":"BWDB_SW95","issuedTime":"2024-08-21T01:02:44.441009Z","siteName":"Sureshswar","river":"Padma","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.661579,25.123256]},"properties":{"gaugeId":"BWDB_SW263","issuedTime":"2024-08-21T01:02:43.752847Z","siteName":"Durgapur","river":"Someswari","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.249526,24.599517]},"properties":{"gaugeId":"BWDB_SW211.5","issuedTime":"2024-08-21T01:09:59.760859Z","siteName":"Chapai-Nawabganj","river":"Mohananda","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.991206,24.045541]},"properties":{"gaugeId":"BWDB_SW273","issuedTime":"2024-08-21T01:02:43.750627Z","siteName":"Bhairab - Bazar","river":"Upper Meghna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.842925,23.645365]},"properties":{"gaugeId":"BWDB_SW207","issuedTime":"2024-08-21T01:02:43.751180Z","siteName":"Chuadanga","river":"Mathabhanga","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.138756,24.497782]},"properties":{"gaugeId":"BWDB_SW147.5","issuedTime":"2024-08-21T01:02:43.750599Z","siteName":"Singra","river":"Atrai - Gur","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.391511,24.831299]},"properties":{"gaugeId":"BWDB_SW65","issuedTime":"2024-08-21T01:02:43.751897Z","siteName":"Bogura","river":"Karatoa","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.689858,24.635869]},"properties":{"gaugeId":"BWDB_SW49A","issuedTime":"2024-08-21T01:02:43.749730Z","siteName":"Kazipur","river":"Jamuna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.72653,23.918646]},"properties":{"gaugeId":"BWDB_SW274","issuedTime":"2024-08-21T01:08:08.803288Z","siteName":"Narsingdi","river":"Meghna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.206392,23.511165]},"properties":{"gaugeId":"BWDB_SW93.4L","issuedTime":"2024-08-21T01:02:43.751012Z","siteName":"Bhagyakul","river":"Padma","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.686153,25.544273]},"properties":{"gaugeId":"BWDB_SW45.5","issuedTime":"2024-08-21T01:12:38.287522Z","siteName":"Chilmari","river":"Brahmaputra","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.772772,23.881297]},"properties":{"gaugeId":"BWDB_SW50.6","issuedTime":"2024-08-21T01:02:43.752637Z","siteName":"Aricha","river":"Jamuna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.667595,25.82041]},"properties":{"gaugeId":"BWDB_SW77","issuedTime":"2024-08-21T01:02:43.747425Z","siteName":"Kurigram","river":"Dharla","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.062548,25.675475]},"properties":{"gaugeId":"BWDB_SW62","issuedTime":"2024-08-21T01:02:44.614160Z","siteName":"Badarganj","river":"Jamuneswari","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.889765,25.073472]},"properties":{"gaugeId":"BWDB_SW263.1","issuedTime":"2024-08-21T01:02:43.741605Z","siteName":"Kalmakanda","river":"Someswari","severity":"UNKNOWN","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.718387,24.470952]},"properties":{"gaugeId":"BWDB_SW49","issuedTime":"2024-08-21T01:02:43.741341Z","siteName":"Serajganj","river":"Jamuna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.967658,24.923502]},"properties":{"gaugeId":"BWDB_SW225","issuedTime":"2024-08-21T01:02:44.513328Z","siteName":"Jamalpur","river":"Old - Brahmaputra","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.857085,23.787087]},"properties":{"gaugeId":"BWDB_SW206","issuedTime":"2024-08-21T01:02:43.741928Z","siteName":"Hatboalia","river":"Mathabhanga","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.544405,26.330021]},"properties":{"gaugeId":"BWDB_SW140","issuedTime":"2024-08-21T01:02:43.751230Z","siteName":"Panchagarh","river":"Upper - Karatoa","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.849452,24.888834]},"properties":{"gaugeId":"BWDB_SW267","issuedTime":"2024-08-21T01:02:43.742505Z","siteName":"Sylhet","river":"Surma","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.419454,23.696849]},"properties":{"gaugeId":"BWDB_SW42","issuedTime":"2024-08-21T01:02:43.750274Z","siteName":"Dhaka - (MilBarack)","river":"Buriganga","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.84582,24.352029]},"properties":{"gaugeId":"BWDB_SW67","issuedTime":"2024-08-21T01:02:43.746795Z","siteName":"Kamalganj","river":"Dhalai","severity":"SEVERE","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"db6f4ad7e66841bca99a730de855e901"},{"level":"MEDIUM","serializedPolygonId":"0f14f753676647f6bbfccf2962f91723"},{"level":"LOW","serializedPolygonId":"3a88c77589164db4bfc280a5e94360f7"}],"inundationMapsTimeRange":{"start":"2024-08-20T09:00:00Z","end":"2024-08-20T09:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.318746,24.820982]},"properties":{"gaugeId":"BWDB_SW238","issuedTime":"2024-08-21T01:02:43.742372Z","siteName":"Rohanpur","river":"Punarvaba","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.377776,25.146083]},"properties":{"gaugeId":"BWDB_SW63","issuedTime":"2024-08-21T01:02:43.752743Z","siteName":"Chakrahimpur","river":"Karatoa","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.110489,24.70217]},"properties":{"gaugeId":"BWDB_SW72","issuedTime":"2024-08-21T01:02:43.752141Z","siteName":"Khaliajuri","river":"Dhanu","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.681667,24.628307]},"properties":{"gaugeId":"BWDB_SW175.5","issuedTime":"2024-08-21T01:02:43.747298Z","siteName":"Sherpur-Sylhet","river":"Kushiyara","severity":"ABOVE_NORMAL","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"e8278d924c20403199eb8f112356d454"},{"level":"MEDIUM","serializedPolygonId":"76ad2fc7b9e540a79943200e10224160"},{"level":"LOW","serializedPolygonId":"56b85a8803b94a9387ce8dbab72c26f5"}],"inundationMapsTimeRange":{"start":"2024-08-22T06:00:00Z","end":"2024-08-22T06:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.191013,24.890721]},"properties":{"gaugeId":"BWDB_SW173","issuedTime":"2024-08-21T01:02:43.752905Z","siteName":"Sheola","river":"Kushiyara","severity":"SEVERE","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"9c03e0c5c52b45d1bf6a6170ad74117a"},{"level":"MEDIUM","serializedPolygonId":"3ff908a6701c49b3867d546c89ac2a87"},{"level":"LOW","serializedPolygonId":"287018525e2e4c2fa16360708d5e5dc4"}],"inundationMapsTimeRange":{"start":"2024-08-21T20:00:00Z","end":"2024-08-21T20:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.209356,21.793554]},"properties":{"gaugeId":"BWDB_SW203","issuedTime":"2024-08-21T01:02:43.753321Z","siteName":"Lama","river":"Matamuhuri","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.496305,23.732784]},"properties":{"gaugeId":"BWDB_SW179","issuedTime":"2024-08-21T01:02:43.751669Z","siteName":"Demra","river":"Balu","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.719765,22.807724]},"properties":{"gaugeId":"BWDB_SW117","issuedTime":"2024-08-21T01:02:43.747064Z","siteName":"Narayanhat","river":"Halda","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.937553,24.428089]},"properties":{"gaugeId":"BWDB_SW201","issuedTime":"2024-08-21T01:10:01.557770Z","siteName":"Manu-RB","river":"Manu","severity":"ABOVE_NORMAL","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"c35c936946cd4050971396eee52c57fc"},{"level":"MEDIUM","serializedPolygonId":"6b0a2e86bb704b9580dd81671a099132"},{"level":"LOW","serializedPolygonId":"e4cb9c9127af45e9beaf316fe104c2b2"}],"inundationMapsTimeRange":{"start":"2024-08-20T06:00:00Z","end":"2024-08-20T06:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.260002,23.4704]},"properties":{"gaugeId":"BWDB_SW93.5L","issuedTime":"2024-08-21T01:09:51.850328Z","siteName":"Mawa","river":"Padma","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.216246,22.194878]},"properties":{"gaugeId":"BWDB_SW247","issuedTime":"2024-08-21T01:09:25.330476Z","siteName":"Bandarban","river":"Sangu","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.250119,25.191499]},"properties":{"gaugeId":"BWDB_SW131.5","issuedTime":"2024-08-21T01:02:43.741552Z","siteName":"Lorergorh","river":"Jadukata","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.702683,26.030516]},"properties":{"gaugeId":"BWDB_SW132.2","issuedTime":"2024-08-21T01:02:43.750057Z","siteName":"Phulbari","river":"Ichamati-Jamuna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.03352,24.06764]},"properties":{"gaugeId":"BWDB_SW90","issuedTime":"2024-08-21T01:02:43.752829Z","siteName":"Hardinge-RB","river":"Ganges","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.405531,25.071634]},"properties":{"gaugeId":"BWDB_SW269","issuedTime":"2024-08-21T01:02:44.605627Z","siteName":"Sunamganj","river":"Surma","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.230264,23.911094]},"properties":{"gaugeId":"BWDB_SW14.5","issuedTime":"2024-08-21T01:02:43.741257Z","siteName":"Nayarhat","river":"Bangshi","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.437306,25.787864]},"properties":{"gaugeId":"BWDB_SW294","issuedTime":"2024-08-21T01:02:43.742417Z","siteName":"Kaunia","river":"Teesta","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.958068,23.862486]},"properties":{"gaugeId":"BWDB_SW137A","issuedTime":"2024-08-21T01:02:45.009553Z","siteName":"Taraghat","river":"Kaliganga","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.182899,23.883877]},"properties":{"gaugeId":"BWDB_SW99","issuedTime":"2024-08-21T01:02:43.749961Z","siteName":"Gorai-RB","river":"Gorai","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.209848,23.187806]},"properties":{"gaugeId":"BWDB_SW5","issuedTime":"2024-08-21T01:02:43.752147Z","siteName":"Madaripur","river":"Arialkhan","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.76646,25.920668]},"properties":{"gaugeId":"BWDB_SW45","issuedTime":"2024-08-21T01:02:43.741370Z","siteName":"Noonkhawa","river":"Brahmaputra","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.410342,24.392752]},"properties":{"gaugeId":"BWDB_SW159","issuedTime":"2024-08-21T01:02:43.750462Z","siteName":"Habiganj","river":"Khowai","severity":"ABOVE_NORMAL","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"50e66b72ecb64b4786ed2d2b5f7c05db"},{"level":"MEDIUM","serializedPolygonId":"a6aedce476b747d4905ce6a5a269aec7"},{"level":"LOW","serializedPolygonId":"15cd641a589746b882ada11e7c74dc70"}],"inundationMapsTimeRange":{"start":"2024-08-20T06:00:00Z","end":"2024-08-20T06:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.639487,23.23169]},"properties":{"gaugeId":"BWDB_SW277","issuedTime":"2024-08-21T01:02:43.752489Z","siteName":"Chandpur","river":"Lower - Meghna","severity":"ABOVE_NORMAL","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"661a4c6448fa49c7aec78f52b6c64d87"},{"level":"MEDIUM","serializedPolygonId":"b4c5af47cbb94fb2bd65ff49616d861f"},{"level":"LOW","serializedPolygonId":"bc8d872d9673474294e5cc6f4d68a206"}],"inundationMapsTimeRange":{"start":"2024-08-22T00:00:00Z","end":"2024-08-22T00:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.70111,25.104949]},"properties":{"gaugeId":"BWDB_SW46.9L","issuedTime":"2024-08-21T01:02:43.750700Z","siteName":"Bahadurabad - (Transit)","river":"Jamuna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.025397,23.878853]},"properties":{"gaugeId":"BWDB_SW68.5","issuedTime":"2024-08-21T01:02:43.742212Z","siteName":"Jagir","river":"Old - Dhaleswari","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.068931,24.644253]},"properties":{"gaugeId":"BWDB_SW88A","issuedTime":"2024-08-21T01:07:50.480790Z","siteName":"Pankha","river":"Ganges","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.652813,25.009779]},"properties":{"gaugeId":"BWDB_SW36","issuedTime":"2024-08-21T01:02:43.741671Z","siteName":"Jariajanjail","river":"Kangsha","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.59615,24.098525]},"properties":{"gaugeId":"BWDB_SW157","issuedTime":"2024-08-21T01:02:43.741786Z","siteName":"Ballah","river":"Khowai","severity":"EXTREME","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"705c9b71897a4c40ad740b65b22b7429"},{"level":"MEDIUM","serializedPolygonId":"b1fed2465d3d4de48c4c405e5821138b"},{"level":"LOW","serializedPolygonId":"e919a50ee20b4c00a6f8cd91572eefe3"}],"inundationMapsTimeRange":{"start":"2024-08-20T09:00:00Z","end":"2024-08-20T09:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.932033,24.844091]},"properties":{"gaugeId":"BWDB_SW133","issuedTime":"2024-08-21T01:08:28.891683Z","siteName":"Naogaon","river":"Little - Jamuna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.650532,24.040344]},"properties":{"gaugeId":"BWDB_SW177","issuedTime":"2024-08-21T01:02:43.742057Z","siteName":"Lakhpur","river":"Lakhya","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.4013,23.881792]},"properties":{"gaugeId":"BWDB_SW299","issuedTime":"2024-08-21T01:02:43.742395Z","siteName":"Tongi","river":"Tongi - Khal","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.846427,22.56086]},"properties":{"gaugeId":"BWDB_SW119.1","issuedTime":"2024-08-21T01:02:43.752413Z","siteName":"Panchpukuria","river":"Halda","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.731861,25.767523]},"properties":{"gaugeId":"BWDB_SW142.1","issuedTime":"2024-08-21T01:02:43.753367Z","siteName":"Bhusirbandar","river":"Upper - Atrai","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.11833,25.087706]},"properties":{"gaugeId":"BWDB_SW251","issuedTime":"2024-08-21T01:02:43.747689Z","siteName":"Sarighat","river":"Sarigowain","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.379531,24.785555]},"properties":{"gaugeId":"BWDB_SW269.5","issuedTime":"2024-08-21T01:02:43.750692Z","siteName":"Derai","river":"Surma - Old Course","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}}]}' - headers: - content-length: - - '26138' - content-type: - - application/json - status: - code: 200 - message: OK version: 1 diff --git a/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api_case_insensitive.yaml b/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api_case_insensitive.yaml index 541092747..290d67e1c 100644 --- a/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api_case_insensitive.yaml +++ b/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api_case_insensitive.yaml @@ -19,76 +19,84 @@ interactions: response: body: string: !!binary | - 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 + AA== headers: Alt-Svc: - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 @@ -99,11 +107,11 @@ interactions: Content-Type: - application/json; charset=UTF-8 Date: - - Wed, 21 Aug 2024 01:18:32 GMT + - Thu, 22 Aug 2024 04:44:13 GMT Server: - ESF Server-Timing: - - gfet4t7; dur=382 + - gfet4t7; dur=572 Transfer-Encoding: - chunked Vary: @@ -190,11 +198,11 @@ interactions: Content-Type: - application/json; charset=UTF-8 Date: - - Wed, 21 Aug 2024 01:18:32 GMT + - Thu, 22 Aug 2024 04:44:14 GMT Server: - ESF Server-Timing: - - gfet4t7; dur=124 + - gfet4t7; dur=318 Transfer-Encoding: - chunked Vary: @@ -210,49 +218,4 @@ interactions: status: code: 200 message: OK -- request: - body: '' - headers: - accept: - - '*/*' - accept-encoding: - - gzip, deflate - connection: - - keep-alive - host: - - testserver - user-agent: - - testclient - method: GET - uri: http://testserver/google-floods/gauges/?region_codes=bd - response: - body: - string: '{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[91.389698,24.691644]},"properties":{"gaugeId":"BWDB_SW270","issuedTime":"2024-08-21T01:11:04.800016Z","siteName":"Markuli","river":"Surma-Meghna","severity":"SEVERE","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"f618d9d0b41047e5a73e0352c54737cb"},{"level":"MEDIUM","serializedPolygonId":"5ac17564f96c416aa65622210f7be455"},{"level":"LOW","serializedPolygonId":"3d8b39f6fc0b45df9d6ac2945a8a57b2"}],"inundationMapsTimeRange":{"start":"2024-08-22T09:00:00Z","end":"2024-08-22T09:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.431068,24.737208]},"properties":{"gaugeId":"BWDB_SW228","issuedTime":"2024-08-21T01:09:48.625563Z","siteName":"Mymensingh","river":"Old - Brahmaputra","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.553699,24.368824]},"properties":{"gaugeId":"BWDB_SW88","issuedTime":"2024-08-21T01:02:43.741872Z","siteName":"Rajshahi","river":"Ganges","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.438231,23.221259]},"properties":{"gaugeId":"BWDB_SW212","issuedTime":"2024-08-21T01:02:43.741974Z","siteName":"Parshuram","river":"Muhuri","severity":"SEVERE","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"3047087919894a6b8fdce086515cc171"},{"level":"MEDIUM","serializedPolygonId":"84c6899783e149eeabcdc05c6ec149e0"},{"level":"LOW","serializedPolygonId":"6544a995d4fd4ff5b5de00c8f261dd1b"}],"inundationMapsTimeRange":{"start":"2024-08-20T09:00:00Z","end":"2024-08-20T09:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.485642,24.872495]},"properties":{"gaugeId":"BWDB_SW172","issuedTime":"2024-08-21T01:02:43.752334Z","siteName":"Amalshid","river":"Kushiyara","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.119442,23.956966]},"properties":{"gaugeId":"BWDB_SW3A","issuedTime":"2024-08-21T01:02:43.753813Z","siteName":"B. - Baria","river":"Titas","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.774876,24.496424]},"properties":{"gaugeId":"BWDB_SW202","issuedTime":"2024-08-21T01:02:43.747282Z","siteName":"Moulvibazar","river":"Manu","severity":"ABOVE_NORMAL","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"0bca00b745534e5d9f97637c845445af"},{"level":"MEDIUM","serializedPolygonId":"d6d0fa09a1fb472ebc33248431455131"},{"level":"LOW","serializedPolygonId":"4c3976049e454c608c082f9ebfbd9b2a"}],"inundationMapsTimeRange":{"start":"2024-08-20T06:00:00Z","end":"2024-08-20T06:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.063472,22.15791]},"properties":{"gaugeId":"BWDB_SW248","issuedTime":"2024-08-21T01:02:44.639650Z","siteName":"Dohazari","river":"Sangu","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.703954,22.968128]},"properties":{"gaugeId":"BWDB_SW84","issuedTime":"2024-08-21T01:02:43.752323Z","siteName":"Ramgarh","river":"Feni","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.580654,24.891637]},"properties":{"gaugeId":"BWDB_SW15J","issuedTime":"2024-08-21T01:02:43.751949Z","siteName":"Sariakandi - (Mathurapara)","river":"Jamuna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.265191,25.004479]},"properties":{"gaugeId":"BWDB_SW266","issuedTime":"2024-08-21T01:11:03.131730Z","siteName":"Kanaighat","river":"Surma","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.618762,25.689237]},"properties":{"gaugeId":"BWDB_SW236","issuedTime":"2024-08-21T01:02:43.752832Z","siteName":"Dinajpur","river":"Punarbhaba","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.460897,26.03796]},"properties":{"gaugeId":"BWDB_SW285","issuedTime":"2024-08-21T01:10:48.136382Z","siteName":"Thakurgaon","river":"Tangon","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.744249,24.916416]},"properties":{"gaugeId":"BWDB_SW145","issuedTime":"2024-08-21T01:02:43.750317Z","siteName":"Mohadebpur","river":"Atrai","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.096763,23.101868]},"properties":{"gaugeId":"BWDB_SW162","issuedTime":"2024-08-21T01:02:44.417982Z","siteName":"Jhikargacha","river":"Kobadak","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.19839,23.471078]},"properties":{"gaugeId":"BWDB_SW110","issuedTime":"2024-08-21T01:02:43.751995Z","siteName":"Cumilla","river":"Gumti","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.778872,23.768642]},"properties":{"gaugeId":"BWDB_SW91.9R","issuedTime":"2024-08-21T01:02:43.753415Z","siteName":"Goalondo - (Transit)","river":"Padma","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.073729,26.125276]},"properties":{"gaugeId":"BWDB_SW291.5R","issuedTime":"2024-08-21T01:02:43.742990Z","siteName":"Dalia","river":"Teesta","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.336562,23.784904]},"properties":{"gaugeId":"BWDB_SW302","issuedTime":"2024-08-21T01:02:43.742314Z","siteName":"Mirpur","river":"Turag","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.516256,23.539828]},"properties":{"gaugeId":"BWDB_SW101","issuedTime":"2024-08-21T01:02:43.747180Z","siteName":"Kamarkhali - (Transit)","river":"Gorai","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.48001,23.56269]},"properties":{"gaugeId":"BWDB_SW71A","issuedTime":"2024-08-21T01:02:43.751997Z","siteName":"Rekabi-Bazar","river":"Dhaleswari","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.638969,23.58457]},"properties":{"gaugeId":"BWDB_SW275.5","issuedTime":"2024-08-21T01:02:43.752988Z","siteName":"Meghna - Bridge","river":"Meghna","severity":"ABOVE_NORMAL","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"c131d800f16b4e1091db58bc2c1843ae"},{"level":"MEDIUM","serializedPolygonId":"28fcb2013d574375bcf045dbdd93e8cd"},{"level":"LOW","serializedPolygonId":"f3eae83263644992857b356dd7f06c4e"}],"inundationMapsTimeRange":{"start":"2024-08-20T09:00:00Z","end":"2024-08-20T09:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.26666666666668,23.473055555555554]},"properties":{"gaugeId":"CWC_012-MDSIL","issuedTime":"2024-08-21T01:03:39.394447Z","siteName":"Sonamura - (II)","river":null,"severity":"ABOVE_NORMAL","source":"CWC","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.079743,21.773552]},"properties":{"gaugeId":"BWDB_SW204","issuedTime":"2024-08-21T01:12:06.279121Z","siteName":"Chiringa","river":"Matamuhuri","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.439032,23.320123]},"properties":{"gaugeId":"BWDB_SW95","issuedTime":"2024-08-21T01:02:44.441009Z","siteName":"Sureshswar","river":"Padma","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.661579,25.123256]},"properties":{"gaugeId":"BWDB_SW263","issuedTime":"2024-08-21T01:02:43.752847Z","siteName":"Durgapur","river":"Someswari","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.249526,24.599517]},"properties":{"gaugeId":"BWDB_SW211.5","issuedTime":"2024-08-21T01:09:59.760859Z","siteName":"Chapai-Nawabganj","river":"Mohananda","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.991206,24.045541]},"properties":{"gaugeId":"BWDB_SW273","issuedTime":"2024-08-21T01:02:43.750627Z","siteName":"Bhairab - Bazar","river":"Upper Meghna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.842925,23.645365]},"properties":{"gaugeId":"BWDB_SW207","issuedTime":"2024-08-21T01:02:43.751180Z","siteName":"Chuadanga","river":"Mathabhanga","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.138756,24.497782]},"properties":{"gaugeId":"BWDB_SW147.5","issuedTime":"2024-08-21T01:02:43.750599Z","siteName":"Singra","river":"Atrai - Gur","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.391511,24.831299]},"properties":{"gaugeId":"BWDB_SW65","issuedTime":"2024-08-21T01:02:43.751897Z","siteName":"Bogura","river":"Karatoa","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.689858,24.635869]},"properties":{"gaugeId":"BWDB_SW49A","issuedTime":"2024-08-21T01:02:43.749730Z","siteName":"Kazipur","river":"Jamuna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.72653,23.918646]},"properties":{"gaugeId":"BWDB_SW274","issuedTime":"2024-08-21T01:08:08.803288Z","siteName":"Narsingdi","river":"Meghna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.206392,23.511165]},"properties":{"gaugeId":"BWDB_SW93.4L","issuedTime":"2024-08-21T01:02:43.751012Z","siteName":"Bhagyakul","river":"Padma","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.686153,25.544273]},"properties":{"gaugeId":"BWDB_SW45.5","issuedTime":"2024-08-21T01:12:38.287522Z","siteName":"Chilmari","river":"Brahmaputra","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.772772,23.881297]},"properties":{"gaugeId":"BWDB_SW50.6","issuedTime":"2024-08-21T01:02:43.752637Z","siteName":"Aricha","river":"Jamuna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.667595,25.82041]},"properties":{"gaugeId":"BWDB_SW77","issuedTime":"2024-08-21T01:02:43.747425Z","siteName":"Kurigram","river":"Dharla","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.062548,25.675475]},"properties":{"gaugeId":"BWDB_SW62","issuedTime":"2024-08-21T01:02:44.614160Z","siteName":"Badarganj","river":"Jamuneswari","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.889765,25.073472]},"properties":{"gaugeId":"BWDB_SW263.1","issuedTime":"2024-08-21T01:02:43.741605Z","siteName":"Kalmakanda","river":"Someswari","severity":"UNKNOWN","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.718387,24.470952]},"properties":{"gaugeId":"BWDB_SW49","issuedTime":"2024-08-21T01:02:43.741341Z","siteName":"Serajganj","river":"Jamuna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.967658,24.923502]},"properties":{"gaugeId":"BWDB_SW225","issuedTime":"2024-08-21T01:02:44.513328Z","siteName":"Jamalpur","river":"Old - Brahmaputra","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.857085,23.787087]},"properties":{"gaugeId":"BWDB_SW206","issuedTime":"2024-08-21T01:02:43.741928Z","siteName":"Hatboalia","river":"Mathabhanga","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.544405,26.330021]},"properties":{"gaugeId":"BWDB_SW140","issuedTime":"2024-08-21T01:02:43.751230Z","siteName":"Panchagarh","river":"Upper - Karatoa","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.849452,24.888834]},"properties":{"gaugeId":"BWDB_SW267","issuedTime":"2024-08-21T01:02:43.742505Z","siteName":"Sylhet","river":"Surma","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.419454,23.696849]},"properties":{"gaugeId":"BWDB_SW42","issuedTime":"2024-08-21T01:02:43.750274Z","siteName":"Dhaka - (MilBarack)","river":"Buriganga","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.84582,24.352029]},"properties":{"gaugeId":"BWDB_SW67","issuedTime":"2024-08-21T01:02:43.746795Z","siteName":"Kamalganj","river":"Dhalai","severity":"SEVERE","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"db6f4ad7e66841bca99a730de855e901"},{"level":"MEDIUM","serializedPolygonId":"0f14f753676647f6bbfccf2962f91723"},{"level":"LOW","serializedPolygonId":"3a88c77589164db4bfc280a5e94360f7"}],"inundationMapsTimeRange":{"start":"2024-08-20T09:00:00Z","end":"2024-08-20T09:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.318746,24.820982]},"properties":{"gaugeId":"BWDB_SW238","issuedTime":"2024-08-21T01:02:43.742372Z","siteName":"Rohanpur","river":"Punarvaba","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.377776,25.146083]},"properties":{"gaugeId":"BWDB_SW63","issuedTime":"2024-08-21T01:02:43.752743Z","siteName":"Chakrahimpur","river":"Karatoa","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.110489,24.70217]},"properties":{"gaugeId":"BWDB_SW72","issuedTime":"2024-08-21T01:02:43.752141Z","siteName":"Khaliajuri","river":"Dhanu","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.681667,24.628307]},"properties":{"gaugeId":"BWDB_SW175.5","issuedTime":"2024-08-21T01:02:43.747298Z","siteName":"Sherpur-Sylhet","river":"Kushiyara","severity":"ABOVE_NORMAL","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"e8278d924c20403199eb8f112356d454"},{"level":"MEDIUM","serializedPolygonId":"76ad2fc7b9e540a79943200e10224160"},{"level":"LOW","serializedPolygonId":"56b85a8803b94a9387ce8dbab72c26f5"}],"inundationMapsTimeRange":{"start":"2024-08-22T06:00:00Z","end":"2024-08-22T06:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.191013,24.890721]},"properties":{"gaugeId":"BWDB_SW173","issuedTime":"2024-08-21T01:02:43.752905Z","siteName":"Sheola","river":"Kushiyara","severity":"SEVERE","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"9c03e0c5c52b45d1bf6a6170ad74117a"},{"level":"MEDIUM","serializedPolygonId":"3ff908a6701c49b3867d546c89ac2a87"},{"level":"LOW","serializedPolygonId":"287018525e2e4c2fa16360708d5e5dc4"}],"inundationMapsTimeRange":{"start":"2024-08-21T20:00:00Z","end":"2024-08-21T20:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.209356,21.793554]},"properties":{"gaugeId":"BWDB_SW203","issuedTime":"2024-08-21T01:02:43.753321Z","siteName":"Lama","river":"Matamuhuri","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.496305,23.732784]},"properties":{"gaugeId":"BWDB_SW179","issuedTime":"2024-08-21T01:02:43.751669Z","siteName":"Demra","river":"Balu","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.719765,22.807724]},"properties":{"gaugeId":"BWDB_SW117","issuedTime":"2024-08-21T01:02:43.747064Z","siteName":"Narayanhat","river":"Halda","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.937553,24.428089]},"properties":{"gaugeId":"BWDB_SW201","issuedTime":"2024-08-21T01:10:01.557770Z","siteName":"Manu-RB","river":"Manu","severity":"ABOVE_NORMAL","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"c35c936946cd4050971396eee52c57fc"},{"level":"MEDIUM","serializedPolygonId":"6b0a2e86bb704b9580dd81671a099132"},{"level":"LOW","serializedPolygonId":"e4cb9c9127af45e9beaf316fe104c2b2"}],"inundationMapsTimeRange":{"start":"2024-08-20T06:00:00Z","end":"2024-08-20T06:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.260002,23.4704]},"properties":{"gaugeId":"BWDB_SW93.5L","issuedTime":"2024-08-21T01:09:51.850328Z","siteName":"Mawa","river":"Padma","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.216246,22.194878]},"properties":{"gaugeId":"BWDB_SW247","issuedTime":"2024-08-21T01:09:25.330476Z","siteName":"Bandarban","river":"Sangu","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.250119,25.191499]},"properties":{"gaugeId":"BWDB_SW131.5","issuedTime":"2024-08-21T01:02:43.741552Z","siteName":"Lorergorh","river":"Jadukata","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.702683,26.030516]},"properties":{"gaugeId":"BWDB_SW132.2","issuedTime":"2024-08-21T01:02:43.750057Z","siteName":"Phulbari","river":"Ichamati-Jamuna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.03352,24.06764]},"properties":{"gaugeId":"BWDB_SW90","issuedTime":"2024-08-21T01:02:43.752829Z","siteName":"Hardinge-RB","river":"Ganges","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.405531,25.071634]},"properties":{"gaugeId":"BWDB_SW269","issuedTime":"2024-08-21T01:02:44.605627Z","siteName":"Sunamganj","river":"Surma","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.230264,23.911094]},"properties":{"gaugeId":"BWDB_SW14.5","issuedTime":"2024-08-21T01:02:43.741257Z","siteName":"Nayarhat","river":"Bangshi","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.437306,25.787864]},"properties":{"gaugeId":"BWDB_SW294","issuedTime":"2024-08-21T01:02:43.742417Z","siteName":"Kaunia","river":"Teesta","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.958068,23.862486]},"properties":{"gaugeId":"BWDB_SW137A","issuedTime":"2024-08-21T01:02:45.009553Z","siteName":"Taraghat","river":"Kaliganga","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.182899,23.883877]},"properties":{"gaugeId":"BWDB_SW99","issuedTime":"2024-08-21T01:02:43.749961Z","siteName":"Gorai-RB","river":"Gorai","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.209848,23.187806]},"properties":{"gaugeId":"BWDB_SW5","issuedTime":"2024-08-21T01:02:43.752147Z","siteName":"Madaripur","river":"Arialkhan","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.76646,25.920668]},"properties":{"gaugeId":"BWDB_SW45","issuedTime":"2024-08-21T01:02:43.741370Z","siteName":"Noonkhawa","river":"Brahmaputra","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.410342,24.392752]},"properties":{"gaugeId":"BWDB_SW159","issuedTime":"2024-08-21T01:02:43.750462Z","siteName":"Habiganj","river":"Khowai","severity":"ABOVE_NORMAL","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"50e66b72ecb64b4786ed2d2b5f7c05db"},{"level":"MEDIUM","serializedPolygonId":"a6aedce476b747d4905ce6a5a269aec7"},{"level":"LOW","serializedPolygonId":"15cd641a589746b882ada11e7c74dc70"}],"inundationMapsTimeRange":{"start":"2024-08-20T06:00:00Z","end":"2024-08-20T06:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.639487,23.23169]},"properties":{"gaugeId":"BWDB_SW277","issuedTime":"2024-08-21T01:02:43.752489Z","siteName":"Chandpur","river":"Lower - Meghna","severity":"ABOVE_NORMAL","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"661a4c6448fa49c7aec78f52b6c64d87"},{"level":"MEDIUM","serializedPolygonId":"b4c5af47cbb94fb2bd65ff49616d861f"},{"level":"LOW","serializedPolygonId":"bc8d872d9673474294e5cc6f4d68a206"}],"inundationMapsTimeRange":{"start":"2024-08-22T00:00:00Z","end":"2024-08-22T00:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[89.70111,25.104949]},"properties":{"gaugeId":"BWDB_SW46.9L","issuedTime":"2024-08-21T01:02:43.750700Z","siteName":"Bahadurabad - (Transit)","river":"Jamuna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.025397,23.878853]},"properties":{"gaugeId":"BWDB_SW68.5","issuedTime":"2024-08-21T01:02:43.742212Z","siteName":"Jagir","river":"Old - Dhaleswari","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.068931,24.644253]},"properties":{"gaugeId":"BWDB_SW88A","issuedTime":"2024-08-21T01:07:50.480790Z","siteName":"Pankha","river":"Ganges","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.652813,25.009779]},"properties":{"gaugeId":"BWDB_SW36","issuedTime":"2024-08-21T01:02:43.741671Z","siteName":"Jariajanjail","river":"Kangsha","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.59615,24.098525]},"properties":{"gaugeId":"BWDB_SW157","issuedTime":"2024-08-21T01:02:43.741786Z","siteName":"Ballah","river":"Khowai","severity":"EXTREME","source":"BWDB","qualityVerified":true,"inundationMapSet":{"inundationMaps":[{"level":"HIGH","serializedPolygonId":"705c9b71897a4c40ad740b65b22b7429"},{"level":"MEDIUM","serializedPolygonId":"b1fed2465d3d4de48c4c405e5821138b"},{"level":"LOW","serializedPolygonId":"e919a50ee20b4c00a6f8cd91572eefe3"}],"inundationMapsTimeRange":{"start":"2024-08-20T09:00:00Z","end":"2024-08-20T09:00:00Z"},"inundationMapType":"PROBABILITY"}}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.932033,24.844091]},"properties":{"gaugeId":"BWDB_SW133","issuedTime":"2024-08-21T01:08:28.891683Z","siteName":"Naogaon","river":"Little - Jamuna","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.650532,24.040344]},"properties":{"gaugeId":"BWDB_SW177","issuedTime":"2024-08-21T01:02:43.742057Z","siteName":"Lakhpur","river":"Lakhya","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[90.4013,23.881792]},"properties":{"gaugeId":"BWDB_SW299","issuedTime":"2024-08-21T01:02:43.742395Z","siteName":"Tongi","river":"Tongi - Khal","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.846427,22.56086]},"properties":{"gaugeId":"BWDB_SW119.1","issuedTime":"2024-08-21T01:02:43.752413Z","siteName":"Panchpukuria","river":"Halda","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[88.731861,25.767523]},"properties":{"gaugeId":"BWDB_SW142.1","issuedTime":"2024-08-21T01:02:43.753367Z","siteName":"Bhusirbandar","river":"Upper - Atrai","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[92.11833,25.087706]},"properties":{"gaugeId":"BWDB_SW251","issuedTime":"2024-08-21T01:02:43.747689Z","siteName":"Sarighat","river":"Sarigowain","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}},{"type":"Feature","geometry":{"type":"Point","coordinates":[91.379531,24.785555]},"properties":{"gaugeId":"BWDB_SW269.5","issuedTime":"2024-08-21T01:02:43.750692Z","siteName":"Derai","river":"Surma - Old Course","severity":"NO_FLOODING","source":"BWDB","qualityVerified":true}}]}' - headers: - content-length: - - '26138' - content-type: - - application/json - status: - code: 200 - message: OK version: 1 diff --git a/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api_requires_valid_region_code.yaml b/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api_requires_valid_region_code.yaml deleted file mode 100644 index 13abcf9b7..000000000 --- a/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api_requires_valid_region_code.yaml +++ /dev/null @@ -1,28 +0,0 @@ -interactions: -- request: - body: '' - headers: - accept: - - '*/*' - accept-encoding: - - gzip, deflate - connection: - - keep-alive - host: - - testserver - user-agent: - - testclient - method: GET - uri: http://testserver/google-floods/gauges/?region_codes=usa - response: - body: - string: '{"detail":"Region code ''usa'' must be exactly two characters (iso2)."}' - headers: - content-length: - - '69' - content-type: - - application/json - status: - code: 400 - message: Bad Request -version: 1 diff --git a/api/app/tests/test_google_floods_api.py b/api/app/tests/test_google_floods_api.py index 764dc13a6..ddca5e649 100644 --- a/api/app/tests/test_google_floods_api.py +++ b/api/app/tests/test_google_floods_api.py @@ -30,6 +30,7 @@ def test_get_google_floods_gauges(): match_on=["uri", "method"], filter_headers=["Authorization"], filter_query_parameters=["key"], + ignore_hosts=["testserver"], ) def test_get_google_floods_gauges_api(): """ @@ -47,6 +48,7 @@ def test_get_google_floods_gauges_api(): match_on=["uri", "method"], filter_headers=["Authorization"], filter_query_parameters=["key"], + ignore_hosts=["testserver"], ) def test_get_google_floods_gauges_api_case_insensitive(): """ @@ -64,6 +66,7 @@ def test_get_google_floods_gauges_api_case_insensitive(): match_on=["uri", "method"], filter_headers=["Authorization"], filter_query_parameters=["key"], + ignore_hosts=["testserver"], ) def test_get_google_floods_gauges_api_requires_valid_region_code(): """ From 0adb49dd8cfb2af41d74454fd63dd9a63238fa56 Mon Sep 17 00:00:00 2001 From: ericboucher Date: Thu, 22 Aug 2024 19:04:30 +0200 Subject: [PATCH 16/19] Update API URL --- frontend/src/config/mozambique/layers.json | 21 ++++++--------------- frontend/src/config/rbd/layers.json | 4 ++-- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/frontend/src/config/mozambique/layers.json b/frontend/src/config/mozambique/layers.json index 5d595957e..cdd7b7603 100644 --- a/frontend/src/config/mozambique/layers.json +++ b/frontend/src/config/mozambique/layers.json @@ -36,7 +36,7 @@ "line-opacity": 0.8 } } - }, + }, "admin_boundaries": { "type": "boundary", "path": "data/mozambique/moz_bnd_adm3_WFP.json", @@ -2415,7 +2415,7 @@ "type": "admin_level_data", "path": "data/mozambique/ipc/ipc-2022.json", "data_field": "ph3ps_p", - "boundary": "admin2_boundaries", + "boundary": "admin2_boundaries", "admin_level": 2, "admin_code": "adm2_source_id", "opacity": 0.9, @@ -2870,28 +2870,19 @@ { "id": "spi_1m", "importance": 0.5, - "key": [ - "CHIRPS", - "R1S_DEKAD" - ], + "key": ["CHIRPS", "R1S_DEKAD"], "aggregation": "last_dekad" }, { "id": "lst_anomaly", "importance": 0.25, - "key": [ - "MODIS", - "MYD11C2_TDD_DEKAD" - ], + "key": ["MODIS", "MYD11C2_TDD_DEKAD"], "aggregation": "last_dekad" }, { "id": "ndvi_dekad", "importance": 0.25, - "key": [ - "MODIS", - "NDVI_smoothed_5KM" - ], + "key": ["MODIS", "NDVI_smoothed_5KM"], "aggregation": "average", "invert": "True" } @@ -2959,7 +2950,7 @@ "title": "Current Flood Status (Google AI)", "type": "point_data", "hex_display": false, - "data": "http://0.0.0.0:80/google-floods/gauges/?region_codes=MZ", + "data": "https://prism-api.ovio.org/google-floods/gauges/?region_codes=MZ", "data_field": "severity", "data_field_type": "text", "opacity": 0.9, diff --git a/frontend/src/config/rbd/layers.json b/frontend/src/config/rbd/layers.json index 0fdf61575..45445e605 100644 --- a/frontend/src/config/rbd/layers.json +++ b/frontend/src/config/rbd/layers.json @@ -6405,7 +6405,7 @@ "color": "#e51a19" } ], - "legend_text": "ACLED Conflict analysis 2021 produced by IFPRI. For more details, see [Political violence in the G5 Sahel Countries](https://hdl.handle.net/10568/139670)" + "legend_text": "ACLED Conflict analysis 2021 produced by IFPRI. For more details, see [Political violence in the G5 Sahel Countries](https://hdl.handle.net/10568/139670)" }, "fs_hotspot_2024": { "title": "Food security hotspot analysis", @@ -6536,7 +6536,7 @@ "title": "Current Flood Status (Google AI)", "type": "point_data", "hex_display": false, - "data": "http://0.0.0.0:80/google-floods/gauges/?region_codes=BF®ion_codes=CM®ion_codes=TD®ion_codes=GH®ion_codes=ML®ion_codes=MR®ion_codes=NE®ion_codes=SL®ion_codes=CI®ion_codes=GN®ion_codes=SN®ion_codes=GM®ion_codes=GW®ion_codes=LR®ion_codes=TG®ion_codes=BJ®ion_codes=NG®ion_codes=CF", + "data": "https://prism-api.ovio.org/google-floods/gauges/?region_codes=BF®ion_codes=CM®ion_codes=TD®ion_codes=GH®ion_codes=ML®ion_codes=MR®ion_codes=NE®ion_codes=SL®ion_codes=CI®ion_codes=GN®ion_codes=SN®ion_codes=GM®ion_codes=GW®ion_codes=LR®ion_codes=TG®ion_codes=BJ®ion_codes=NG®ion_codes=CF", "data_field": "severity", "data_field_type": "text", "opacity": 0.9, From 7f401bb6700e3a9595dbee4585af950ec73af944 Mon Sep 17 00:00:00 2001 From: Will Gislason <8203830+gislawill@users.noreply.github.com> Date: Mon, 7 Oct 2024 10:56:09 -0500 Subject: [PATCH 17/19] Adding support for Cambodia --- frontend/src/config/cambodia/layers.json | 69 ++++++++++++++++++++++++ frontend/src/config/cambodia/prism.json | 3 ++ 2 files changed, 72 insertions(+) diff --git a/frontend/src/config/cambodia/layers.json b/frontend/src/config/cambodia/layers.json index 77481b8f7..fec7acac2 100644 --- a/frontend/src/config/cambodia/layers.json +++ b/frontend/src/config/cambodia/layers.json @@ -1988,5 +1988,74 @@ } ], "legend_text": "Index meausring a household’s social and economic capacities and resilience to cope with, adapt to and recover from the floods and droughts. Aggregated at Commune level" + }, + "google_flood_status_at_gauges": { + "title": "Current Flood Status (Google AI)", + "type": "point_data", + "hex_display": false, + "data": "https://prism-api.ovio.org/google-floods/gauges/?region_codes=KH", + "data_field": "severity", + "data_field_type": "text", + "opacity": 0.9, + "legend_text": "Current flood status at verified gauges. Visit [Google Research](https://sites.research.google/floodforecasting/) about Google's AI Forecasting models.", + "legend": [ + { "label": "Extreme", "value": "EXTREME", "color": "#a70606" }, + { "label": "Danger", "value": "SEVERE", "color": "#ea250a" }, + { "label": "Warning", "value": "ABOVE_NORMAL", "color": "#fba705" }, + { "label": "Normal", "value": "NO_FLOODING", "color": "#089180" }, + { "label": "Unknown", "value": "UNKNOWN", "color": "#858585" } + ], + "feature_info_title": { + "siteName": { + "type": "text", + "template": "Site: {{siteName}}", + "visibility": "if-defined" + }, + "riverName": { + "type": "text", + "template": "River: {{riverName}}", + "visibility": "if-defined" + }, + "gaugeId": { + "type": "text", + "template": "Gauge ID: {{gaugeId}}", + "visibility": "if-defined" + } + }, + "feature_info_props": { + "siteName": { + "type": "text", + "dataTitle": "Site", + "visibility": "if-defined" + }, + "river": { + "type": "text", + "dataTitle": "River", + "visibility": "if-defined" + }, + "severity": { + "type": "labelMapping", + "dataTitle": "Flood Status", + "labelMap": { + "EXTREME": "Extreme", + "SEVERE": "Danger", + "ABOVE_NORMAL": "Warning", + "NO_FLOODING": "Normal", + "UNKNOWN": "Unknown" + } + }, + "gaugeId": { + "type": "text", + "dataTitle": "Gauge ID" + }, + "source": { + "type": "text", + "dataTitle": "Data source" + }, + "issuedTime": { + "type": "date", + "dataTitle": "Status issued" + } + } } } diff --git a/frontend/src/config/cambodia/prism.json b/frontend/src/config/cambodia/prism.json index 5fa399a30..e3329d20e 100644 --- a/frontend/src/config/cambodia/prism.json +++ b/frontend/src/config/cambodia/prism.json @@ -209,6 +209,9 @@ }, "field_reports": { "field_reports": ["flood_report", "drought_report", "kh_incident_report"] + }, + "flooding": { + "flood_status": ["google_flood_status_at_gauges"] } } } From 2a890cfff8c02a2224e92b30e2be09eefb9e6f64 Mon Sep 17 00:00:00 2001 From: Will Gislason <8203830+gislawill@users.noreply.github.com> Date: Wed, 9 Oct 2024 14:31:05 -0500 Subject: [PATCH 18/19] Adding date support --- api/app/googleflood.py | 45 ++++++++++++++++++++++ api/app/main.py | 24 +++++++++++- frontend/src/config/cambodia/layers.json | 1 + frontend/src/config/mozambique/layers.json | 1 + frontend/src/config/rbd/layers.json | 1 + 5 files changed, 71 insertions(+), 1 deletion(-) diff --git a/api/app/googleflood.py b/api/app/googleflood.py index 40d4b7a7e..7cdcbc693 100644 --- a/api/app/googleflood.py +++ b/api/app/googleflood.py @@ -2,6 +2,7 @@ import logging from concurrent.futures import ThreadPoolExecutor, as_completed +from datetime import datetime, timezone from os import getenv from urllib.parse import urlencode @@ -57,6 +58,50 @@ def fetch_flood_status(region_code): return {} +def get_google_flood_dates(region_codes: list[str]): + """ + When more complex date support is needed, this can be used to fetch dates from the Google Floods API. + + For now, we just return today's date at the region + """ + flood_statuses = [] + + # Retry 3 times due to intermittent API errors + with ThreadPoolExecutor() as executor: + future_to_region = { + executor.submit(fetch_flood_status, code): code for code in region_codes + } + for future in as_completed(future_to_region): + status_response = future.result() + if "error" in status_response: + logger.error("Error in response: %s", status_response["error"]) + raise HTTPException( + status_code=500, + detail="Error fetching flood status data from Google API", + ) + flood_statuses.extend(status_response.get("floodStatuses", [])) + + parsed_issued_times = [ + datetime.strptime(status["issuedTime"], "%Y-%m-%dT%H:%M:%S.%fZ") + for status in flood_statuses + if "issuedTime" in status + ] + parsed_issued_times.sort(reverse=True) # Sort in descending order + + # Format only the most recent date + most_recent_date = ( + { + "date": parsed_issued_times[0] + .replace(tzinfo=timezone.utc) + .strftime("%Y-%m-%d") + } + if parsed_issued_times + else {} + ) + + return [most_recent_date] if most_recent_date else [] + + def get_google_floods_gauges( region_codes: list[str], as_geojson: bool = True, diff --git a/api/app/main.py b/api/app/main.py index 42a903dd7..7c27ee32d 100644 --- a/api/app/main.py +++ b/api/app/main.py @@ -14,7 +14,7 @@ from app.database.alert_model import AlchemyEncoder, AlertModel from app.database.database import AlertsDataBase from app.database.user_info_model import UserInfoModel -from app.googleflood import get_google_floods_gauges +from app.googleflood import get_google_flood_dates, get_google_floods_gauges from app.hdc import get_hdc_stats from app.kobo import get_form_dates, get_form_responses, parse_datetime_params from app.models import AcledRequest, RasterGeotiffModel @@ -433,3 +433,25 @@ def get_google_floods_gauges_api(region_codes: list[str] = Query(...)): iso2_codes = [region_code.upper() for region_code in region_codes] return get_google_floods_gauges(iso2_codes) + + +@app.get("/google-floods/dates/") +def get_google_floods_dates_api(region_codes: list[str] = Query(...)): + """ + Get the Google Floods dates for a list of regions. + """ + if not region_codes: + raise HTTPException( + status_code=400, + detail="At least one region code must be provided.", + ) + + for region_code in region_codes: + if len(region_code) != 2: + raise HTTPException( + status_code=400, + detail=f"Region code '{region_code}' must be exactly two characters (iso2).", + ) + + iso2_codes = [region_code.upper() for region_code in region_codes] + return get_google_flood_dates(iso2_codes) diff --git a/frontend/src/config/cambodia/layers.json b/frontend/src/config/cambodia/layers.json index fec7acac2..a1fb36d55 100644 --- a/frontend/src/config/cambodia/layers.json +++ b/frontend/src/config/cambodia/layers.json @@ -1996,6 +1996,7 @@ "data": "https://prism-api.ovio.org/google-floods/gauges/?region_codes=KH", "data_field": "severity", "data_field_type": "text", + "date_url": "https://prism-api.ovio.org/google-floods/dates/?region_codes=KH", "opacity": 0.9, "legend_text": "Current flood status at verified gauges. Visit [Google Research](https://sites.research.google/floodforecasting/) about Google's AI Forecasting models.", "legend": [ diff --git a/frontend/src/config/mozambique/layers.json b/frontend/src/config/mozambique/layers.json index cdd7b7603..cc2e9926b 100644 --- a/frontend/src/config/mozambique/layers.json +++ b/frontend/src/config/mozambique/layers.json @@ -2953,6 +2953,7 @@ "data": "https://prism-api.ovio.org/google-floods/gauges/?region_codes=MZ", "data_field": "severity", "data_field_type": "text", + "date_url": "https://prism-api.ovio.org/google-floods/dates/?region_codes=MZ", "opacity": 0.9, "legend_text": "Current flood status at verified gauges. Visit [Google Research](https://sites.research.google/floodforecasting/) about Google's AI Forecasting models.", "legend": [ diff --git a/frontend/src/config/rbd/layers.json b/frontend/src/config/rbd/layers.json index 45445e605..10bc6753d 100644 --- a/frontend/src/config/rbd/layers.json +++ b/frontend/src/config/rbd/layers.json @@ -6539,6 +6539,7 @@ "data": "https://prism-api.ovio.org/google-floods/gauges/?region_codes=BF®ion_codes=CM®ion_codes=TD®ion_codes=GH®ion_codes=ML®ion_codes=MR®ion_codes=NE®ion_codes=SL®ion_codes=CI®ion_codes=GN®ion_codes=SN®ion_codes=GM®ion_codes=GW®ion_codes=LR®ion_codes=TG®ion_codes=BJ®ion_codes=NG®ion_codes=CF", "data_field": "severity", "data_field_type": "text", + "date_url": "https://prism-api.ovio.org/google-floods/dates/?region_codes=BF®ion_codes=CM®ion_codes=TD®ion_codes=GH®ion_codes=ML®ion_codes=MR®ion_codes=NE®ion_codes=SL®ion_codes=CI®ion_codes=GN®ion_codes=SN®ion_codes=GM®ion_codes=GW®ion_codes=LR®ion_codes=TG®ion_codes=BJ®ion_codes=NG®ion_codes=CF", "opacity": 0.9, "legend_text": "Current flood status at verified gauges. Visit [Google Research](https://sites.research.google/floodforecasting/) about Google's AI Forecasting models.", "legend": [ From 6d33543e4384cfdddb53017c9f29fe6757403173 Mon Sep 17 00:00:00 2001 From: Will Gislason <8203830+gislawill@users.noreply.github.com> Date: Thu, 31 Oct 2024 12:29:12 -0700 Subject: [PATCH 19/19] Google Floods Part 2: Adding tooltip graph; COUNTRY=cambodia (#1330) * Adding graph for google flood data * Merge conflict resolution and units * Updating tests * formatting * Using superscript * Supporting rbd * Add support for Cambodia * Updating url for data * api lint * Fixing date logic on graph look up * Updates to chart to denote past vs future * Adding translation to 'future' label * Fix chart tests using mock * Requested changes: descriptive labels --- api/app/googleflood.py | 103 ++++++-- api/app/main.py | 21 +- ...test_get_google_floods_gauge_forecast.yaml | 67 ++++++ ...floods_gauge_forecast_multiple_gauges.yaml | 84 +++++++ .../test_get_google_floods_gauges.yaml | 222 +++++++++++------- .../test_get_google_floods_gauges_api.yaml | 222 +++++++++++------- ...le_floods_gauges_api_case_insensitive.yaml | 222 +++++++++++------- api/app/tests/test_google_floods_api.py | 46 ++++ frontend/package.json | 1 + .../src/components/Common/Chart/index.tsx | 220 ++++++++++++++--- .../MapView/Layers/PointDataLayer/index.tsx | 19 +- .../PointDataChart/PopupPointDataChart.tsx | 23 +- .../PointDataChart/usePointDataChart.tsx | 57 +++-- frontend/src/components/MapView/utils.ts | 32 +-- frontend/src/config/cambodia/layers.json | 6 +- frontend/src/config/cambodia/translation.json | 2 +- frontend/src/config/mozambique/layers.json | 8 +- frontend/src/config/rbd/layers.json | 8 +- .../config/shared/translation/english.json | 2 +- .../src/config/shared/translation/khmer.json | 2 +- frontend/src/config/types.ts | 6 +- frontend/src/context/datasetStateSlice.ts | 110 ++++++++- frontend/src/context/tableStateSlice.ts | 20 +- frontend/src/utils/admin-utils.ts | 8 +- frontend/src/utils/ews-utils.ts | 21 +- frontend/src/utils/fetch-with-timeout.ts | 2 +- frontend/src/utils/google-flood-utils.ts | 123 ++++++++++ frontend/src/utils/title-utils.ts | 27 +++ frontend/test/setupTests.ts | 10 + frontend/yarn.lock | 11 +- 30 files changed, 1303 insertions(+), 402 deletions(-) create mode 100644 api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauge_forecast.yaml create mode 100644 api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauge_forecast_multiple_gauges.yaml create mode 100644 frontend/src/utils/google-flood-utils.ts create mode 100644 frontend/src/utils/title-utils.ts diff --git a/api/app/googleflood.py b/api/app/googleflood.py index 7cdcbc693..6921fd446 100644 --- a/api/app/googleflood.py +++ b/api/app/googleflood.py @@ -16,6 +16,28 @@ logger.warning("Missing backend parameter: GOOGLE_FLOODS_API_KEY") +def make_google_floods_request(url, method="get", data=None, retries=1, timeout=10): + """Make a request with retries and error handling.""" + for _ in range(retries): + try: + if method == "post": + response_data = requests.post(url, json=data, timeout=timeout).json() + else: + response_data = requests.get(url, timeout=timeout).json() + break + except requests.exceptions.RequestException as e: + logger.warning("Request failed at url %s: %s", url, e) + response_data = {} + + if "error" in response_data: + logger.error("Error in response: %s", response_data["error"]) + raise HTTPException( + status_code=500, detail="Error fetching data from Google API" + ) + + return response_data + + def format_gauge_to_geojson(data): """Format Gauge data to GeoJSON""" geojson = { @@ -37,6 +59,8 @@ def format_gauge_to_geojson(data): "severity": data["severity"], "source": data["source"], "qualityVerified": data["qualityVerified"], + "thresholds": data["thresholds"], + "gaugeValueUnit": data["gaugeValueUnit"], }, } if "inundationMapSet" in data: @@ -47,15 +71,10 @@ def format_gauge_to_geojson(data): def fetch_flood_status(region_code): """Fetch flood status for a region code""" flood_status_url = f"https://floodforecasting.googleapis.com/v1/floodStatus:searchLatestFloodStatusByArea?key={GOOGLE_FLOODS_API_KEY}" - for _ in range(3): - try: - status_response = requests.post( - flood_status_url, json={"regionCode": region_code}, timeout=2 - ).json() - return status_response - except requests.RequestException as e: - logger.warning("Request failed at url %s: %s", flood_status_url, e) - return {} + status_response = make_google_floods_request( + flood_status_url, method="post", data={"regionCode": region_code}, retries=3 + ) + return status_response def get_google_flood_dates(region_codes: list[str]): @@ -124,34 +143,36 @@ def get_google_floods_gauges( ) initial_gauges.extend(status_response.get("floodStatuses", [])) - gauge_params = urlencode( + gauge_details_params = urlencode( {"names": [f"gauges/{gauge['gaugeId']}" for gauge in initial_gauges]}, doseq=True, ) - gauges_details_url = f"https://floodforecasting.googleapis.com/v1/gauges:batchGet?key={GOOGLE_FLOODS_API_KEY}&{gauge_params}" + gauges_details_url = f"https://floodforecasting.googleapis.com/v1/gauges:batchGet?key={GOOGLE_FLOODS_API_KEY}&{gauge_details_params}" - try: - details_response = requests.get(gauges_details_url, timeout=2).json() - except requests.RequestException as e: - logger.warning("Request failed at url %s: %s", gauges_details_url, e) - details_response = {} + gauge_models_params = urlencode( + {"names": [f"gaugeModels/{gauge['gaugeId']}" for gauge in initial_gauges]}, + doseq=True, + ) + gauges_models_url = f"https://floodforecasting.googleapis.com/v1/gaugeModels:batchGet?key={GOOGLE_FLOODS_API_KEY}&{gauge_models_params}" - if "error" in details_response: - logger.error("Error in response: %s", details_response["error"]) - raise HTTPException( - status_code=500, detail="Error fetching gauges details from Google API" - ) + # Run both requests + details_response = make_google_floods_request(gauges_details_url) + models_response = make_google_floods_request(gauges_models_url) - # Create a map for quick lookup + # Create maps for quick lookup gauge_details_map = { item["gaugeId"]: item for item in details_response.get("gauges", []) } + gauge_models_map = { + item["gaugeId"]: item for item in models_response.get("gaugeModels", []) + } gauges_details = [] for gauge in initial_gauges: gauge_id = gauge["gaugeId"] detail = gauge_details_map.get(gauge_id, {}) - merged_gauge = {**gauge, **detail} + model = gauge_models_map.get(gauge_id, {}) + merged_gauge = {**gauge, **detail, **model} gauges_details.append(merged_gauge) if as_geojson: @@ -161,3 +182,39 @@ def get_google_floods_gauges( } return geojson_feature_collection return gauges_details + + +def get_google_floods_gauge_forecast(gauge_ids: list[str]): + """Get forecast data for a gauge""" + + gauge_params = urlencode( + {"gaugeIds": [gauge_id for gauge_id in gauge_ids]}, + doseq=True, + ) + forecast_url = f"https://floodforecasting.googleapis.com/v1/gauges:queryGaugeForecasts?key={GOOGLE_FLOODS_API_KEY}&{gauge_params}" + forecast_response = make_google_floods_request(forecast_url) + + forecasts = forecast_response.get("forecasts", {}) + + forecast_data = {} + for gauge_id in gauge_ids: + forecast_map = {} + for forecast in forecasts.get(gauge_id, {}).get("forecasts", []): + issued_time = forecast.get("issuedTime") + for forecast_range in forecast.get("forecastRanges", []): + start_time = forecast_range.get("forecastStartTime") + value = round(forecast_range.get("value"), 2) + + # Deduplicate by forecastStartTime, keeping the most recent issuedTime + if ( + start_time not in forecast_map + or issued_time > forecast_map[start_time]["issuedTime"] + ): + forecast_map[start_time] = { + "issuedTime": issued_time, + "value": [start_time, value], + } + + forecast_data[gauge_id] = list(forecast_map.values()) + + return forecast_data diff --git a/api/app/main.py b/api/app/main.py index 7c27ee32d..ac50703f6 100644 --- a/api/app/main.py +++ b/api/app/main.py @@ -14,7 +14,11 @@ from app.database.alert_model import AlchemyEncoder, AlertModel from app.database.database import AlertsDataBase from app.database.user_info_model import UserInfoModel -from app.googleflood import get_google_flood_dates, get_google_floods_gauges +from app.googleflood import ( + get_google_flood_dates, + get_google_floods_gauge_forecast, + get_google_floods_gauges, +) from app.hdc import get_hdc_stats from app.kobo import get_form_dates, get_form_responses, parse_datetime_params from app.models import AcledRequest, RasterGeotiffModel @@ -423,7 +427,6 @@ def get_google_floods_gauges_api(region_codes: list[str] = Query(...)): status_code=400, detail="At least one region code must be provided.", ) - for region_code in region_codes: if len(region_code) != 2: raise HTTPException( @@ -455,3 +458,17 @@ def get_google_floods_dates_api(region_codes: list[str] = Query(...)): iso2_codes = [region_code.upper() for region_code in region_codes] return get_google_flood_dates(iso2_codes) + + +@app.get("/google-floods/gauges/forecasts") +def get_google_floods_gauge_forecast_api( + gauge_ids: str = Query(..., description="Comma-separated list of gauge IDs") +): + """Get forecast data for a gauge or multiple gauges""" + gauge_id_list = [id.strip() for id in gauge_ids.split(",")] + if not gauge_id_list: + raise HTTPException( + status_code=400, + detail="gauge_ids must be provided and contain at least one value.", + ) + return get_google_floods_gauge_forecast(gauge_id_list) diff --git a/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauge_forecast.yaml b/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauge_forecast.yaml new file mode 100644 index 000000000..d72a05ebb --- /dev/null +++ b/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauge_forecast.yaml @@ -0,0 +1,67 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.32.0 + method: GET + uri: https://floodforecasting.googleapis.com/v1/gauges:queryGaugeForecasts?gaugeIds=hybas_1121465590 + response: + body: + string: !!binary | + H4sIAAAAAAAC/9Vay24bRxC86ysEnaVBvx+8+wcSnRIEgZIojoHEBiw5QGDo39OkY4GkL9zWEhMB + PJDLnd3isruqq3s+X1xeXv3+4eP9r3cPjw9Xm8vPdaAO/fHPL3cPPyMSiqkmPH9zdPqP/x28fP56 + d8q7h4dP97/dvvvrvs65IiC5gbghuUXeKG00hlEE2A9X1/vLvl75u7v3b+8PL398i935f9/9+Wl7 + B40cyS4caRLCrtfHp3699PePdx8fvwHGtwCb3esQ0cHSN++//UX7Cw/WPV2fCD1xACKIszEF0lLo + 0oUua0APYjYh9QZy7SLXFyOveBHX1ArvTrhYF7m9HLkNURcNSYNcDt270P3l0HmkkVuoisVi5NFF + Hi9HDqNiXNzAhXA59OxCzxdDdx3uFeTIELo8Xhia0A8WHkLf+/TT8/u9H3SKkuhWSYQ2IJUOmbme + kvgg8Ajt/dMT2bg4zRQsK1rhtdFx1QMVpZSY2XnqM/lYRgZVwLTSayod07AIr2gHXh4tE9nYS7wF + I0UbuOdSMSRVMc1MjUd+Dio+GXoJoBiIdNKTsQscz6ohtnMjudOQKgU5VtOQqtEEvJg4O9XlTCK2 + QQ4oaIBqi5NrLg+X9klX/GbyMFZx6RgK2pKQmUy89fFVzSejCSyPl5lkXLqNLE0HOJWLeSj2jMg5 + mHgB7MLMDgbL7V/eQA/60cL1RcR3IsIbqOobQsRXExGt3CqrT66cjdyaycVaHio1xckaKjK3RREu + xuzReeYzWxQ4oNsTmknDMbAAI/VsyFQe3nYKpCSkBXwmE1d5ysHaqebPQ8QLkCNzIuLyVnkBoC5y + OquExK6XpdupiJdr4PUkJAcRGoaVu2kYkZlEnIOZm3w2k4Z9WOk1g722grgMlKNls68yk4ir3BCm + svCI/rpq4ooWrYTvSMhcIg4bllRVfEb8T5h4QdszVaJkZLHvq/v3BsVHC9eXkLxF2QBtkAYZg+Rq + EgIjJcopN+chc4d29f9Gq8yZXhRrAjlkS/+mFsU5AJ072TWZimEEUKjJcvmbzMUwzJw620fmMnEZ + qCrkIQN7z/wMXHwydBruTkHeaB8Wgt6Y+Gjh6jJS+f9lfxb7SNzueFhLRpzLiQjJK+wT0xDndsN1 + JhVXjFZsFh13dmdNbVAU8vL56OG4WP8mdyh4VIinl5b4Yss9mY5haBkohWg0P+fSsdkgFG7sKzsP + F5+MWwYLRaouH1oWgN6g+Gjh+iryJYtwIzyUSuVX62eZV6XT7f/NJWOLEYbUGn7NJWPLwVuvT5av + rDB2HGAogGyL+0JzqbiiBcpEARMtn6BNpmIdgk7Z2s4+mY25ivoSvmZP6wxsfDJyHKUl6oqtHO2N + io8WnqIjF/tHtp+eLp4u/gULG2d/gzIAAA== + headers: + Alt-Svc: + - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 + Cache-Control: + - private + Content-Encoding: + - gzip + Content-Type: + - application/json; charset=UTF-8 + Date: + - Sat, 31 Aug 2024 00:23:43 GMT + Server: + - ESF + Server-Timing: + - gfet4t7; dur=397 + Transfer-Encoding: + - chunked + Vary: + - Origin + - X-Origin + - Referer + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-XSS-Protection: + - '0' + status: + code: 200 + message: OK +version: 1 diff --git a/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauge_forecast_multiple_gauges.yaml b/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauge_forecast_multiple_gauges.yaml new file mode 100644 index 000000000..8d889d28b --- /dev/null +++ b/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauge_forecast_multiple_gauges.yaml @@ -0,0 +1,84 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.32.0 + method: GET + uri: https://floodforecasting.googleapis.com/v1/gauges:queryGaugeForecasts?gaugeIds=hybas_1121465590&gaugeIds=hybas_1121499110 + response: + body: + string: !!binary | + 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 + headers: + Alt-Svc: + - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 + Cache-Control: + - private + Content-Encoding: + - gzip + Content-Type: + - application/json; charset=UTF-8 + Date: + - Sat, 31 Aug 2024 00:23:44 GMT + Server: + - ESF + Server-Timing: + - gfet4t7; dur=383 + Transfer-Encoding: + - chunked + Vary: + - Origin + - X-Origin + - Referer + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-XSS-Protection: + - '0' + status: + code: 200 + message: OK +version: 1 diff --git a/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges.yaml b/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges.yaml index 27d717428..534a60a6f 100644 --- a/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges.yaml +++ b/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges.yaml @@ -19,84 +19,68 @@ interactions: response: body: string: !!binary | - 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 - AA== + H4sIAAAAAAAC/+1d227bSBJ9n68I8pwQVdXdddGbc5mMd30ZJJkJdhaDgJKorAGPnfVlFtlB/n2b + sh1fSZNiUyspZIIgCduk2DpdPFV1qvqvH548eTo7PD6evjvLz85Pi9Onoyf/jP/55Mlf8z/j6U/5 + +adiexpPPH3x4dWLj+8+kMDTZ1enD05Pz4vp+4M/inIEAfnnoM8dvgcYgY7QMgavEn67/pHZ8Ukx + yU/Pyh96mx99Kn/y6nbx9OlZfnJ2fTF7DvFiNiqvB9dXiQOLo2nlsMtRX+/d9OW/7t/xz/zwvHjg + RDx1ePyf4uTF8fn8Vs8hQ7g40BsgMtKzm6PPP3++Hg3fzny98aFPillxUhxNioef/v7zx8mEB5// + 7gzcGXh998q5eH9yeYEft3Z2rr+fP/LP20dXn/LL5/kXu7v/6vWNIafFn8XJwdmX8tTWi/1fX3/c + 23+7u3VjxMFRnIX87OD4aDf//K44uz3jt85eg+7iuDkb5VcQ73VY3uin7Tc/3Xr++Qc5OcgPD/5b + TH8+Pvzy6fjoAqnmc59PTfKZqMcJ2GzqYFJI/B1mYPz0xlW+Pmtw793Xr7Z/2W149+l4NiU3gTEX + zusUDQRJZDId44TGWLS++87+h6YPXkxnE8ptPJkU3hfjcV4Ew3w8JbZpKPytW3/7++/Pqr6a5aG0 + 6iNcIfDnt/svtl5s72y//8f91X16fH4yKa5s1DUK58Zr53gyv9htCB7G/zs7n5Y/RD5jQ/b+xmc4 + PD76dHXeMHNqbHrvvv8+j9/B2Zdf45cxOyjKxzw7OS9+uDGozo6SNrSjOCKXBQAh2xA7Spd2lEyB + HJGvtqMPWd11Na037ebe/scfd/b3X23vvXmaDsjihECrgAyZdwicGMjaCsfxOwyI3x+O15YP9A9a + x6pUZX1VsxAcmyW2vkjtUIuG9NvyZsVlFD9isOp3kndKDtPOCkrbWUHhjmvZNVvLru+1HIZ30MWA + rstZhbyFKuBS5jWwp7TAdVvtuBSGm9O91u+g8lHKI1h0tSOL1Vocw+VoEB8gKPCA4yoDbIGNudoA + I5pPjeM4Se2ATF5hia8lH21+XLw1rpKIV+HEs+IbUkyEkdeMxNDrwst7fjGCx5b3nWHDa2mllzNF + OxlhUf1WAnZeEq9m9e3YlFqgbrB9nE3dGdYLbGEj3KAIw5c/be29eb1MlBorUqUDH80rOAs+MesP + f2uHU2ORDWFP9Ih9vUuu1ge+S6f9huykyou3rCSbqZFLzO2QS4665qJWwl8dLOyCOA0ZgPdSGVeh + jDigJY6rkGuBU45GSRkXj/VfXIyaMQEacFr14P9fnLJGa1VpTzVjjH5WavdTQ0t7ytqRsWJohNPr + YQNOVwmnnIETq4qSRJh6BjVJTFh9S5gawUaknAaYLkxPyww/1uBUvCefOMmE3Daa56Rr3Aqbxa2w + V5wOYem+gOwyBFSuihBEPwuid84uMZCxqeZPRugyLTM8m85fI2o9DNGBhqj1giA1cS00dYmtb7yq + vW1JZz0tbn9XiCcM0pTLAV1hK6zsqdrYiqimzhpQBG5oC1wObhOAW0dwMwrrA9S32++W6oUhBZJK + ehtZQakMTGxgXdtkNZgtrha6uFgzegv90tvBDVvcoKo3qJQPQOYch9RRrciYG+KUR95nGgDpO1QH + rRF0l00DgjOtzMqWua3o6YfEohfBVpo2bxqPjqh9VPRyZ1g/1rUVaDN3qYBBIzBSW6PQwXJJQoQx + E1dmvqI7q3EaE3NZCVnLWC364G/A+KFytO3drTevP77c2Xr3bvvH7Zdb77f39x6ex1WsTtOJTWis + PAu5eShm43E+GU9D/BcbTsz6rU7TmVObOD/LJd5dxkqzKSI74NmMfdFnddo0LyS42XhS4MRjPjPJ + RS26phMtpuBkqE77Nrm3l636UJUIjMuW59Vpidbtyw8vP0b683z31bvtnYYLl0bgMouGusP75+Ji + 0ozdS9+syXmbH75UW7kQaup8exZhEo1cI9heD1ycSG2erQ1Twmk+I5+HsZ+w2NRmEy6YbMoT0nG/ + tlZUbTYb52ObeT/jYgyzIi5WQyfsJxR6tLUTV1iIlhXcrPAM0YTojOOHmTGbYM+VwJ1Am8jWRkO2 + UJjaQfh21MjciW8cqSuDoaluOIxCWbwcf/mOlpebWV7ul/kvyTl94GEfpgJ3H3dV4ypl2cXt19Q9 + ebuY+MRZQWvK7HkUMGMf34+Li4VWykFtwQ8gSxq17he6y3ZIHUWu6Wo8UmfgUqdX2LWMqwAurhke + NG4Vj7tGUeuQYakbrywFjC4Yl9VFiXGK2Dh0wiVS1UvkLBsSt36sLmOoe2sqfAtmAWt0xGWxNqUu + 2JSWNpYC3ERu/7MCPtL7ynJAyKKTRpB6VkAazoofOc6ARPxGyFa/k85p/fMl9sFxVWuFuJbVk31T + SSQTW0u7EP68u8Km1AcOMtbe+giIaI2yCp1K6pQqN8WxjFxZER59u64O64DjDcexOiSrSqpGHDvD + gImzqt6aSgPmjgGXifFNIRJDwfbVgM5NL13QSjlARC6raUgd2pamoW0dRd7hzKRDaPsCko+Gtu8M + 6wW5D9jUupjhPfX2+sB42TFEQ2VfE5uRUhudFsUWXdamyXFfdiSK9tfzRjRvHYKIi8s4MDq+lX3x + yjXPzhIHu31r+RU42BTO+whVGEhu4/h38J6kKk8zpwqMqY1sgKxlcxcU9x1Wbw1IbmOEVaO7VtOl + SIQkdUGXNA37fjPBHarAVwjHA1dY2OAqQWV2orS3LMESx3nb9ipA4a6tn1dDzTGgdOEWRRK8VKYj + LAOm4FNHENhlTcu5rsoOAX1FcvGXvb/v7X/YSzgnIGUf0WqWr2rCiZeut3YvGAbblPzMEA68GtA5 + ISNglQrCkhmhOk3cyImohXfKmUdF25TKzGEPnL46PZELUAPksj9O8rg2tPBVJbMg2LXV8yAqXGv2 + VJbCC2iNMEtDPJ9czNG0kdMlVXDmFze4K1TU1U6BlFazvUn5Fs6ci++sSt9Uy1ihh8SwJW4VQgnl + l9zVOV0JnjCY18WFGfFwNRVc6s2H1OmWFjGUUpkLgZcpe3VlrVh87mrv1GOclMRN2tutXW+mt8L4 + S9h/LsQPUrPTmvqgqYtQXMtNEwk6vIdXyKANLWkuB3Q2bwRWrZ/UzKGKT62fbKrq17IjgJgE3Yi3 + 8KBfvxzQuY6q7AZek0d2Eo/UfZTa5jUQOhZTr04P5gG0CSytRHensv1KuQ0geE3dOHyBtklkXZPG + qyGU3AiMPuDxPNRcZXf/1esKLK9iN5WcJTeejYPl3hc8HjudqaLAmAEmU9dvN5UwdbNp/FXkYeJD + znkOYaqAJKTTYso9dlMZTzEELSyPlMrnpEaTHJkEhGU8Zuyrm0rlumy2Mm8vlKV3rvIZkzqosZ2s + yJx6c5C2tacmsBG9k4fNQhN6VwZSGeQ0ytAQMLHgkaAFcH1mASR0bfuzEtuFrlTDtY0CMkYn3NX0 + saKMIA5I7HGhtNSjxKXUVXP+aJLpzrCBu7bhrktIhjoSrekL7o1d6qwSYlthrnXYHmSFDO6A04X3 + Z1YQoZqskmB6eR817l9/pe+7TQyWoB0jBa3JoJiT0EMRXmhahHdBmDyJ34j+SMP67bAPVd3uE8Sl + IC/x6vUN3zIIZcmzKDtnS1y9pTPjtXpvrsgRkSl1Kgld8+5m89WLQqHDnsirFOEcpEiXAzqnkyzO + YM1rh8psTurQvIsLog1wib1f6oIut+SFULvXKRBr6tdxS2EhhO9Ryb1Gr+dlh9yAhatezWUtkXOp + 1VrELeIUmrEjlI3A7MAfO5R3IdepCj1ERydxuyf07Zs4uI4ti1dHwzA0Luurbw6C1flCLrKExFJQ + sqbtn75tyKuLVypeXOxRi3tnWG9AHsQ4CeyvRE+1jiZ4Jy5131500nIrPovA3QSiMDTiTmhwlaM1 + q9mi18r3VeK6RGubiVPeiNYjg729HNC9X45TqemXg0pqiUMsLclu6LL3+ZCVq3jcNfLKXESh3Gqo + eb+1nmnqRiS+rU+Gm9OdbGisdzmgK501AuaajaWFOXnmJbTkBIba1b5+V7vLbZx99Zkzkurd5TDz + CM6njs62bZuH0dp0DHpRs6AX9YvTzF+oIVVBDAShLqGQsd0anBLJm7XZHDms2/2cXZkGT8wROLMW + GpX5bnPds9yrQhPcpQOGVm5AoFbT8Xxo1dWGNUSLYJVV/CVriHOeOAfB2jYH0anD0ToDeY179y89 + uiCqoWb/T6DgLLFNVm0bzFVZvIr9gjA0iy9Q72UWg1IhBRuOLyeqRK1qBqyWOgfsmvaX86MQyn3i + IiHv2F+uGRnGfsnwQCP6oxEAJlLHiANp6iI3DC07eQFDRynDEN1d8+gDRKeIKjdOwSwudUxdGuRa + 1WLGF4LbjIZzw94T/eFYvQer6ZxojsCltreNo2jzrQIRRGkjNI6PpCnWyOYuXYjrI3esEYZxXOcu + dbC3sVAhjIKWm27iLWHYUjaOEavp6++T9wOIhLfNTgc+cz5Q12692Ewuh/0u3oEsLVzMFRgqRUbz + XpbsKXXHFU/tgFp6p9h1B4rVqOUagLqwkpMlUE0URRwqJ46iUGi5dQwKdqX1j3qfd4YNOF0tnIKK + VGuLouVDTU3aia1dtiVEZ802JW04CDdTsHjREI9qIuDE2hYqxT9//+HrD/8DfW/ahDfUAAA= headers: Alt-Svc: - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 @@ -107,11 +91,11 @@ interactions: Content-Type: - application/json; charset=UTF-8 Date: - - Thu, 22 Aug 2024 04:44:11 GMT + - Sat, 31 Aug 2024 00:23:39 GMT Server: - ESF Server-Timing: - - gfet4t7; dur=572 + - gfet4t7; dur=574 Transfer-Encoding: - chunked Vary: @@ -198,11 +182,85 @@ interactions: Content-Type: - application/json; charset=UTF-8 Date: - - Thu, 22 Aug 2024 04:44:11 GMT + - Sat, 31 Aug 2024 00:23:40 GMT Server: - ESF Server-Timing: - - gfet4t7; dur=311 + - gfet4t7; dur=272 + Transfer-Encoding: + - chunked + Vary: + - Origin + - X-Origin + - Referer + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-XSS-Protection: + - '0' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.32.0 + method: GET + uri: https://floodforecasting.googleapis.com/v1/gaugeModels:batchGet?names=gaugeModels%2FBWDB_SW101&names=gaugeModels%2FBWDB_SW110&names=gaugeModels%2FBWDB_SW117&names=gaugeModels%2FBWDB_SW119.1&names=gaugeModels%2FBWDB_SW131.5&names=gaugeModels%2FBWDB_SW132.2&names=gaugeModels%2FBWDB_SW133&names=gaugeModels%2FBWDB_SW137A&names=gaugeModels%2FBWDB_SW14.5&names=gaugeModels%2FBWDB_SW140&names=gaugeModels%2FBWDB_SW142.1&names=gaugeModels%2FBWDB_SW145&names=gaugeModels%2FBWDB_SW147.5&names=gaugeModels%2FBWDB_SW157&names=gaugeModels%2FBWDB_SW159&names=gaugeModels%2FBWDB_SW15J&names=gaugeModels%2FBWDB_SW162&names=gaugeModels%2FBWDB_SW172&names=gaugeModels%2FBWDB_SW173&names=gaugeModels%2FBWDB_SW175.5&names=gaugeModels%2FBWDB_SW177&names=gaugeModels%2FBWDB_SW179&names=gaugeModels%2FBWDB_SW201&names=gaugeModels%2FBWDB_SW202&names=gaugeModels%2FBWDB_SW203&names=gaugeModels%2FBWDB_SW204&names=gaugeModels%2FBWDB_SW206&names=gaugeModels%2FBWDB_SW207&names=gaugeModels%2FBWDB_SW211.5&names=gaugeModels%2FBWDB_SW212&names=gaugeModels%2FBWDB_SW225&names=gaugeModels%2FBWDB_SW228&names=gaugeModels%2FBWDB_SW236&names=gaugeModels%2FBWDB_SW238&names=gaugeModels%2FBWDB_SW247&names=gaugeModels%2FBWDB_SW248&names=gaugeModels%2FBWDB_SW251&names=gaugeModels%2FBWDB_SW263&names=gaugeModels%2FBWDB_SW263.1&names=gaugeModels%2FBWDB_SW266&names=gaugeModels%2FBWDB_SW267&names=gaugeModels%2FBWDB_SW269&names=gaugeModels%2FBWDB_SW269.5&names=gaugeModels%2FBWDB_SW270&names=gaugeModels%2FBWDB_SW273&names=gaugeModels%2FBWDB_SW274&names=gaugeModels%2FBWDB_SW275.5&names=gaugeModels%2FBWDB_SW277&names=gaugeModels%2FBWDB_SW285&names=gaugeModels%2FBWDB_SW291.5R&names=gaugeModels%2FBWDB_SW294&names=gaugeModels%2FBWDB_SW299&names=gaugeModels%2FBWDB_SW302&names=gaugeModels%2FBWDB_SW36&names=gaugeModels%2FBWDB_SW3A&names=gaugeModels%2FBWDB_SW42&names=gaugeModels%2FBWDB_SW45&names=gaugeModels%2FBWDB_SW45.5&names=gaugeModels%2FBWDB_SW46.9L&names=gaugeModels%2FBWDB_SW49&names=gaugeModels%2FBWDB_SW49A&names=gaugeModels%2FBWDB_SW5&names=gaugeModels%2FBWDB_SW50.6&names=gaugeModels%2FBWDB_SW62&names=gaugeModels%2FBWDB_SW63&names=gaugeModels%2FBWDB_SW65&names=gaugeModels%2FBWDB_SW67&names=gaugeModels%2FBWDB_SW68.5&names=gaugeModels%2FBWDB_SW71A&names=gaugeModels%2FBWDB_SW72&names=gaugeModels%2FBWDB_SW77&names=gaugeModels%2FBWDB_SW84&names=gaugeModels%2FBWDB_SW88&names=gaugeModels%2FBWDB_SW88A&names=gaugeModels%2FBWDB_SW90&names=gaugeModels%2FBWDB_SW91.9R&names=gaugeModels%2FBWDB_SW93.4L&names=gaugeModels%2FBWDB_SW93.5L&names=gaugeModels%2FBWDB_SW95&names=gaugeModels%2FBWDB_SW99&names=gaugeModels%2FCWC_012-MDSIL + response: + body: + string: !!binary | + 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 + IquH+H9eC0mfvx59PvoHXlAKZG1VAAA= + headers: + Alt-Svc: + - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 + Cache-Control: + - private + Content-Encoding: + - gzip + Content-Type: + - application/json; charset=UTF-8 + Date: + - Sat, 31 Aug 2024 00:23:40 GMT + Server: + - ESF + Server-Timing: + - gfet4t7; dur=145 Transfer-Encoding: - chunked Vary: diff --git a/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api.yaml b/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api.yaml index c7643ec4c..08776e427 100644 --- a/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api.yaml +++ b/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api.yaml @@ -19,84 +19,68 @@ interactions: response: body: string: !!binary | - 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 - AA== + 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 headers: Alt-Svc: - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 @@ -107,11 +91,11 @@ interactions: Content-Type: - application/json; charset=UTF-8 Date: - - Thu, 22 Aug 2024 04:44:12 GMT + - Sat, 31 Aug 2024 00:23:40 GMT Server: - ESF Server-Timing: - - gfet4t7; dur=589 + - gfet4t7; dur=548 Transfer-Encoding: - chunked Vary: @@ -198,11 +182,85 @@ interactions: Content-Type: - application/json; charset=UTF-8 Date: - - Thu, 22 Aug 2024 04:44:12 GMT + - Sat, 31 Aug 2024 00:23:41 GMT Server: - ESF Server-Timing: - - gfet4t7; dur=399 + - gfet4t7; dur=274 + Transfer-Encoding: + - chunked + Vary: + - Origin + - X-Origin + - Referer + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-XSS-Protection: + - '0' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.32.0 + method: GET + uri: https://floodforecasting.googleapis.com/v1/gaugeModels:batchGet?names=gaugeModels%2FBWDB_SW101&names=gaugeModels%2FBWDB_SW110&names=gaugeModels%2FBWDB_SW117&names=gaugeModels%2FBWDB_SW119.1&names=gaugeModels%2FBWDB_SW131.5&names=gaugeModels%2FBWDB_SW132.2&names=gaugeModels%2FBWDB_SW133&names=gaugeModels%2FBWDB_SW137A&names=gaugeModels%2FBWDB_SW14.5&names=gaugeModels%2FBWDB_SW140&names=gaugeModels%2FBWDB_SW142.1&names=gaugeModels%2FBWDB_SW145&names=gaugeModels%2FBWDB_SW147.5&names=gaugeModels%2FBWDB_SW157&names=gaugeModels%2FBWDB_SW159&names=gaugeModels%2FBWDB_SW15J&names=gaugeModels%2FBWDB_SW162&names=gaugeModels%2FBWDB_SW172&names=gaugeModels%2FBWDB_SW173&names=gaugeModels%2FBWDB_SW175.5&names=gaugeModels%2FBWDB_SW177&names=gaugeModels%2FBWDB_SW179&names=gaugeModels%2FBWDB_SW201&names=gaugeModels%2FBWDB_SW202&names=gaugeModels%2FBWDB_SW203&names=gaugeModels%2FBWDB_SW204&names=gaugeModels%2FBWDB_SW206&names=gaugeModels%2FBWDB_SW207&names=gaugeModels%2FBWDB_SW211.5&names=gaugeModels%2FBWDB_SW212&names=gaugeModels%2FBWDB_SW225&names=gaugeModels%2FBWDB_SW228&names=gaugeModels%2FBWDB_SW236&names=gaugeModels%2FBWDB_SW238&names=gaugeModels%2FBWDB_SW247&names=gaugeModels%2FBWDB_SW248&names=gaugeModels%2FBWDB_SW251&names=gaugeModels%2FBWDB_SW263&names=gaugeModels%2FBWDB_SW263.1&names=gaugeModels%2FBWDB_SW266&names=gaugeModels%2FBWDB_SW267&names=gaugeModels%2FBWDB_SW269&names=gaugeModels%2FBWDB_SW269.5&names=gaugeModels%2FBWDB_SW270&names=gaugeModels%2FBWDB_SW273&names=gaugeModels%2FBWDB_SW274&names=gaugeModels%2FBWDB_SW275.5&names=gaugeModels%2FBWDB_SW277&names=gaugeModels%2FBWDB_SW285&names=gaugeModels%2FBWDB_SW291.5R&names=gaugeModels%2FBWDB_SW294&names=gaugeModels%2FBWDB_SW299&names=gaugeModels%2FBWDB_SW302&names=gaugeModels%2FBWDB_SW36&names=gaugeModels%2FBWDB_SW3A&names=gaugeModels%2FBWDB_SW42&names=gaugeModels%2FBWDB_SW45&names=gaugeModels%2FBWDB_SW45.5&names=gaugeModels%2FBWDB_SW46.9L&names=gaugeModels%2FBWDB_SW49&names=gaugeModels%2FBWDB_SW49A&names=gaugeModels%2FBWDB_SW5&names=gaugeModels%2FBWDB_SW50.6&names=gaugeModels%2FBWDB_SW62&names=gaugeModels%2FBWDB_SW63&names=gaugeModels%2FBWDB_SW65&names=gaugeModels%2FBWDB_SW67&names=gaugeModels%2FBWDB_SW68.5&names=gaugeModels%2FBWDB_SW71A&names=gaugeModels%2FBWDB_SW72&names=gaugeModels%2FBWDB_SW77&names=gaugeModels%2FBWDB_SW84&names=gaugeModels%2FBWDB_SW88&names=gaugeModels%2FBWDB_SW88A&names=gaugeModels%2FBWDB_SW90&names=gaugeModels%2FBWDB_SW91.9R&names=gaugeModels%2FBWDB_SW93.4L&names=gaugeModels%2FBWDB_SW93.5L&names=gaugeModels%2FBWDB_SW95&names=gaugeModels%2FBWDB_SW99&names=gaugeModels%2FCWC_012-MDSIL + response: + body: + string: !!binary | + H4sIAAAAAAAC/+1cO28cNxDu9SsE1QpBDt/pYsuFA6uxEqsIAkPAreUDLjJylvKA4f8e3smKI3KH + y5mCdA5ScYVuRhC/ncc3D+6no+Pjk+uru+vp/MNq2nw8+f74l/Sr4+NP+8+HL1+u0hcnzy7Pnr29 + uAQvT04fvr59v50+vv+wWe1UH5TS7/+82t6sb65fTX9Mm/SNE9bK9KOi9NoEp/XpV9nV1c31tH0Q + 9ULiotNft9vpt+nskUYoNL4ofD59dIo3V5u76eeb9e3uMOcvfnrx+uLrQX6/u9qsb/9+M23X79bT + 7ry327vp6D9/pgYJBDIkSuWYoJAoyE+4BInSuUZvSAIDES+siekHtJdOWuNxRNIzR0XnEYm5Rncj + UUCHpPbkCyPB7QkzEjvWSJRnQGJE2D3H6FSwWoKvQGKFRkXnIXG5Rm9I9A9kREx7cLXk4OrGB1fJ + MBIpgmz0GyU0KjpvJJBrdIfE0KNr+SBRSKrZehYSX2h0zzeGbiSFs+NG4ipBZ95IfK7RPbjaH+mQ + WOFtDQWwDQcH290hnOPkVqicFR4jgWVQ3/+smn5WDc3USmsqtdJmOLUKlp41ozD7mOUdRB2Nxb0/ + iUZUdBYSK3ON7t5v6JAk13WmMSAGoVBRjIBnGt0hcXQiYYTaP0cZrXbeaOVwKxEOF523kkKjOySK + XssfOLeKSsTXZFCS5+yzfZARnFXpcaKgJM/BRWdBiYVG9wCbULF0VKy6t3BlwQYfosS9x8K9p82K + znuPzjV6o6IZlQnOOKxY5BuJmHePEFIxnKFCrHwDrwoDaJVXnMq7clDTcFA7gj/6ZGmMozaXj9V+ + BALDsPLx+eXzt1LBd+dnFy9fsZq4ePbTyx6tjDD7hKelVd76oLqbg6RXzjZP0rWOU8BFkSCXa3Sn + AHT30BU7MIvm3/2ZO/3Uis6784oRFUFWiuXHoCRRvASfBQVUrtE/VdDt5MBjA0jPyRJq/2/roIyL + HiqDrcSYUVGsYso0ulNE4xmuszvpo6qmAgpkBdAyKDrX6A2KYyCSXMc2mklyHVQUm2xlGr0RMZFO + sBM9whsIq5xJ4W2JeUiK+NM/vtK5l6l16G1Dg94N6M9HLQydXSd/2Oe/KI3TYF0wlYMHXBRLJZlG + d4fg1GEAtecPusEAwAywACsFfWwRhDHNXbWIiyJdtVyjNyaeTiXANg9ywFEHOeBHD3IYHXqtBMi2 + OU4S9ajo/GgLco3uKcIlKvM07M+pBKd8bR72A3nYr0cP+wEYfLMWIIrJP7F4LZf5ukMiGTsBRR+i + xjepS5nF9lVvSJRhrO7Ge5b8b4MSUEi8FBoVnQ8lKtfoH18Z9bxsr0pqw9J5K1GjqxLDmGq155uy + 17/M1EfnG46NhEqFntlIrNT980RN5hrd3UbTNxBBtTdLi9bnIiTFhlN3I2H01GMzd02iRO6ajGQw + d2Vsdx84cVWs2Wt5waVSBlNBid8AKKxpVDNRK+7CLKbggtr1564MSGrLVsWUgcpKYDQrUZ5e9BUt + 4RotqYytEFqSa3SHRDF4yYF31BnrSqpoe+GQ1K6ozUMSRvOSmGpaTu+9efG1XGNddp3Ri69gnlwn + jyaaswFRcqoKN6FePovDL58pDYLOYiHilU1cXgrTsv+eZ2Qsgut2f9Bkfyg8qHuIcHTC4duXXzx5 + +SUMX35JD4UeIVz7FLecyS6XdKOnuBDpM3wIwsfGTkgUgIpi0SPT6B80PX3Vw7fPej151ltOh7vH + V8bIqlalFSMr6kWbInj3RoSzZFtZt9cN6/ZmwLo94x7egQ/5laX7QrWvtVogjYu+IIf3exirIA/3 + dKOFVEBBMPhgTn+xp1lRxFNGdwWNE5FxIaMot/GYWbwRZtF1im3v3qC4wCrRDpqUhkAnG9X5UhZh + gWwmxQ363pAw3hBQxkDccST5ekfxrqv+OYexa1cM0HAjqS2hYfPKTKM/S2fMGA68BcZIw6ZWsxYz + BvKScq7RnZkwCpcD7x2r3assnhhs3hoCBig6NL8gQEfqCwKMHP2CALCMaZRqXxwC6uLQruofvDjk + IquH+H9eC0mfvx59PvoHXlAKZG1VAAA= + headers: + Alt-Svc: + - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 + Cache-Control: + - private + Content-Encoding: + - gzip + Content-Type: + - application/json; charset=UTF-8 + Date: + - Sat, 31 Aug 2024 00:23:41 GMT + Server: + - ESF + Server-Timing: + - gfet4t7; dur=388 Transfer-Encoding: - chunked Vary: diff --git a/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api_case_insensitive.yaml b/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api_case_insensitive.yaml index 290d67e1c..187959390 100644 --- a/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api_case_insensitive.yaml +++ b/api/app/tests/cassettes/test_google_floods_api/test_get_google_floods_gauges_api_case_insensitive.yaml @@ -19,84 +19,68 @@ interactions: response: body: string: !!binary | - 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 - AA== + H4sIAAAAAAAC/+1d227bSBJ9n68I8pwQVdXdddGbc5mMd30ZJJkJdhaDgJKorAGPnfVlFtlB/n2b + sh1fSZNiUyspZIIgCduk2DpdPFV1qvqvH548eTo7PD6evjvLz85Pi9Onoyf/jP/55Mlf8z/j6U/5 + +adiexpPPH3x4dWLj+8+kMDTZ1enD05Pz4vp+4M/inIEAfnnoM8dvgcYgY7QMgavEn67/pHZ8Ukx + yU/Pyh96mx99Kn/y6nbx9OlZfnJ2fTF7DvFiNiqvB9dXiQOLo2nlsMtRX+/d9OW/7t/xz/zwvHjg + RDx1ePyf4uTF8fn8Vs8hQ7g40BsgMtKzm6PPP3++Hg3fzny98aFPillxUhxNioef/v7zx8mEB5// + 7gzcGXh998q5eH9yeYEft3Z2rr+fP/LP20dXn/LL5/kXu7v/6vWNIafFn8XJwdmX8tTWi/1fX3/c + 23+7u3VjxMFRnIX87OD4aDf//K44uz3jt85eg+7iuDkb5VcQ73VY3uin7Tc/3Xr++Qc5OcgPD/5b + TH8+Pvzy6fjoAqnmc59PTfKZqMcJ2GzqYFJI/B1mYPz0xlW+Pmtw793Xr7Z/2W149+l4NiU3gTEX + zusUDQRJZDId44TGWLS++87+h6YPXkxnE8ptPJkU3hfjcV4Ew3w8JbZpKPytW3/7++/Pqr6a5aG0 + 6iNcIfDnt/svtl5s72y//8f91X16fH4yKa5s1DUK58Zr53gyv9htCB7G/zs7n5Y/RD5jQ/b+xmc4 + PD76dHXeMHNqbHrvvv8+j9/B2Zdf45cxOyjKxzw7OS9+uDGozo6SNrSjOCKXBQAh2xA7Spd2lEyB + HJGvtqMPWd11Na037ebe/scfd/b3X23vvXmaDsjihECrgAyZdwicGMjaCsfxOwyI3x+O15YP9A9a + x6pUZX1VsxAcmyW2vkjtUIuG9NvyZsVlFD9isOp3kndKDtPOCkrbWUHhjmvZNVvLru+1HIZ30MWA + rstZhbyFKuBS5jWwp7TAdVvtuBSGm9O91u+g8lHKI1h0tSOL1Vocw+VoEB8gKPCA4yoDbIGNudoA + I5pPjeM4Se2ATF5hia8lH21+XLw1rpKIV+HEs+IbUkyEkdeMxNDrwst7fjGCx5b3nWHDa2mllzNF + OxlhUf1WAnZeEq9m9e3YlFqgbrB9nE3dGdYLbGEj3KAIw5c/be29eb1MlBorUqUDH80rOAs+MesP + f2uHU2ORDWFP9Ih9vUuu1ge+S6f9huykyou3rCSbqZFLzO2QS4665qJWwl8dLOyCOA0ZgPdSGVeh + jDigJY6rkGuBU45GSRkXj/VfXIyaMQEacFr14P9fnLJGa1VpTzVjjH5WavdTQ0t7ytqRsWJohNPr + YQNOVwmnnIETq4qSRJh6BjVJTFh9S5gawUaknAaYLkxPyww/1uBUvCefOMmE3Daa56Rr3Aqbxa2w + V5wOYem+gOwyBFSuihBEPwuid84uMZCxqeZPRugyLTM8m85fI2o9DNGBhqj1giA1cS00dYmtb7yq + vW1JZz0tbn9XiCcM0pTLAV1hK6zsqdrYiqimzhpQBG5oC1wObhOAW0dwMwrrA9S32++W6oUhBZJK + ehtZQakMTGxgXdtkNZgtrha6uFgzegv90tvBDVvcoKo3qJQPQOYch9RRrciYG+KUR95nGgDpO1QH + rRF0l00DgjOtzMqWua3o6YfEohfBVpo2bxqPjqh9VPRyZ1g/1rUVaDN3qYBBIzBSW6PQwXJJQoQx + E1dmvqI7q3EaE3NZCVnLWC364G/A+KFytO3drTevP77c2Xr3bvvH7Zdb77f39x6ex1WsTtOJTWis + PAu5eShm43E+GU9D/BcbTsz6rU7TmVObOD/LJd5dxkqzKSI74NmMfdFnddo0LyS42XhS4MRjPjPJ + RS26phMtpuBkqE77Nrm3l636UJUIjMuW59Vpidbtyw8vP0b683z31bvtnYYLl0bgMouGusP75+Ji + 0ozdS9+syXmbH75UW7kQaup8exZhEo1cI9heD1ycSG2erQ1Twmk+I5+HsZ+w2NRmEy6YbMoT0nG/ + tlZUbTYb52ObeT/jYgyzIi5WQyfsJxR6tLUTV1iIlhXcrPAM0YTojOOHmTGbYM+VwJ1Am8jWRkO2 + UJjaQfh21MjciW8cqSuDoaluOIxCWbwcf/mOlpebWV7ul/kvyTl94GEfpgJ3H3dV4ypl2cXt19Q9 + ebuY+MRZQWvK7HkUMGMf34+Li4VWykFtwQ8gSxq17he6y3ZIHUWu6Wo8UmfgUqdX2LWMqwAurhke + NG4Vj7tGUeuQYakbrywFjC4Yl9VFiXGK2Dh0wiVS1UvkLBsSt36sLmOoe2sqfAtmAWt0xGWxNqUu + 2JSWNpYC3ERu/7MCPtL7ynJAyKKTRpB6VkAazoofOc6ARPxGyFa/k85p/fMl9sFxVWuFuJbVk31T + SSQTW0u7EP68u8Km1AcOMtbe+giIaI2yCp1K6pQqN8WxjFxZER59u64O64DjDcexOiSrSqpGHDvD + gImzqt6aSgPmjgGXifFNIRJDwfbVgM5NL13QSjlARC6raUgd2pamoW0dRd7hzKRDaPsCko+Gtu8M + 6wW5D9jUupjhPfX2+sB42TFEQ2VfE5uRUhudFsUWXdamyXFfdiSK9tfzRjRvHYKIi8s4MDq+lX3x + yjXPzhIHu31r+RU42BTO+whVGEhu4/h38J6kKk8zpwqMqY1sgKxlcxcU9x1Wbw1IbmOEVaO7VtOl + SIQkdUGXNA37fjPBHarAVwjHA1dY2OAqQWV2orS3LMESx3nb9ipA4a6tn1dDzTGgdOEWRRK8VKYj + LAOm4FNHENhlTcu5rsoOAX1FcvGXvb/v7X/YSzgnIGUf0WqWr2rCiZeut3YvGAbblPzMEA68GtA5 + ISNglQrCkhmhOk3cyImohXfKmUdF25TKzGEPnL46PZELUAPksj9O8rg2tPBVJbMg2LXV8yAqXGv2 + VJbCC2iNMEtDPJ9czNG0kdMlVXDmFze4K1TU1U6BlFazvUn5Fs6ci++sSt9Uy1ihh8SwJW4VQgnl + l9zVOV0JnjCY18WFGfFwNRVc6s2H1OmWFjGUUpkLgZcpe3VlrVh87mrv1GOclMRN2tutXW+mt8L4 + S9h/LsQPUrPTmvqgqYtQXMtNEwk6vIdXyKANLWkuB3Q2bwRWrZ/UzKGKT62fbKrq17IjgJgE3Yi3 + 8KBfvxzQuY6q7AZek0d2Eo/UfZTa5jUQOhZTr04P5gG0CSytRHensv1KuQ0geE3dOHyBtklkXZPG + qyGU3AiMPuDxPNRcZXf/1esKLK9iN5WcJTeejYPl3hc8HjudqaLAmAEmU9dvN5UwdbNp/FXkYeJD + znkOYaqAJKTTYso9dlMZTzEELSyPlMrnpEaTHJkEhGU8Zuyrm0rlumy2Mm8vlKV3rvIZkzqosZ2s + yJx6c5C2tacmsBG9k4fNQhN6VwZSGeQ0ytAQMLHgkaAFcH1mASR0bfuzEtuFrlTDtY0CMkYn3NX0 + saKMIA5I7HGhtNSjxKXUVXP+aJLpzrCBu7bhrktIhjoSrekL7o1d6qwSYlthrnXYHmSFDO6A04X3 + Z1YQoZqskmB6eR817l9/pe+7TQyWoB0jBa3JoJiT0EMRXmhahHdBmDyJ34j+SMP67bAPVd3uE8Sl + IC/x6vUN3zIIZcmzKDtnS1y9pTPjtXpvrsgRkSl1Kgld8+5m89WLQqHDnsirFOEcpEiXAzqnkyzO + YM1rh8psTurQvIsLog1wib1f6oIut+SFULvXKRBr6tdxS2EhhO9Ryb1Gr+dlh9yAhatezWUtkXOp + 1VrELeIUmrEjlI3A7MAfO5R3IdepCj1ERydxuyf07Zs4uI4ti1dHwzA0Luurbw6C1flCLrKExFJQ + sqbtn75tyKuLVypeXOxRi3tnWG9AHsQ4CeyvRE+1jiZ4Jy5131500nIrPovA3QSiMDTiTmhwlaM1 + q9mi18r3VeK6RGubiVPeiNYjg729HNC9X45TqemXg0pqiUMsLclu6LL3+ZCVq3jcNfLKXESh3Gqo + eb+1nmnqRiS+rU+Gm9OdbGisdzmgK501AuaajaWFOXnmJbTkBIba1b5+V7vLbZx99Zkzkurd5TDz + CM6njs62bZuH0dp0DHpRs6AX9YvTzF+oIVVBDAShLqGQsd0anBLJm7XZHDms2/2cXZkGT8wROLMW + GpX5bnPds9yrQhPcpQOGVm5AoFbT8Xxo1dWGNUSLYJVV/CVriHOeOAfB2jYH0anD0ToDeY179y89 + uiCqoWb/T6DgLLFNVm0bzFVZvIr9gjA0iy9Q72UWg1IhBRuOLyeqRK1qBqyWOgfsmvaX86MQyn3i + IiHv2F+uGRnGfsnwQCP6oxEAJlLHiANp6iI3DC07eQFDRynDEN1d8+gDRKeIKjdOwSwudUxdGuRa + 1WLGF4LbjIZzw94T/eFYvQer6ZxojsCltreNo2jzrQIRRGkjNI6PpCnWyOYuXYjrI3esEYZxXOcu + dbC3sVAhjIKWm27iLWHYUjaOEavp6++T9wOIhLfNTgc+cz5Q12692Ewuh/0u3oEsLVzMFRgqRUbz + XpbsKXXHFU/tgFp6p9h1B4rVqOUagLqwkpMlUE0URRwqJ46iUGi5dQwKdqX1j3qfd4YNOF0tnIKK + VGuLouVDTU3aia1dtiVEZ802JW04CDdTsHjREI9qIuDE2hYqxT9//+HrD/8DfW/ahDfUAAA= headers: Alt-Svc: - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 @@ -107,11 +91,11 @@ interactions: Content-Type: - application/json; charset=UTF-8 Date: - - Thu, 22 Aug 2024 04:44:13 GMT + - Sat, 31 Aug 2024 00:23:42 GMT Server: - ESF Server-Timing: - - gfet4t7; dur=572 + - gfet4t7; dur=517 Transfer-Encoding: - chunked Vary: @@ -198,11 +182,85 @@ interactions: Content-Type: - application/json; charset=UTF-8 Date: - - Thu, 22 Aug 2024 04:44:14 GMT + - Sat, 31 Aug 2024 00:23:42 GMT Server: - ESF Server-Timing: - - gfet4t7; dur=318 + - gfet4t7; dur=268 + Transfer-Encoding: + - chunked + Vary: + - Origin + - X-Origin + - Referer + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-XSS-Protection: + - '0' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.32.0 + method: GET + uri: https://floodforecasting.googleapis.com/v1/gaugeModels:batchGet?names=gaugeModels%2FBWDB_SW101&names=gaugeModels%2FBWDB_SW110&names=gaugeModels%2FBWDB_SW117&names=gaugeModels%2FBWDB_SW119.1&names=gaugeModels%2FBWDB_SW131.5&names=gaugeModels%2FBWDB_SW132.2&names=gaugeModels%2FBWDB_SW133&names=gaugeModels%2FBWDB_SW137A&names=gaugeModels%2FBWDB_SW14.5&names=gaugeModels%2FBWDB_SW140&names=gaugeModels%2FBWDB_SW142.1&names=gaugeModels%2FBWDB_SW145&names=gaugeModels%2FBWDB_SW147.5&names=gaugeModels%2FBWDB_SW157&names=gaugeModels%2FBWDB_SW159&names=gaugeModels%2FBWDB_SW15J&names=gaugeModels%2FBWDB_SW162&names=gaugeModels%2FBWDB_SW172&names=gaugeModels%2FBWDB_SW173&names=gaugeModels%2FBWDB_SW175.5&names=gaugeModels%2FBWDB_SW177&names=gaugeModels%2FBWDB_SW179&names=gaugeModels%2FBWDB_SW201&names=gaugeModels%2FBWDB_SW202&names=gaugeModels%2FBWDB_SW203&names=gaugeModels%2FBWDB_SW204&names=gaugeModels%2FBWDB_SW206&names=gaugeModels%2FBWDB_SW207&names=gaugeModels%2FBWDB_SW211.5&names=gaugeModels%2FBWDB_SW212&names=gaugeModels%2FBWDB_SW225&names=gaugeModels%2FBWDB_SW228&names=gaugeModels%2FBWDB_SW236&names=gaugeModels%2FBWDB_SW238&names=gaugeModels%2FBWDB_SW247&names=gaugeModels%2FBWDB_SW248&names=gaugeModels%2FBWDB_SW251&names=gaugeModels%2FBWDB_SW263&names=gaugeModels%2FBWDB_SW263.1&names=gaugeModels%2FBWDB_SW266&names=gaugeModels%2FBWDB_SW267&names=gaugeModels%2FBWDB_SW269&names=gaugeModels%2FBWDB_SW269.5&names=gaugeModels%2FBWDB_SW270&names=gaugeModels%2FBWDB_SW273&names=gaugeModels%2FBWDB_SW274&names=gaugeModels%2FBWDB_SW275.5&names=gaugeModels%2FBWDB_SW277&names=gaugeModels%2FBWDB_SW285&names=gaugeModels%2FBWDB_SW291.5R&names=gaugeModels%2FBWDB_SW294&names=gaugeModels%2FBWDB_SW299&names=gaugeModels%2FBWDB_SW302&names=gaugeModels%2FBWDB_SW36&names=gaugeModels%2FBWDB_SW3A&names=gaugeModels%2FBWDB_SW42&names=gaugeModels%2FBWDB_SW45&names=gaugeModels%2FBWDB_SW45.5&names=gaugeModels%2FBWDB_SW46.9L&names=gaugeModels%2FBWDB_SW49&names=gaugeModels%2FBWDB_SW49A&names=gaugeModels%2FBWDB_SW5&names=gaugeModels%2FBWDB_SW50.6&names=gaugeModels%2FBWDB_SW62&names=gaugeModels%2FBWDB_SW63&names=gaugeModels%2FBWDB_SW65&names=gaugeModels%2FBWDB_SW67&names=gaugeModels%2FBWDB_SW68.5&names=gaugeModels%2FBWDB_SW71A&names=gaugeModels%2FBWDB_SW72&names=gaugeModels%2FBWDB_SW77&names=gaugeModels%2FBWDB_SW84&names=gaugeModels%2FBWDB_SW88&names=gaugeModels%2FBWDB_SW88A&names=gaugeModels%2FBWDB_SW90&names=gaugeModels%2FBWDB_SW91.9R&names=gaugeModels%2FBWDB_SW93.4L&names=gaugeModels%2FBWDB_SW93.5L&names=gaugeModels%2FBWDB_SW95&names=gaugeModels%2FBWDB_SW99&names=gaugeModels%2FCWC_012-MDSIL + response: + body: + string: !!binary | + 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 + IquH+H9eC0mfvx59PvoHXlAKZG1VAAA= + headers: + Alt-Svc: + - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 + Cache-Control: + - private + Content-Encoding: + - gzip + Content-Type: + - application/json; charset=UTF-8 + Date: + - Sat, 31 Aug 2024 00:23:43 GMT + Server: + - ESF + Server-Timing: + - gfet4t7; dur=406 Transfer-Encoding: - chunked Vary: diff --git a/api/app/tests/test_google_floods_api.py b/api/app/tests/test_google_floods_api.py index ddca5e649..6c9095c63 100644 --- a/api/app/tests/test_google_floods_api.py +++ b/api/app/tests/test_google_floods_api.py @@ -24,6 +24,9 @@ def test_get_google_floods_gauges(): assert "gaugeId" in feature["properties"] assert "issuedTime" in feature["properties"] assert "severity" in feature["properties"] + assert "siteName" in feature["properties"] + assert "thresholds" in feature["properties"] + assert "gaugeValueUnit" in feature["properties"] @pytest.mark.vcr( @@ -78,3 +81,46 @@ def test_get_google_floods_gauges_api_requires_valid_region_code(): response.json()["detail"] == "Region code 'usa' must be exactly two characters (iso2)." ) + + +@pytest.mark.vcr( + match_on=["uri", "method"], + filter_headers=["Authorization"], + filter_query_parameters=["key"], + ignore_hosts=["testserver"], +) +def test_get_google_floods_gauge_forecast(): + """ + This test is used to test the API endpoint for getting Google Floods gauge forecast + """ + response = client.get("/google-floods/gauges/forecasts/?gauge_ids=hybas_1121465590") + assert response.status_code == 200 + response_json = response.json() + assert len(response_json) == 1 + assert len(response_json["hybas_1121465590"]) > 0 + assert isinstance(response_json["hybas_1121465590"][0]["value"][0], str) + assert isinstance(response_json["hybas_1121465590"][0]["value"][1], float) + + +@pytest.mark.vcr( + match_on=["uri", "method"], + filter_headers=["Authorization"], + filter_query_parameters=["key"], + ignore_hosts=["testserver"], +) +def test_get_google_floods_gauge_forecast_multiple_gauges(): + """ + This test is used to test the API endpoint for getting Google Floods gauge forecast + """ + gauge_ids = ["hybas_1121465590", "hybas_1121499110"] + response = client.get( + "/google-floods/gauges/forecasts/?gauge_ids=" + ",".join(gauge_ids) + ) + assert response.status_code == 200 + response_json = response.json() + assert len(response_json) == 2 + for gauge_id, gauge in response_json.items(): + assert gauge_id in gauge_ids + assert len(gauge) > 0 + assert isinstance(gauge[0]["value"][0], str) + assert isinstance(gauge[0]["value"][1], float) diff --git a/frontend/package.json b/frontend/package.json index 80d911e7f..6253869a7 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -68,6 +68,7 @@ "babel-eslint": "10.0.3", "canvas": "link:./node_modules/.cache/null", "chart.js": "^2.9.3", + "chartjs-plugin-annotation": "0.5.7", "chartjs-plugin-datalabels": "^1.0.0", "colormap": "^2.3.1", "comlink": "^4.4.1", diff --git a/frontend/src/components/Common/Chart/index.tsx b/frontend/src/components/Common/Chart/index.tsx index bc01ccd32..c7d43c518 100644 --- a/frontend/src/components/Common/Chart/index.tsx +++ b/frontend/src/components/Common/Chart/index.tsx @@ -1,6 +1,7 @@ import React, { memo, useCallback, useMemo } from 'react'; import colormap from 'colormap'; import { ChartOptions } from 'chart.js'; +import 'chartjs-plugin-annotation'; import { Bar, Line } from 'react-chartjs-2'; import { ChartConfig, DatasetField } from 'config/types'; import { TableData } from 'context/tableStateSlice'; @@ -31,14 +32,14 @@ function downloadChartPng(ref: React.RefObject, filename: string) { const useStyles = makeStyles(() => ({ firstIcon: { position: 'absolute', - top: 0, - right: 0, + top: '8px', + right: '0rem', padding: '0.25rem', }, secondIcon: { position: 'absolute', - top: 0, - right: '2rem', + top: '8px', + right: '1.75rem', padding: '0.25rem', }, })); @@ -56,6 +57,8 @@ export type ChartProps = { showDownloadIcons?: boolean; iconStyles?: React.CSSProperties; downloadFilenamePrefix?: string[]; + units?: string; + yAxisLabel?: string; }; const Chart = memo( @@ -72,11 +75,15 @@ const Chart = memo( showDownloadIcons = false, iconStyles, downloadFilenamePrefix = [], + units, + yAxisLabel, }: ChartProps) => { const { t } = useSafeTranslation(); const classes = useStyles(); const chartRef = React.useRef(null); const isEWSChart = !!data.EWSConfig; + const isGoogleFloodChart = !!data.GoogleFloodConfig; + const isFloodChart = isEWSChart || isGoogleFloodChart; const downloadFilename = buildCsvFileName([ ...downloadFilenamePrefix, @@ -149,11 +156,19 @@ const Chart = memo( backgroundColor: colors[i], borderColor: colors[i], borderWidth: 2, - pointRadius: isEWSChart ? 0 : 1, // Disable point rendering for EWS only. + pointRadius: isFloodChart ? 0 : 1, // Disable point rendering for flood charts only. data: indices.map(index => (row[index] as number) || null), pointHitRadius: 10, })), - [colors, config.category, config.fill, indices, isEWSChart, t, tableRows], + [ + colors, + config.category, + config.fill, + indices, + isFloodChart, + t, + tableRows, + ], ); const configureIndicePointRadius = useCallback( @@ -165,9 +180,9 @@ const Chart = memo( if (foundDataSetFieldPointRadius !== undefined) { return foundDataSetFieldPointRadius; } - return isEWSChart ? 0 : 1; // Disable point rendering for EWS only. + return isFloodChart ? 0 : 1; // Disable point rendering for flood charts only. }, - [isEWSChart, datasetFields, header], + [isFloodChart, datasetFields, header], ); // The indicesDataSet @@ -178,7 +193,7 @@ const Chart = memo( fill: config.fill || false, backgroundColor: colors[i], borderColor: colors[i], - borderWidth: 2, + borderWidth: 4, data: tableRows.map(row => (row[indiceKey] as number) || null), pointRadius: configureIndicePointRadius(indiceKey), pointHitRadius: 10, @@ -194,7 +209,7 @@ const Chart = memo( ], ); - const EWSthresholds = useMemo(() => { + const floodThresholds = useMemo(() => { if (data.EWSConfig) { return Object.values(data.EWSConfig).map(obj => ({ label: obj.label, @@ -208,8 +223,21 @@ const Chart = memo( fill: false, })); } + if (data.GoogleFloodConfig) { + return Object.values(data.GoogleFloodConfig).map(obj => ({ + label: obj.label, + backgroundColor: obj.color, + borderColor: obj.color, + borderWidth: 2, + pointRadius: 0, + pointHitRadius: 10, + // Deep copy is needed: https://github.com/reactchartjs/react-chartjs-2/issues/524#issuecomment-722814079 + data: [...obj.values], + fill: false, + })); + } return []; - }, [data.EWSConfig]); + }, [data.EWSConfig, data.GoogleFloodConfig]); /** * The following value assumes that the data is formatted as follows: @@ -237,22 +265,66 @@ const Chart = memo( * using config.transpose = true. * - fill */ - const datasets = !transpose ? tableRowsDataSet : indicesDataSet; - const datasetsWithThresholds = [...datasets, ...EWSthresholds]; - const datasetsTrimmed = datasetsWithThresholds.map(set => ({ - ...set, - data: set.data.slice(chartRange[0], chartRange[1]), - })); + const today = useMemo(() => { + const date = new Date(); + date.setHours(0, 0, 0, 0); + return date; + }, []); - const chartData = React.useMemo( - () => ({ - labels, - datasets: datasetsTrimmed, - }), - [datasetsTrimmed, labels], + const parseDateString = (dateString: string) => { + const [year, month, day] = dateString.split('-').map(Number); + const date = new Date(year, month - 1, day); + date.setHours(0, 0, 0, 0); + return date; + }; + + const isFutureDate = useCallback( + (dateString: string) => parseDateString(dateString) >= today, + [today], + ); + const isPastDate = useCallback( + (dateString: string) => parseDateString(dateString) <= today, + [today], ); + const datasets = !transpose ? tableRowsDataSet : indicesDataSet; + const chartData = React.useMemo(() => { + if (isGoogleFloodChart) { + const pastDatasets = datasets.map(dataset => ({ + ...dataset, + data: dataset.data.map((point, index) => + isPastDate(labels[index] as string) ? point : null, + ), + borderDash: 0, + })); + const futureDatasets = datasets.map(dataset => ({ + ...dataset, + label: t(`${dataset.label} (Future)`), + data: dataset.data.map((point, index) => + isFutureDate(labels[index] as string) ? point : null, + ), + borderDash: [5, 5], + })); + return { + labels, + datasets: [...pastDatasets, ...futureDatasets, ...floodThresholds], + }; + } + return { + labels, + datasets: [...datasets, ...floodThresholds], + }; + }, [ + isGoogleFloodChart, + labels, + datasets, + floodThresholds, + isPastDate, + t, + isFutureDate, + ]); + const chartConfig = useMemo( () => ({ @@ -281,6 +353,8 @@ const Chart = memo( scaleLabel: { labelString: xAxisLabel, display: true, + lineHeight: 1.5, + fontColor: '#AAA', }, } : {}), @@ -292,32 +366,122 @@ const Chart = memo( fontColor: '#CCC', ...(config?.minValue && { suggestedMin: config?.minValue }), ...(config?.maxValue && { suggestedMax: config?.maxValue }), + maxTicksLimit: 8, + callback: (value: string) => + `${value}${units ? ` ${units}` : ''}`, }, stacked: config?.stacked ?? false, gridLines: { display: false, }, + afterDataLimits: axis => { + // Increase y-axis by 20% for Google Flood charts to make space for the annotation label + if (isGoogleFloodChart) { + const range = axis.max - axis.min; + axis.max += range * 0.25; // eslint-disable-line no-param-reassign, fp/no-mutation + } + }, + ...(yAxisLabel + ? { + scaleLabel: { + display: true, + labelString: yAxisLabel, + lineHeight: 1.5, + fontColor: '#AAA', + }, + } + : {}), }, ], }, - // display values for all datasets in the tooltip tooltips: { mode: 'index', + callbacks: { + label: (tooltipItem, labelData) => { + const datasetLabel = + labelData.datasets?.[tooltipItem.datasetIndex as number] + ?.label || ''; + const value = tooltipItem.yLabel; + const unitLabel = units ? ` ${units}` : ''; + + // Get the data point for the current tooltip item + const dataPoint = + labelData.datasets?.[tooltipItem.datasetIndex as number] + ?.data?.[tooltipItem.index as number]; + + // Check if any label is present in the tooltip + const labelPresent = labelData.datasets?.some(dataset => { + const { label } = dataset; + if (tooltipItem.index !== undefined) { + const indexData = dataset.data?.[tooltipItem.index]; + return ( + label === datasetLabel.replace(' (Future)', '') && + indexData !== null + ); + } + return false; + }); + + // Hide "{label} (Future)" if "{label}" is present + if (labelPresent && datasetLabel.includes(' (Future)')) { + return null; + } + + // Only show labels with non-null data points + if (dataPoint !== null) { + return `${datasetLabel}: ${value}${unitLabel}`; + } + + return null; + }, + }, }, legend: { display: config.displayLegend, position: legendAtBottom ? 'bottom' : 'right', labels: { boxWidth: 12, boxHeight: 12 }, }, + ...(isGoogleFloodChart + ? { + annotation: { + annotations: [ + { + type: 'line', + mode: 'vertical', + scaleID: 'x-axis-0', + value: today.toISOString().split('T')[0], + borderColor: 'rgba(255, 255, 255, 0.8)', + borderWidth: 2, + label: { + content: t('Today'), + enabled: true, + position: 'top', + yAdjust: -6, + fontColor: '#CCC', + fontSize: 10, + }, + }, + ], + }, + } + : {}), }) as ChartOptions, [ - config, - isEWSChart, - legendAtBottom, notMaintainAspectRatio, - title, subtitle, + title, + config?.stacked, + config?.minValue, + config?.maxValue, + config.displayLegend, xAxisLabel, + legendAtBottom, + isGoogleFloodChart, + today, + t, + isEWSChart, + units, + yAxisLabel, ], ); diff --git a/frontend/src/components/MapView/Layers/PointDataLayer/index.tsx b/frontend/src/components/MapView/Layers/PointDataLayer/index.tsx index 1fcfb1ccd..b0ab8b458 100644 --- a/frontend/src/components/MapView/Layers/PointDataLayer/index.tsx +++ b/frontend/src/components/MapView/Layers/PointDataLayer/index.tsx @@ -27,7 +27,11 @@ import { fillPaintCategorical, fillPaintData, } from 'components/MapView/Layers/styles'; -import { setEWSParams, clearDataset } from 'context/datasetStateSlice'; +import { + setEWSParams, + setGoogleFloodParams, + clearDataset, +} from 'context/datasetStateSlice'; import { createEWSDatasetParams } from 'utils/ews-utils'; import { addPopupParams } from 'components/MapView/Layers/layer-utils'; import { @@ -38,6 +42,7 @@ import { import { findFeature, getLayerMapId, useMapCallback } from 'utils/map-utils'; import { getFormattedDate } from 'utils/date-utils'; import { geoToH3, h3ToGeoBoundary } from 'h3-js'; +import { createGoogleFloodDatasetParams } from 'utils/google-flood-utils'; const onClick = ({ layer, dispatch, t }: MapEventWrapFunctionProps) => @@ -57,6 +62,18 @@ const onClick = ); dispatch(setEWSParams(ewsDatasetParams)); } + if (layer.loader === PointDataLoader.GOOGLE_FLOOD && layer.detailUrl) { + dispatch(clearDataset()); + if (!feature?.properties) { + return; + } + const googleFloodDatasetParams = createGoogleFloodDatasetParams( + feature?.properties, + layer.detailUrl, + layer.featureInfoTitle, + ); + dispatch(setGoogleFloodParams(googleFloodDatasetParams)); + } }; // Point Data, takes any GeoJSON of points and shows it. diff --git a/frontend/src/components/MapView/MapTooltip/PointDataChart/PopupPointDataChart.tsx b/frontend/src/components/MapView/MapTooltip/PointDataChart/PopupPointDataChart.tsx index be44e7acd..5ed35a3f4 100644 --- a/frontend/src/components/MapView/MapTooltip/PointDataChart/PopupPointDataChart.tsx +++ b/frontend/src/components/MapView/MapTooltip/PointDataChart/PopupPointDataChart.tsx @@ -1,5 +1,5 @@ import Chart from 'components/Common/Chart'; -import { isAdminBoundary } from 'components/MapView/utils'; + import { ChartConfig } from 'config/types'; import { CHART_DATA_PREFIXES, @@ -9,6 +9,8 @@ import { t } from 'i18next'; import { memo } from 'react'; import { useSelector } from 'react-redux'; import { createStyles, makeStyles } from '@material-ui/core'; +import { isAdminBoundary } from 'utils/admin-utils'; +import { GoogleFloodParams } from 'utils/google-flood-utils'; const useStyles = makeStyles(() => createStyles({ @@ -16,7 +18,7 @@ const useStyles = makeStyles(() => display: 'flex', flexDirection: 'column', gap: '8px', - paddingTop: '20px', // leave room for the close icon + paddingTop: '8px', // leave room for the close icon }, chartSection: { paddingTop: '16px', // leave room for the download icons @@ -47,20 +49,25 @@ const PopupPointDataChart = memo(() => { return null; } + const xAxisLabel = isAdminBoundary(datasetParams) + ? undefined + : t('Timestamps reflect local time in region'); + const yAxisLabel = (datasetParams as GoogleFloodParams).yAxisLabel + ? t((datasetParams as GoogleFloodParams).yAxisLabel) + : undefined; + return (
diff --git a/frontend/src/components/MapView/MapTooltip/PointDataChart/usePointDataChart.tsx b/frontend/src/components/MapView/MapTooltip/PointDataChart/usePointDataChart.tsx index 55ccf3328..6ff9930ea 100644 --- a/frontend/src/components/MapView/MapTooltip/PointDataChart/usePointDataChart.tsx +++ b/frontend/src/components/MapView/MapTooltip/PointDataChart/usePointDataChart.tsx @@ -7,7 +7,11 @@ import { dateRangeSelector } from 'context/mapStateSlice/selectors'; import { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { appConfig } from 'config'; -import { isAdminBoundary } from '../../utils'; +import { + GoogleFloodParams, + isGoogleFloodDatasetParams, +} from 'utils/google-flood-utils'; +import { isAdminBoundary } from 'utils/admin-utils'; const usePointDataChart = () => { const dispatch = useDispatch(); @@ -19,31 +23,34 @@ const usePointDataChart = () => { const { startDate: selectedDate } = useSelector(dateRangeSelector); useEffect(() => { - if (!datasetParams || !selectedDate) { - return; - } + if (datasetParams && selectedDate) { + if (isAdminBoundary(datasetParams)) { + const { code: adminCode, level } = + datasetParams.boundaryProps[datasetParams.id]; + const requestParams: DatasetRequestParams = { + id: datasetParams.id, + level, + adminCode: adminCode || appConfig.countryAdmin0Id, + boundaryProps: datasetParams.boundaryProps, + url: datasetParams.url, + serverLayerName: datasetParams.serverLayerName, + datasetFields: datasetParams.datasetFields, + }; + dispatch(loadDataset(requestParams)); + } else { + if (isGoogleFloodDatasetParams(datasetParams as GoogleFloodParams)) { + const requestParams = datasetParams as GoogleFloodParams; + dispatch(loadDataset(requestParams)); + return; + } - if (isAdminBoundary(datasetParams)) { - const { code: adminCode, level } = - datasetParams.boundaryProps[datasetParams.id]; - const requestParams: DatasetRequestParams = { - id: datasetParams.id, - level, - adminCode: adminCode || appConfig.countryAdmin0Id, - boundaryProps: datasetParams.boundaryProps, - url: datasetParams.url, - serverLayerName: datasetParams.serverLayerName, - datasetFields: datasetParams.datasetFields, - }; - dispatch(loadDataset(requestParams)); - } else { - const requestParams: DatasetRequestParams = { - date: selectedDate, - externalId: datasetParams.externalId, - triggerLevels: datasetParams.triggerLevels, - baseUrl: datasetParams.baseUrl, - }; - dispatch(loadDataset(requestParams)); + // Assumes EWSDataset + const requestParams: DatasetRequestParams = { + date: selectedDate, + ...datasetParams, + }; + dispatch(loadDataset(requestParams)); + } } }, [datasetParams, dispatch, selectedDate]); diff --git a/frontend/src/components/MapView/utils.ts b/frontend/src/components/MapView/utils.ts index 94c870eeb..21efa2c2c 100644 --- a/frontend/src/components/MapView/utils.ts +++ b/frontend/src/components/MapView/utils.ts @@ -20,9 +20,9 @@ import { addNotification } from 'context/notificationStateSlice'; import { LocalError } from 'utils/error-utils'; import { Column, quoteAndEscapeCell } from 'utils/analysis-utils'; import { TableRow } from 'context/analysisResultStateSlice'; -import { AdminBoundaryParams, EWSParams } from 'context/datasetStateSlice'; import { MapRef, Point } from 'react-map-gl/maplibre'; import { PopupData } from 'context/tooltipStateSlice'; +import { getTitle } from 'utils/title-utils'; import { getExtent } from './Layers/raster-utils'; // TODO: maplibre: fix feature @@ -118,31 +118,6 @@ const sortKeys = (featureInfoProps: FeatureInfoObject): string[][] => { return [dataKeys, metaDataKeys]; }; -const getTitle = ( - featureInfoTitle: FeatureTitleObject | undefined, - properties: any, -): PopupData | {} => { - if (!featureInfoTitle) { - return {}; - } - const titleField = Object.keys(featureInfoTitle).find( - (field: string) => - featureInfoTitle[field].visibility !== FeatureInfoVisibility.IfDefined || - !!properties[field], - ); - return titleField - ? { - title: { - prop: titleField, - data: featureInfoTitle[titleField].template, - context: { - [titleField]: properties[titleField], - }, - }, - } - : {}; -}; - const getMetaData = ( featureInfoProps: FeatureInfoObject, metaDataKeys: string[], @@ -342,8 +317,3 @@ export const getExposureAnalysisTableData = ( sortColumn: Column['id'], sortOrder: 'asc' | 'desc', ) => orderBy(tableData, sortColumn, sortOrder); - -export const isAdminBoundary = ( - params: AdminBoundaryParams | EWSParams, -): params is AdminBoundaryParams => - (params as AdminBoundaryParams).id !== undefined; diff --git a/frontend/src/config/cambodia/layers.json b/frontend/src/config/cambodia/layers.json index a1fb36d55..1df88745c 100644 --- a/frontend/src/config/cambodia/layers.json +++ b/frontend/src/config/cambodia/layers.json @@ -1991,9 +1991,11 @@ }, "google_flood_status_at_gauges": { "title": "Current Flood Status (Google AI)", + "loader": "google_flood", "type": "point_data", "hex_display": false, "data": "https://prism-api.ovio.org/google-floods/gauges/?region_codes=KH", + "detail_url": "https://prism-api.ovio.org/google-floods/gauges/forecasts", "data_field": "severity", "data_field_type": "text", "date_url": "https://prism-api.ovio.org/google-floods/dates/?region_codes=KH", @@ -2004,7 +2006,7 @@ { "label": "Danger", "value": "SEVERE", "color": "#ea250a" }, { "label": "Warning", "value": "ABOVE_NORMAL", "color": "#fba705" }, { "label": "Normal", "value": "NO_FLOODING", "color": "#089180" }, - { "label": "Unknown", "value": "UNKNOWN", "color": "#858585" } + { "label": "No data", "value": "UNKNOWN", "color": "#858585" } ], "feature_info_title": { "siteName": { @@ -2042,7 +2044,7 @@ "SEVERE": "Danger", "ABOVE_NORMAL": "Warning", "NO_FLOODING": "Normal", - "UNKNOWN": "Unknown" + "UNKNOWN": "No data" } }, "gaugeId": { diff --git a/frontend/src/config/cambodia/translation.json b/frontend/src/config/cambodia/translation.json index 713ade12a..4e443ef1a 100644 --- a/frontend/src/config/cambodia/translation.json +++ b/frontend/src/config/cambodia/translation.json @@ -108,7 +108,7 @@ "3 - commune": "3 - ឃុំ", "Commune": "ឃុំ", "Number of people affected": "ចំនួនមនុស្ស", - "Timestamps reflect local time in Cambodia": "ត្រាពេលវេលាឆ្លុះបញ្ចាំងម៉ោងក្នុងស្រុកនៅកម្ពុជា", + "Timestamps reflect local time in region": "ត្រាពេលវេលាឆ្លុះបញ្ចាំងម៉ោងក្នុងស្រុកនៅកម្ពុជា", "EWS 1294 river level data": "EWS 1294 ទិន្នន័យកម្រិតទន្លេ", "Mean water level": "កម្រិតទឹកជាមធ្យម", "Max water level": "កម្រិតទឹកអតិបរមា", diff --git a/frontend/src/config/mozambique/layers.json b/frontend/src/config/mozambique/layers.json index cc2e9926b..bb6d23cac 100644 --- a/frontend/src/config/mozambique/layers.json +++ b/frontend/src/config/mozambique/layers.json @@ -2948,9 +2948,11 @@ }, "google_flood_status_at_gauges": { "title": "Current Flood Status (Google AI)", + "loader": "google_flood", "type": "point_data", "hex_display": false, - "data": "https://prism-api.ovio.org/google-floods/gauges/?region_codes=MZ", + "data": "http://prism-api.ovio.org/google-floods/gauges/?region_codes=MZ", + "detail_url": "http://prism-api.ovio.org/google-floods/gauges/forecasts", "data_field": "severity", "data_field_type": "text", "date_url": "https://prism-api.ovio.org/google-floods/dates/?region_codes=MZ", @@ -2961,7 +2963,7 @@ { "label": "Danger", "value": "SEVERE", "color": "#ea250a" }, { "label": "Warning", "value": "ABOVE_NORMAL", "color": "#fba705" }, { "label": "Normal", "value": "NO_FLOODING", "color": "#089180" }, - { "label": "Unknown", "value": "UNKNOWN", "color": "#858585" } + { "label": "No data", "value": "UNKNOWN", "color": "#858585" } ], "feature_info_title": { "siteName": { @@ -2999,7 +3001,7 @@ "SEVERE": "Danger", "ABOVE_NORMAL": "Warning", "NO_FLOODING": "Normal", - "UNKNOWN": "Unknown" + "UNKNOWN": "No data" } }, "gaugeId": { diff --git a/frontend/src/config/rbd/layers.json b/frontend/src/config/rbd/layers.json index 10bc6753d..ab01c4807 100644 --- a/frontend/src/config/rbd/layers.json +++ b/frontend/src/config/rbd/layers.json @@ -6535,8 +6535,10 @@ "google_flood_status_at_gauges": { "title": "Current Flood Status (Google AI)", "type": "point_data", + "loader": "google_flood", "hex_display": false, - "data": "https://prism-api.ovio.org/google-floods/gauges/?region_codes=BF®ion_codes=CM®ion_codes=TD®ion_codes=GH®ion_codes=ML®ion_codes=MR®ion_codes=NE®ion_codes=SL®ion_codes=CI®ion_codes=GN®ion_codes=SN®ion_codes=GM®ion_codes=GW®ion_codes=LR®ion_codes=TG®ion_codes=BJ®ion_codes=NG®ion_codes=CF", + "data": "http://prism-api.ovio.org/google-floods/gauges/?region_codes=BF®ion_codes=CM®ion_codes=TD®ion_codes=GH®ion_codes=ML®ion_codes=MR®ion_codes=NE®ion_codes=SL®ion_codes=CI®ion_codes=GN®ion_codes=SN®ion_codes=GM®ion_codes=GW®ion_codes=LR®ion_codes=TG®ion_codes=BJ®ion_codes=NG®ion_codes=CF", + "detail_url": "http://prism-api.ovio.org/google-floods/gauges/forecasts", "data_field": "severity", "data_field_type": "text", "date_url": "https://prism-api.ovio.org/google-floods/dates/?region_codes=BF®ion_codes=CM®ion_codes=TD®ion_codes=GH®ion_codes=ML®ion_codes=MR®ion_codes=NE®ion_codes=SL®ion_codes=CI®ion_codes=GN®ion_codes=SN®ion_codes=GM®ion_codes=GW®ion_codes=LR®ion_codes=TG®ion_codes=BJ®ion_codes=NG®ion_codes=CF", @@ -6547,7 +6549,7 @@ { "label": "Danger", "value": "SEVERE", "color": "#ea250a" }, { "label": "Warning", "value": "ABOVE_NORMAL", "color": "#fba705" }, { "label": "Normal", "value": "NO_FLOODING", "color": "#089180" }, - { "label": "Unknown", "value": "UNKNOWN", "color": "#858585" } + { "label": "No data", "value": "UNKNOWN", "color": "#858585" } ], "feature_info_title": { "siteName": { @@ -6585,7 +6587,7 @@ "SEVERE": "Danger", "ABOVE_NORMAL": "Warning", "NO_FLOODING": "Normal", - "UNKNOWN": "Unknown" + "UNKNOWN": "No data" } }, "gaugeId": { diff --git a/frontend/src/config/shared/translation/english.json b/frontend/src/config/shared/translation/english.json index 651ad40b4..22d042ff1 100644 --- a/frontend/src/config/shared/translation/english.json +++ b/frontend/src/config/shared/translation/english.json @@ -114,7 +114,7 @@ "The following layer requires authentication": "The following layer requires authentication", "Threshold": "Threshold", "Timeline": "Timeline", - "Timestamps reflect local time in Cambodia": "Timestamps reflect local time in Cambodia", + "Timestamps reflect local time in region": "Timestamps reflect local time in region", "Title": "Title", "Today": "Today", "trig.": "trig.", diff --git a/frontend/src/config/shared/translation/khmer.json b/frontend/src/config/shared/translation/khmer.json index 713ade12a..4e443ef1a 100644 --- a/frontend/src/config/shared/translation/khmer.json +++ b/frontend/src/config/shared/translation/khmer.json @@ -108,7 +108,7 @@ "3 - commune": "3 - ឃុំ", "Commune": "ឃុំ", "Number of people affected": "ចំនួនមនុស្ស", - "Timestamps reflect local time in Cambodia": "ត្រាពេលវេលាឆ្លុះបញ្ចាំងម៉ោងក្នុងស្រុកនៅកម្ពុជា", + "Timestamps reflect local time in region": "ត្រាពេលវេលាឆ្លុះបញ្ចាំងម៉ោងក្នុងស្រុកនៅកម្ពុជា", "EWS 1294 river level data": "EWS 1294 ទិន្នន័យកម្រិតទន្លេ", "Mean water level": "កម្រិតទឹកជាមធ្យម", "Max water level": "កម្រិតទឹកអតិបរមា", diff --git a/frontend/src/config/types.ts b/frontend/src/config/types.ts index 508949c9a..69d91994d 100644 --- a/frontend/src/config/types.ts +++ b/frontend/src/config/types.ts @@ -680,6 +680,7 @@ export class ImpactLayerProps extends CommonLayerProps { export enum PointDataLoader { EWS = 'ews', ACLED = 'acled', + GOOGLE_FLOOD = 'google_flood', } export class PointDataLayerProps extends CommonLayerProps { @@ -734,6 +735,9 @@ export class PointDataLayerProps extends CommonLayerProps { @optional dataFieldType?: DataFieldType = DataFieldType.NUMBER; + + @optional + detailUrl?: string; } export type RequiredKeys = { @@ -881,7 +885,7 @@ type AdminLevelDisplayType = { export type PointData = { lat: number; lon: number; - date: number; // in unix time. + date?: number; // in unix time. [key: string]: any; }; diff --git a/frontend/src/context/datasetStateSlice.ts b/frontend/src/context/datasetStateSlice.ts index a440b5ea5..c2fdcff44 100644 --- a/frontend/src/context/datasetStateSlice.ts +++ b/frontend/src/context/datasetStateSlice.ts @@ -10,6 +10,11 @@ import { } from 'utils/ews-utils'; import { fetchWithTimeout } from 'utils/fetch-with-timeout'; import { getFormattedDate, getTimeInMilliseconds } from 'utils/date-utils'; +import { + FloodSensorData, + GoogleFloodParams, + GoogleFloodTriggersConfig, +} from 'utils/google-flood-utils'; import type { CreateAsyncThunkTypes, RootState } from './store'; import { TableData } from './tableStateSlice'; @@ -32,7 +37,7 @@ type EWSDataPointsRequestParams = EWSParams & { type DatasetState = { data?: TableData; isLoading: boolean; - datasetParams?: AdminBoundaryParams | EWSParams; + datasetParams?: AdminBoundaryParams | EWSParams | GoogleFloodParams; chartType: ChartType; title: string; }; @@ -69,7 +74,8 @@ export type AdminBoundaryRequestParams = AdminBoundaryParams & { export type DatasetRequestParams = | AdminBoundaryRequestParams - | EWSDataPointsRequestParams; + | EWSDataPointsRequestParams + | GoogleFloodParams; type DataItem = { date: number; @@ -169,6 +175,63 @@ export const loadEWSDataset = async ( }); }; +export const loadGoogleFloodDataset = async ( + params: GoogleFloodParams, + dispatch: Dispatch, +): Promise => { + const { gaugeId, triggerLevels, detailUrl } = params; + + const url = `${detailUrl}?gauge_ids=${gaugeId}`; + + let dataPoints: { [key: string]: FloodSensorData[] } = {}; + try { + const resp = await fetchWithTimeout( + url, + dispatch, + {}, + `Request failed for fetching Google Flood data points by location at ${url}`, + ); + // eslint-disable-next-line fp/no-mutation + dataPoints = await resp.json(); + } catch (error) { + console.error(error); + } + + const results: DataItem[] = dataPoints[gaugeId].map(item => { + const [measureDate, value] = item.value; + // offset back from UTC to local time so that the date is displayed correctly + // i.e. in Cambodia Time as it is received. + const offset = new Date().getTimezoneOffset(); + return { + date: getTimeInMilliseconds(measureDate) - offset * 60 * 1000, + values: { Measure: value.toString() }, + }; + }); + + const tableData = createTableData(results, TableDataFormat.DATE); + + const GoogleFloodConfig = Object.entries(triggerLevels).reduce( + (acc, [key, value]) => { + const obj = { + ...GoogleFloodTriggersConfig[key], + values: tableData.rows.map(() => value), + }; + + return { ...acc, [key]: obj }; + }, + {}, + ); + + const tableDataWithGoogleFloodConfig: TableData = { + ...tableData, + GoogleFloodConfig, + }; + + return new Promise(resolve => { + resolve(tableDataWithGoogleFloodConfig); + }); +}; + type HDCResponse = { data: { [key: string]: number[] }; date: string[]; @@ -282,10 +345,18 @@ export const loadDataset = createAsyncThunk< CreateAsyncThunkTypes >( 'datasetState/loadDataset', - async (params: DatasetRequestParams, { dispatch }) => - (params as AdminBoundaryRequestParams).id - ? loadAdminBoundaryDataset(params as AdminBoundaryRequestParams, dispatch) - : loadEWSDataset(params as EWSDataPointsRequestParams, dispatch), + async (params: DatasetRequestParams, { dispatch }) => { + if ((params as AdminBoundaryRequestParams).id) { + return loadAdminBoundaryDataset( + params as AdminBoundaryRequestParams, + dispatch, + ); + } + if ((params as EWSDataPointsRequestParams).date) { + return loadEWSDataset(params as EWSDataPointsRequestParams, dispatch); + } + return loadGoogleFloodDataset(params as GoogleFloodParams, dispatch); + }, ); export const datasetResultStateSlice = createSlice({ @@ -332,6 +403,32 @@ export const datasetResultStateSlice = createSlice({ title: chartTitle, }; }, + setGoogleFloodParams: ( + state, + { payload }: PayloadAction, + ): DatasetState => { + const { + gaugeId, + triggerLevels, + detailUrl, + chartTitle, + unit, + yAxisLabel, + } = payload; + + return { + ...state, + datasetParams: { + gaugeId, + triggerLevels, + chartTitle, + detailUrl, + unit, + yAxisLabel, + }, + title: chartTitle, + }; + }, }, extraReducers: builder => { builder.addCase( @@ -369,6 +466,7 @@ export const { setDatasetTitle, setDatasetChartType, setEWSParams, + setGoogleFloodParams, } = datasetResultStateSlice.actions; export default datasetResultStateSlice.reducer; diff --git a/frontend/src/context/tableStateSlice.ts b/frontend/src/context/tableStateSlice.ts index e2d2ddb81..3690dca72 100644 --- a/frontend/src/context/tableStateSlice.ts +++ b/frontend/src/context/tableStateSlice.ts @@ -2,14 +2,30 @@ import { createSlice, PayloadAction, createAsyncThunk } from '@reduxjs/toolkit'; import * as Papa from 'papaparse'; import { TableType } from 'config/types'; import { TableDefinitions } from 'config/utils'; -import { EWSChartItemsObject } from 'utils/ews-utils'; import type { CreateAsyncThunkTypes, RootState } from './store'; export type TableRowType = { [key: string]: string | number }; + +type FloodChartConfig = { + label: string; + color: string; +}; + +type FloodChartItem = FloodChartConfig & { values: number[] }; + +export type FloodChartConfigObject = { + [key: string]: FloodChartConfig; +}; + +type FloodChartItemsObject = { + [key: string]: FloodChartItem; +}; + export type TableData = { columns: string[]; rows: TableRowType[]; - EWSConfig?: EWSChartItemsObject; + EWSConfig?: FloodChartItemsObject; + GoogleFloodConfig?: FloodChartItemsObject; }; type TableState = { diff --git a/frontend/src/utils/admin-utils.ts b/frontend/src/utils/admin-utils.ts index 3310d2950..c978a99d1 100644 --- a/frontend/src/utils/admin-utils.ts +++ b/frontend/src/utils/admin-utils.ts @@ -10,8 +10,9 @@ import { getBoundaryLayersByAdminLevel, getDisplayBoundaryLayers, } from 'config/utils'; -import { AdminBoundaryParams } from 'context/datasetStateSlice'; +import { AdminBoundaryParams, EWSParams } from 'context/datasetStateSlice'; import { CHART_API_URL } from 'utils/constants'; +import { GoogleFloodParams } from './google-flood-utils'; const { multiCountry } = appConfig; const MAX_ADMIN_LEVEL = multiCountry ? 3 : 2; @@ -89,3 +90,8 @@ export const getChartAdminBoundaryParams = ( return adminBoundaryParams; }; + +export const isAdminBoundary = ( + params: AdminBoundaryParams | EWSParams | GoogleFloodParams, +): params is AdminBoundaryParams => + (params as AdminBoundaryParams).id !== undefined; diff --git a/frontend/src/utils/ews-utils.ts b/frontend/src/utils/ews-utils.ts index 53a90b4ad..d166d6527 100644 --- a/frontend/src/utils/ews-utils.ts +++ b/frontend/src/utils/ews-utils.ts @@ -2,35 +2,26 @@ import GeoJSON, { FeatureCollection, Point } from 'geojson'; import { Dispatch } from 'redux'; import { PointData, PointLayerData } from 'config/types'; import { oneDayInMs } from 'components/MapView/LeftPanel/utils'; +import { FloodChartConfigObject } from 'context/tableStateSlice'; import { fetchWithTimeout } from './fetch-with-timeout'; import { getFormattedDate } from './date-utils'; import { DateFormat } from './name-utils'; -type EWSChartConfig = { - label: string; - color: string; -}; - -type EWSChartItem = EWSChartConfig & { values: number[] }; - -export type EWSChartConfigObject = { [key: string]: EWSChartConfig }; -export type EWSChartItemsObject = { [key: string]: EWSChartItem }; - -export const EWSTriggersConfig: EWSChartConfigObject = { +export const EWSTriggersConfig: FloodChartConfigObject = { normal: { - label: 'normal', + label: 'Normal', color: '#1a9641', }, watchLevel: { - label: 'watch level', + label: 'Watch level', color: '#f9d84e', }, warning: { - label: 'warning', + label: 'Warning', color: '#fdae61', }, severeWarning: { - label: 'severe warning', + label: 'Severe warning', color: '#e34a33', }, }; diff --git a/frontend/src/utils/fetch-with-timeout.ts b/frontend/src/utils/fetch-with-timeout.ts index f5172e155..ae8718ce0 100644 --- a/frontend/src/utils/fetch-with-timeout.ts +++ b/frontend/src/utils/fetch-with-timeout.ts @@ -8,7 +8,7 @@ interface FetchWithTimeoutOptions extends RequestInit { export const ANALYSIS_REQUEST_TIMEOUT = 60000; -const DEFAULT_REQUEST_TIMEOUT = 15000; +const DEFAULT_REQUEST_TIMEOUT = 30000; export const fetchWithTimeout = async ( resource: RequestInfo, diff --git a/frontend/src/utils/google-flood-utils.ts b/frontend/src/utils/google-flood-utils.ts new file mode 100644 index 000000000..2845cb233 --- /dev/null +++ b/frontend/src/utils/google-flood-utils.ts @@ -0,0 +1,123 @@ +import { oneDayInMs } from 'components/MapView/LeftPanel/utils'; +import { getTitle } from 'utils/title-utils'; +import { FeatureTitleObject } from 'config/types'; +import { PopupData } from 'context/tooltipStateSlice'; +import { FloodChartConfigObject } from 'context/tableStateSlice'; +import { t } from 'i18next'; + +export type GoogleFloodParams = { + gaugeId: string; + triggerLevels: GoogleFloodTriggerLevels; + detailUrl: string; + chartTitle: string; + unit: string; + yAxisLabel: string; +}; + +const GOOGLE_FLOOD_UNITS = { + GAUGE_VALUE_UNIT_UNSPECIFIED: '', + METERS: 'm', + CUBIC_METERS_PER_SECOND: 'm³/s', +}; + +const GOOGLE_FLOOD_Y_AXIS_LABEL = { + GAUGE_VALUE_UNIT_UNSPECIFIED: '', + METERS: 'Unit = water depth in m', + CUBIC_METERS_PER_SECOND: 'Unit = discharge in m³/s', +}; + +export const GoogleFloodTriggersConfig: FloodChartConfigObject = { + normal: { + label: 'Normal', + color: '#1a9641', + }, + warning: { + label: 'Warning', + color: '#f9d84e', + }, + danger: { + label: 'Danger', + color: '#fdae61', + }, + extremeDanger: { + label: 'Extreme danger', + color: '#e34a33', + }, +}; + +/* eslint-disable camelcase */ +export type FloodSensorData = { + location_id: number; + value: [string, number]; +}; + +type GoogleFloodTriggerLevels = { + warning: number; + danger: number; + extremeDanger: number; +}; +/* eslint-enable camelcase */ + +// input parameter is used here only for testing +export const createGoogleFloodDatesArray = (testEndDate?: number): number[] => { + const datesArray = []; + + const now = new Date(); + + const endDate = testEndDate + ? new Date(testEndDate).setUTCHours(12, 0, 0, 0) + : now.setUTCHours(12, 0, 0, 0); + + const tempDate = new Date('2021-01-01'); + tempDate.setUTCHours(12, 0, 0, 0); + + while (tempDate.getTime() <= endDate) { + // eslint-disable-next-line fp/no-mutating-methods + datesArray.push(tempDate.getTime()); + + tempDate.setTime(tempDate.getTime() + oneDayInMs); + } + + return datesArray; +}; + +export const createGoogleFloodDatasetParams = ( + featureProperties: any, + detailUrl: string, + featureInfoTitle?: FeatureTitleObject, +): GoogleFloodParams => { + const { gaugeId, thresholds, gaugeValueUnit } = featureProperties; + const chartTitle = + t( + (getTitle(featureInfoTitle, featureProperties) as PopupData)?.title + .data as string, + featureProperties, + ) || featureProperties.gaugeId; + + const parsedLevels = JSON.parse(thresholds); + const triggerLevels = { + warning: parsedLevels.warningLevel.toFixed(2), + danger: parsedLevels.dangerLevel.toFixed(2), + extremeDanger: parsedLevels.extremeDangerLevel.toFixed(2), + }; + const unit = + GOOGLE_FLOOD_UNITS[gaugeValueUnit as keyof typeof GOOGLE_FLOOD_UNITS]; + const yAxisLabel = t( + GOOGLE_FLOOD_Y_AXIS_LABEL[ + gaugeValueUnit as keyof typeof GOOGLE_FLOOD_Y_AXIS_LABEL + ], + ); + + return { + gaugeId, + triggerLevels, + chartTitle, + detailUrl, + unit: t(unit), + yAxisLabel: t(yAxisLabel), + }; +}; + +export const isGoogleFloodDatasetParams = ( + params: GoogleFloodParams, +): params is GoogleFloodParams => params.gaugeId !== undefined; diff --git a/frontend/src/utils/title-utils.ts b/frontend/src/utils/title-utils.ts new file mode 100644 index 000000000..c79145c93 --- /dev/null +++ b/frontend/src/utils/title-utils.ts @@ -0,0 +1,27 @@ +import { FeatureInfoVisibility, FeatureTitleObject } from 'config/types'; +import { PopupData } from 'context/tooltipStateSlice'; + +export const getTitle = ( + featureInfoTitle: FeatureTitleObject | undefined, + properties: any, +): PopupData | {} => { + if (!featureInfoTitle) { + return {}; + } + const titleField = Object.keys(featureInfoTitle).find( + (field: string) => + featureInfoTitle[field].visibility !== FeatureInfoVisibility.IfDefined || + !!properties[field], + ); + return titleField + ? { + title: { + prop: titleField, + data: featureInfoTitle[titleField].template, + context: { + [titleField]: properties[titleField], + }, + }, + } + : {}; +}; diff --git a/frontend/test/setupTests.ts b/frontend/test/setupTests.ts index 4d4f0ae88..94f9758db 100644 --- a/frontend/test/setupTests.ts +++ b/frontend/test/setupTests.ts @@ -148,3 +148,13 @@ global.ResizeObserver = jest.fn().mockImplementation(() => ({ unobserve: jest.fn(), disconnect: jest.fn(), })); + +jest.mock('chartjs-plugin-annotation', () => ({ + // Mock the necessary parts of the module + default: { + id: 'annotation', + beforeInit: jest.fn(), + afterDraw: jest.fn(), + destroy: jest.fn(), + }, +})); diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 586972167..e7da83837 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -6240,9 +6240,11 @@ caniuse-lite@^1.0.30001587: canvas@^2.11.2: version "0.0.0" + uid "" "canvas@link:./node_modules/.cache/null": version "0.0.0" + uid "" canvg@^3.0.6: version "3.0.10" @@ -6316,7 +6318,7 @@ chardet@^0.7.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== -chart.js@^2.9.3: +chart.js@^2.4.0, chart.js@^2.9.3: version "2.9.4" resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-2.9.4.tgz#0827f9563faffb2dc5c06562f8eb10337d5b9684" integrity sha512-B07aAzxcrikjAPyV+01j7BmOpxtQETxTSlQ26BEYJ+3iUkbNKaOJ/nDbT6JjyqYxseM0ON12COHYdU2cTIjC7A== @@ -6339,6 +6341,13 @@ chartjs-color@^2.1.0: chartjs-color-string "^0.6.0" color-convert "^1.9.3" +chartjs-plugin-annotation@0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/chartjs-plugin-annotation/-/chartjs-plugin-annotation-0.5.7.tgz#1bf0e30199a6a9ff9889ce0f37a1e755a80d10bf" + integrity sha512-tKN5KLc69unyZGTvSdhVQEyAOhVNnSkFCCgefZhO4UaqFfABZGFU/d9p6WM2KB0eXFs/rR3Jayh7dvyASC7K0A== + dependencies: + chart.js "^2.4.0" + chartjs-plugin-datalabels@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/chartjs-plugin-datalabels/-/chartjs-plugin-datalabels-1.0.0.tgz#5a3d21dde1ed12602dd48c634985a39f431165f1"