diff --git a/app/location/location_root.py b/app/location/location_root.py new file mode 100644 index 00000000..6fa354f7 --- /dev/null +++ b/app/location/location_root.py @@ -0,0 +1,17 @@ +from csbs import CSBSLocation +from nyt import NYTLocation + +class LocationRoot: + + + def __init__(self, location): + location = NYTLocationService + + + def set_csbs(self, id, state, county, coordinates, last_updated, confirmed, deaths): + self.location = CSBSLocation(id, state, county, coordinates, last_updated, confirmed, deaths) + + + + def set_nyt(self, id, state, county, coordinates, last_updated, timelines): + self.location = NYTLocation( id, state, county, coordinates, last_updated, timelines) diff --git a/app/routers/v2.py b/app/routers/v2.py index 31eb408c..fd91b292 100644 --- a/app/routers/v2.py +++ b/app/routers/v2.py @@ -2,7 +2,7 @@ import enum from fastapi import APIRouter, HTTPException, Request - +from ..services import ServiceRoot from ..data import DATA_SOURCES from ..models import LatestResponse, LocationResponse, LocationsResponse @@ -26,7 +26,11 @@ async def get_latest( """ Getting latest amount of total confirmed cases, deaths, and recoveries. """ - locations = await request.state.source.get_all() + + #service root for aggregate pattern + service = ServiceRoot(source) + + locations = await service.get_all() return { "latest": { "confirmed": sum(map(lambda location: location.confirmed, locations)), @@ -56,8 +60,10 @@ async def get_locations( params.pop("source", None) params.pop("timelines", None) + service = ServiceRoot(source) + # Retrieve all the locations. - locations = await request.state.source.get_all() + locations = await service.get_all() # Attempt to filter out locations with properties matching the provided query params. for key, value in params.items(): @@ -98,7 +104,12 @@ async def get_location_by_id( """ Getting specific location by id. """ - location = await request.state.source.get(id) + + #aggregate root for service layer + service = ServiceRoot(source) + + # Retrieve location. + location = await service.get(id) return {"location": location.serialize(timelines)} diff --git a/app/services/location/csbs.py b/app/services/location/csbs.py index 444ebad6..ffb36477 100644 --- a/app/services/location/csbs.py +++ b/app/services/location/csbs.py @@ -8,7 +8,8 @@ from ...caches import check_cache, load_cache from ...coordinates import Coordinates -from ...location.csbs import CSBSLocation +from ...location.location_root import LocationRoot +#from ...location.csbs import CSBSLocation from ...utils import httputils from . import LocationService @@ -74,21 +75,25 @@ async def get_locations(): # Date string without "EDT" at end. last_update = " ".join(item["Last Update"].split(" ")[0:2]) + #access location aggregate root, and append it to locations. + location_csbs = LocationRoot() + location_csbs.set_csbs( + # General info. + i, + state, + county, + # Coordinates. + Coordinates(item["Latitude"], item["Longitude"]), + # Last update (parse as ISO). + datetime.strptime(last_update, "%Y-%m-%d %H:%M").isoformat() + "Z", + # Statistics. + int(item["Confirmed"] or 0), + int(item["Death"] or 0), + ) + #location.method(args) # Append to locations. locations.append( - CSBSLocation( - # General info. - i, - state, - county, - # Coordinates. - Coordinates(item["Latitude"], item["Longitude"]), - # Last update (parse as ISO). - datetime.strptime(last_update, "%Y-%m-%d %H:%M").isoformat() + "Z", - # Statistics. - int(item["Confirmed"] or 0), - int(item["Death"] or 0), - ) + location_csbs.location ) LOGGER.info(f"{data_id} Data normalized") # save the results to distributed cache diff --git a/app/services/location/nyt.py b/app/services/location/nyt.py index 1f25ec34..ea2f6caa 100644 --- a/app/services/location/nyt.py +++ b/app/services/location/nyt.py @@ -8,7 +8,8 @@ from ...caches import check_cache, load_cache from ...coordinates import Coordinates -from ...location.nyt import NYTLocation +#from ...location.nyt import NYTLocation +from ...location.location_root import LocationRoot from ...models import Timeline from ...utils import httputils from . import LocationService @@ -109,30 +110,34 @@ async def get_locations(): deaths_list = histories["deaths"] deaths_history = {date: int(amount or 0) for date, amount in deaths_list} + #access location aggregate root, and append it to locations. + location_nyt = LocationRoot() + location_nyt.set_nyt( + id=idx, + state=county_state[1], + county=county_state[0], + coordinates=Coordinates(None, None), # NYT does not provide coordinates + last_updated=datetime.utcnow().isoformat() + "Z", # since last request + timelines={ + "confirmed": Timeline( + timeline={ + datetime.strptime(date, "%Y-%m-%d").isoformat() + "Z": amount + for date, amount in confirmed_history.items() + } + ), + "deaths": Timeline( + timeline={ + datetime.strptime(date, "%Y-%m-%d").isoformat() + "Z": amount + for date, amount in deaths_history.items() + } + ), + "recovered": Timeline(), + }, + ) + # Normalize the item and append to locations. locations.append( - NYTLocation( - id=idx, - state=county_state[1], - county=county_state[0], - coordinates=Coordinates(None, None), # NYT does not provide coordinates - last_updated=datetime.utcnow().isoformat() + "Z", # since last request - timelines={ - "confirmed": Timeline( - timeline={ - datetime.strptime(date, "%Y-%m-%d").isoformat() + "Z": amount - for date, amount in confirmed_history.items() - } - ), - "deaths": Timeline( - timeline={ - datetime.strptime(date, "%Y-%m-%d").isoformat() + "Z": amount - for date, amount in deaths_history.items() - } - ), - "recovered": Timeline(), - }, - ) + location_nyt.location ) LOGGER.info(f"{data_id} Data normalized") # save the results to distributed cache diff --git a/app/services/location/service_root.py b/app/services/location/service_root.py new file mode 100644 index 00000000..775049b9 --- /dev/null +++ b/app/services/location/service_root.py @@ -0,0 +1,26 @@ +from jhu import JHULocationService +from nyt import NYTLocationService +from csbs import CSBSLocationService + +class ServiceRoot: + + def __init__(self, source, service): + if source == '' or source == None or source == 'jhu': + self.source = 'jhu' + self.service = JHULocationService() + elif source == 'nyt': + self.source = source + self.service = NYTLocationService() + elif source == 'csbs': + self.source = source + self.service = CSBSLocationService() + else + self.source = None + + async def get_all(self): + locations = await self.service.get_all() + return locations + + async def get(self, id): + location = await self.service.get(id) + return location