wowtoken.app-backend/wow_token/path_handler/relative_path_handler.py

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)