99 lines
3.9 KiB
Python
99 lines
3.9 KiB
Python
import datetime
|
|
from typing import List, Tuple
|
|
|
|
from wow_token.db.cached_range import CachedRange
|
|
from wow_token.db.compacted import Compacted
|
|
from wow_token.db.recent import Recent
|
|
from wow_token.db.trinity import Trinity
|
|
from wow_token.flavor import Flavor
|
|
from wow_token.path_handler.relative_error import InvalidRelativePathError
|
|
from wow_token.region import Region
|
|
|
|
|
|
class RelativePathHandler:
|
|
_cdb : Compacted
|
|
_rdb : Recent
|
|
def __init__(self, cdb: Compacted, rdb: Recent):
|
|
self._cdb = cdb
|
|
self._rdb = rdb
|
|
|
|
|
|
def get_by_timedelta(self, flavor: Flavor, region: Region, timedelta: datetime.timedelta) -> List[Tuple[str, int]]:
|
|
current_time = datetime.datetime.now(datetime.UTC)
|
|
start_time = current_time - timedelta
|
|
|
|
if timedelta.days < 61:
|
|
return self._rdb.get_after_unix_timestamp(flavor, region, int(start_time.timestamp()))
|
|
elif timedelta.days <= 90:
|
|
trinity = Trinity(region, flavor, CachedRange('90d'))
|
|
elif timedelta.days <= 183:
|
|
trinity = Trinity(region, flavor, CachedRange('6m'))
|
|
elif timedelta.days <= 365:
|
|
trinity = Trinity(region, flavor, CachedRange('1y'))
|
|
elif timedelta.days <= 730:
|
|
trinity = Trinity(region, flavor, CachedRange('2y'))
|
|
else:
|
|
trinity = Trinity(region, flavor, CachedRange('all'))
|
|
|
|
# If the data is exactly the size of the precomputed structure, go ahead and return it directly
|
|
if timedelta.days == 90 or timedelta.days == 182 or timedelta.days == 365 or timedelta.days == 730:
|
|
return self._cdb.get_precomputed_range(trinity, str)
|
|
|
|
final_data = []
|
|
data = self._cdb.get_precomputed_range(trinity)
|
|
for timestamp, price in data:
|
|
if timestamp >= start_time:
|
|
final_data.append((timestamp.isoformat(), price))
|
|
return final_data
|
|
|
|
|
|
def relative_time_handler(self, flavor: Flavor, region: Region, relative_range: str) -> List[Tuple[str, int]]:
|
|
if relative_range == '30d':
|
|
relative_range = '744h'
|
|
|
|
relative_unit = relative_range[-1]
|
|
|
|
match relative_unit:
|
|
case 'h':
|
|
hours = int(relative_range[:-1])
|
|
if hours > 1488:
|
|
raise InvalidRelativePathError
|
|
start_time = datetime.datetime.now(datetime.UTC) - datetime.timedelta(hours=hours)
|
|
return self._rdb.get_after_unix_timestamp(flavor, region, int(start_time.timestamp()))
|
|
case 'd':
|
|
days = int(relative_range[:-1])
|
|
if days > 730:
|
|
raise InvalidRelativePathError
|
|
delta = datetime.timedelta(days=days)
|
|
return self.get_by_timedelta(flavor, region, delta)
|
|
case 'm':
|
|
months = int(relative_range[:-1])
|
|
if months > 48:
|
|
raise InvalidRelativePathError
|
|
delta = datetime.timedelta(days=int(30.437*months))
|
|
return self.get_by_timedelta(flavor, region, delta)
|
|
case 'y':
|
|
years = int(relative_range[:-1])
|
|
if years > 10:
|
|
raise InvalidRelativePathError
|
|
delta = datetime.timedelta(days=int(365.25*years))
|
|
return self.get_by_timedelta(flavor, region, delta)
|
|
case _:
|
|
if relative_range == 'all':
|
|
return self._cdb.get_precomputed_range(Trinity(region, flavor, CachedRange('all')), str)
|
|
raise InvalidRelativePathError
|
|
|
|
|
|
|
|
def path_handler(self, uri) -> List[Tuple[str, int]]:
|
|
# This URI takes the form of /v2/relative/{flavor}/{region}/{range}
|
|
split_uri = uri.split('/')
|
|
flavor = Flavor(split_uri[-3])
|
|
region = Region(split_uri[-2])
|
|
_range = split_uri[-1]
|
|
if split_uri[-1].endswith('.json'):
|
|
_range = split_uri[-1][:-5]
|
|
|
|
return self.relative_time_handler(flavor, region, _range)
|
|
|