diff --git a/miyu_bot/commands/cogs/event.py b/miyu_bot/commands/cogs/event.py index 5bef60c..421bdea 100644 --- a/miyu_bot/commands/cogs/event.py +++ b/miyu_bot/commands/cogs/event.py @@ -1,4 +1,5 @@ import asyncio +import datetime import datetime as dt import logging @@ -182,39 +183,35 @@ class Event(commands.Cog): if state == EventState.Upcoming: time_delta_heading = 'Time Until Start' - time_delta = event.start_datetime - dt.datetime.now(dt.timezone.utc) + delta = event.start_datetime - dt.datetime.now(dt.timezone.utc) date_heading = 'Start Date' date_value = event.start_datetime elif state == EventState.Open: time_delta_heading = 'Time Until Close' - time_delta = event.reception_close_datetime - dt.datetime.now(dt.timezone.utc) - progress = 1 - (time_delta / (event.reception_close_datetime - event.start_datetime)) + delta = event.reception_close_datetime - dt.datetime.now(dt.timezone.utc) + progress = 1 - (delta / (event.reception_close_datetime - event.start_datetime)) date_heading = 'Close Date' date_value = event.reception_close_datetime elif state in (EventState.Closing, EventState.Ranks_Fixed): time_delta_heading = 'Time Until Results' - time_delta = event.result_announcement_datetime - dt.datetime.now(dt.timezone.utc) + delta = event.result_announcement_datetime - dt.datetime.now(dt.timezone.utc) date_heading = 'Results Date' date_value = event.result_announcement_datetime elif state == EventState.Results: time_delta_heading = 'Time Until End' - time_delta = event.end_datetime - dt.datetime.now(dt.timezone.utc) + delta = event.end_datetime - dt.datetime.now(dt.timezone.utc) date_heading = 'End Date' date_value = event.end_datetime else: time_delta_heading = 'Time Since End' - time_delta = dt.datetime.now(dt.timezone.utc) - event.end_datetime + delta = dt.datetime.now(dt.timezone.utc) - event.end_datetime date_heading = 'End Date' date_value = event.end_datetime date_value = date_value.astimezone(timezone) - days = time_delta.days - hours, rem = divmod(time_delta.seconds, 3600) - minutes, seconds = divmod(rem, 60) - embed.add_field(name=time_delta_heading, - value=f'{days}d {hours}h {minutes}m', + value=self.format_timedelta(delta), inline=True) embed.add_field(name='Progress', value=f'{round(progress * 100, 2)}%' if progress is not None else 'N/A', @@ -225,6 +222,13 @@ class Event(commands.Cog): await ctx.send(embed=embed) + @staticmethod + def format_timedelta(delta: datetime.timedelta): + days = delta.days + hours, rem = divmod(delta.seconds, 3600) + minutes, seconds = divmod(rem, 60) + return f'{days}d {hours}h {minutes}m' + @commands.command(name='t20', aliases=['top20', 'top_20'], description='Displays the top 20 in the main leaderboard', @@ -240,13 +244,89 @@ class Event(commands.Cog): nl = "\n" update_date = dateutil.parser.isoparse(leaderboard[0]["date"]).replace(microsecond=0) update_date = update_date.astimezone(pytz.timezone('Asia/Tokyo')) - header = f'Updated {update_date}\n\nRank {"Points".ljust(max_points_digits)} Name' + header = f'Updated {update_date}\n\nRank {"Points":<{max_points_digits}} Name' listing = [ - f'{str(player["rank"]).ljust(4)} {str(player["points"]).ljust(max_points_digits)} {player["name"].replace(nl, "")}' + f'{player["rank"]:<4} {player["points"]:<{max_points_digits}} {player["name"].replace(nl, "")}' for player in leaderboard] paged = run_paged_message(ctx, embed, listing, header=header, page_size=10, numbered=False) asyncio.ensure_future(paged) + valid_tiers = {50, 100, 500, 1000, 2000, 5000, 10000, 20000, 30000, 50000} + + @commands.command(name='cutoff', + aliases=['co', 't50', 't100', 't500', 't1000', 't2000', 't5000', + 't10000', 't20000', 't30000', 't50000', + 't1k', 't2k', 't5k', 't10k', 't20k', 't30k', 't50k'], + description=f'Displays the cutoffs at different tiers. Valid tiers: {str(valid_tiers)}', + help='!cutoff 50') + async def cutoff(self, ctx: commands.Context, tier: str = ''): + def process_tier_arg(tier_arg): + if tier_arg[0] == 't': + tier_arg = tier_arg[1:] + if tier_arg[-1] == 'k': + return str(round(1000 * float(tier_arg[:-1]))) + return tier_arg + + if ctx.invoked_with in ['cutoff', 'co']: + tier = process_tier_arg(tier) + if not tier.isnumeric(): + await ctx.send(f'Invalid tier: {tier}.') + return + else: + tier = process_tier_arg(ctx.invoked_with) + + embed = await self.get_tier_embed(tier, self.bot.asset_filters.events.get_latest_event(ctx)) + + if embed: + await ctx.send(embed=embed) + else: + await ctx.send(f'No data available for tier {tier}.') + + async def get_tier_embed(self, tier: str, event: EventMaster): + async with aiohttp.ClientSession() as session: + async with session.get('http://www.projectdivar.com/eventdata/t20?chart=true') as resp: + leaderboard = await resp.json(encoding='utf-8') + + data = leaderboard['statistics'].get(tier) + if not data: + return None + + if event.state() == EventState.Open: + delta = event.reception_close_datetime - dt.datetime.now(dt.timezone.utc) + time_left = self.format_timedelta(delta) + progress = f'{round(100 * (1 - (delta / (event.reception_close_datetime - event.start_datetime))), 2)}%' + else: + time_left = 'N/A' + progress = 'N/A' + + embed = discord.Embed(title=f'{event.name} [t{tier}]', timestamp=dt.datetime.now(dt.timezone.utc)) + embed.set_thumbnail(url=self.bot.asset_url + get_event_logo_path(event)) + embed.add_field(name='Points', + value=data['points'], + inline=True) + embed.add_field(name='Last Update', + value=data['lastUpdate'], + inline=True) + embed.add_field(name='Rate', + value=f'{data["rate"]} pts/hr', + inline=True) + embed.add_field(name='Current Estimate', + value=data['estimate'], + inline=True) + embed.add_field(name='Final Prediction', + value=data['prediction'], + inline=True) + embed.add_field(name='\u200b', + value='\u200b', + inline=True) + embed.add_field(name='Time Left', + value=time_left, + inline=True) + embed.add_field(name='Progress', + value=progress, + inline=True) + return embed + def setup(bot): bot.add_cog(Event(bot))