Skip to content

Commit 8fc0eb7

Browse files
committed
Handle indexes differing for locations between the JHU timeseries
1 parent 1c7e4ae commit 8fc0eb7

File tree

4 files changed

+52
-61
lines changed

4 files changed

+52
-61
lines changed

app/routers/v2.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ async def get_location_by_id(
9999
Getting specific location by id.
100100
"""
101101
location = await request.state.source.get(id)
102+
102103
return {"location": location.serialize(timelines)}
103104

104105

app/services/location/csbs.py

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
LOGGER = logging.getLogger("services.location.csbs")
1616

17-
1817
class CSBSLocationService(LocationService):
1918
"""
2019
Service for retrieving locations from csbs
@@ -23,18 +22,18 @@ class CSBSLocationService(LocationService):
2322
async def get_all(self):
2423
# Get the locations.
2524
locations = await get_locations()
25+
2626
return locations
2727

2828
async def get(self, loc_id): # pylint: disable=arguments-differ
2929
# Get location at the index equal to the provided id.
3030
locations = await self.get_all()
31-
return locations[loc_id]
3231

32+
return locations[loc_id]
3333

3434
# Base URL for fetching data
3535
BASE_URL = "https://facts.csbs.org/covid-19/covid19_county.csv"
3636

37-
3837
@cached(cache=TTLCache(maxsize=1, ttl=1800))
3938
async def get_locations():
4039
"""
@@ -43,8 +42,10 @@ async def get_locations():
4342
:returns: The locations.
4443
:rtype: dict
4544
"""
45+
4646
data_id = "csbs.locations"
4747
LOGGER.info(f"{data_id} Requesting data...")
48+
4849
# check shared cache
4950
cache_results = await check_cache(data_id)
5051
if cache_results:
@@ -77,19 +78,16 @@ async def get_locations():
7778
# Append to locations.
7879
locations.append(
7980
CSBSLocation(
80-
# General info.
81-
i,
82-
state,
83-
county,
84-
# Coordinates.
85-
Coordinates(item["Latitude"], item["Longitude"]),
86-
# Last update (parse as ISO).
87-
datetime.strptime(last_update, "%Y-%m-%d %H:%M").isoformat() + "Z",
88-
# Statistics.
89-
int(item["Confirmed"] or 0),
90-
int(item["Death"] or 0),
81+
id=i,
82+
state=state,
83+
county=county,
84+
coordinates=Coordinates(item["Latitude"], item["Longitude"]),
85+
last_updated=datetime.strptime(last_update, "%Y-%m-%d %H:%M").isoformat() + "Z",
86+
confirmed=int(item["Confirmed"] or 0),
87+
deaths=int(item["Death"] or 0),
9188
)
9289
)
90+
9391
LOGGER.info(f"{data_id} Data normalized")
9492
# save the results to distributed cache
9593
# TODO: fix json serialization
@@ -98,5 +96,4 @@ async def get_locations():
9896
except TypeError as type_err:
9997
LOGGER.error(type_err)
10098

101-
# Return the locations.
10299
return locations

app/services/location/jhu.py

Lines changed: 37 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
LOGGER = logging.getLogger("services.location.jhu")
2121
PID = os.getpid()
2222

23-
2423
class JhuLocationService(LocationService):
2524
"""
2625
Service for retrieving locations from Johns Hopkins CSSE (https://github.com/CSSEGISandData/COVID-19).
@@ -34,6 +33,7 @@ async def get_all(self):
3433
async def get(self, loc_id): # pylint: disable=arguments-differ
3534
# Get location at the index equal to provided id.
3635
locations = await self.get_all()
36+
3737
return locations[loc_id]
3838

3939

@@ -52,6 +52,7 @@ async def get_category(category):
5252
:returns: The data for category.
5353
:rtype: dict
5454
"""
55+
5556
# Adhere to category naming standard.
5657
category = category.lower()
5758
data_id = f"jhu.{category}"
@@ -87,27 +88,24 @@ async def get_category(category):
8788
# Make location history from dates.
8889
history = {date: int(float(amount or 0)) for date, amount in dates.items()}
8990

90-
# Country for this location.
91-
country = item["Country/Region"]
92-
9391
# Latest data insert value.
9492
latest = list(history.values())[-1]
9593

94+
# Country for this location.
95+
country = item["Country/Region"]
96+
9697
# Normalize the item and append to locations.
97-
locations.append(
98-
{
99-
# General info.
100-
"country": country,
101-
"country_code": countries.country_code(country),
102-
"province": item["Province/State"],
103-
# Coordinates.
104-
"coordinates": {"lat": item["Lat"], "long": item["Long"],},
105-
# History.
106-
"history": history,
107-
# Latest statistic.
108-
"latest": int(latest or 0),
109-
}
110-
)
98+
locations.append({
99+
"country": country,
100+
"country_code": countries.country_code(country),
101+
"province": item["Province/State"],
102+
"coordinates": {
103+
"lat": item["Lat"],
104+
"long": item["Long"],
105+
},
106+
"history": history,
107+
"latest": int(latest or 0),
108+
})
111109
LOGGER.debug(f"{data_id} Data normalized")
112110

113111
# Latest total.
@@ -135,8 +133,10 @@ async def get_locations():
135133
:returns: The locations.
136134
:rtype: List[Location]
137135
"""
136+
138137
data_id = "jhu.locations"
139138
LOGGER.info(f"pid:{PID}: {data_id} Requesting data...")
139+
140140
# Get all of the data categories locations.
141141
confirmed = await get_category("confirmed")
142142
deaths = await get_category("deaths")
@@ -163,8 +163,8 @@ async def get_locations():
163163

164164
timelines = {
165165
"confirmed": location["history"],
166-
"deaths": parse_history(key, locations_deaths, index),
167-
"recovered": parse_history(key, locations_recovered, index),
166+
"deaths": parse_history(key, locations_deaths),
167+
"recovered": parse_history(key, locations_recovered),
168168
}
169169

170170
# Grab coordinates.
@@ -173,16 +173,12 @@ async def get_locations():
173173
# Create location (supporting timelines) and append.
174174
locations.append(
175175
TimelinedLocation(
176-
# General info.
177-
index,
178-
location["country"],
179-
location["province"],
180-
# Coordinates.
181-
Coordinates(latitude=coordinates["lat"], longitude=coordinates["long"]),
182-
# Last update.
183-
datetime.utcnow().isoformat() + "Z",
184-
# Timelines (parse dates as ISO).
185-
{
176+
id=index,
177+
country=location["country"],
178+
province=location["province"],
179+
coordinates=Coordinates(latitude=coordinates["lat"], longitude=coordinates["long"]),
180+
last_updated=datetime.utcnow().isoformat() + "Z",
181+
timelines={
186182
"confirmed": Timeline(
187183
timeline={
188184
datetime.strptime(date, "%m/%d/%y").isoformat() + "Z": amount
@@ -204,25 +200,23 @@ async def get_locations():
204200
},
205201
)
206202
)
203+
207204
LOGGER.info(f"{data_id} Data normalized")
208205

209-
# Finally, return the locations.
210206
return locations
211207

212208

213-
def parse_history(key: tuple, locations: list, index: int):
209+
def parse_history(key: tuple, locations: list):
214210
"""
215211
Helper for validating and extracting history content from
216-
locations data based on index. Validates with the current country/province
212+
locations data based on key. Validates with the current country/province
217213
key to make sure no index/column issue.
218-
219-
TEMP: solution because implement a more efficient and better approach in the refactor.
220214
"""
221-
location_history = {}
222-
try:
223-
if key == (locations[index]["country"], locations[index]["province"]):
224-
location_history = locations[index]["history"]
225-
except (IndexError, KeyError):
226-
LOGGER.debug(f"iteration data merge error: {index} {key}")
227-
228-
return location_history
215+
216+
for i, location in enumerate(locations):
217+
if (location["country"], location["province"]) == key:
218+
return location["history"]
219+
220+
LOGGER.debug(f"iteration data merge error: {key}")
221+
222+
return {}

app/services/location/nyt.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515

1616
LOGGER = logging.getLogger("services.location.nyt")
1717

18-
1918
class NYTLocationService(LocationService):
2019
"""
2120
Service for retrieving locations from New York Times (https://github.com/nytimes/covid-19-data).
@@ -24,21 +23,21 @@ class NYTLocationService(LocationService):
2423
async def get_all(self):
2524
# Get the locations.
2625
locations = await get_locations()
26+
2727
return locations
2828

2929
async def get(self, loc_id): # pylint: disable=arguments-differ
3030
# Get location at the index equal to provided id.
3131
locations = await self.get_all()
32+
3233
return locations[loc_id]
3334

3435

3536
# ---------------------------------------------------------------
3637

37-
3838
# Base URL for fetching category.
3939
BASE_URL = "https://raw.githubusercontent.com/nytimes/covid-19-data/master/us-counties.csv"
4040

41-
4241
def get_grouped_locations_dict(data):
4342
"""
4443
Helper function to group history for locations into one dict.

0 commit comments

Comments
 (0)