From d39fb19246aa6e93dd2394e455f6dda4957afc33 Mon Sep 17 00:00:00 2001 From: rina Date: Tue, 3 Dec 2024 18:31:49 +1000 Subject: [PATCH 1/3] advent: increase interaction timeout and optimise optimisation to cache image data when switching to/from full view. this is done by lru_cache, currently with a size of 16 (enough for 8 /leaderboard calls, with 2 image each) --- uqcsbot/advent.py | 4 ++-- uqcsbot/utils/advent_utils.py | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/uqcsbot/advent.py b/uqcsbot/advent.py index a711934..fa0a49f 100644 --- a/uqcsbot/advent.py +++ b/uqcsbot/advent.py @@ -1,6 +1,6 @@ import io import os -from datetime import datetime +from datetime import datetime, timedelta from random import choices from typing import Any, Callable, Dict, Iterable, List, Optional, Literal import requests @@ -141,7 +141,7 @@ class LeaderboardView(discord.ui.View): TRUNCATED_COUNT = 20 - TIMEOUT = 180 # seconds + TIMEOUT = timedelta(hours=24).total_seconds() def __init__( self, diff --git a/uqcsbot/utils/advent_utils.py b/uqcsbot/utils/advent_utils.py index a7d294b..c8aea07 100644 --- a/uqcsbot/utils/advent_utils.py +++ b/uqcsbot/utils/advent_utils.py @@ -6,13 +6,15 @@ Dict, Optional, Callable, - NamedTuple, Tuple, cast, ) +from dataclasses import dataclass from collections import defaultdict +from collections.abc import Hashable from datetime import datetime, timedelta from zoneinfo import ZoneInfo +from functools import lru_cache from io import BytesIO import PIL.Image @@ -33,8 +35,16 @@ Times = Dict[Star, Seconds] Delta = Optional[Seconds] Json = Dict[str, Any] + Colour = str -ColourFragment = NamedTuple("ColourFragment", [("text", str), ("colour", Colour)]) + + +@dataclass(frozen=True) +class ColourFragment(Hashable): + text: str + colour: Colour + + Leaderboard = list[str | ColourFragment] # Puzzles are unlocked at midnight EST. @@ -437,6 +447,7 @@ def _isolate_leaderboard_layers( return spaces_str, cast(Dict[str, Any], layers) +@lru_cache(maxsize=16) def render_leaderboard_to_image(leaderboard: Leaderboard) -> bytes: spaces, layers = _isolate_leaderboard_layers(leaderboard) @@ -462,7 +473,7 @@ def render_leaderboard_to_image(leaderboard: Leaderboard) -> bytes: buf = BytesIO() img.save(buf, format="PNG", optimize=True) - return buf.getvalue() # XXX: why do we need to getvalue()? + return buf.getvalue() def build_leaderboard( From 1be5731cdadb78f386000270c671677693e8ef1c Mon Sep 17 00:00:00 2001 From: rina Date: Tue, 3 Dec 2024 20:24:54 +1000 Subject: [PATCH 2/3] fix types oopsie lists aren't hashable, obviously. --- uqcsbot/advent.py | 2 +- uqcsbot/utils/advent_utils.py | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/uqcsbot/advent.py b/uqcsbot/advent.py index fa0a49f..30658f8 100644 --- a/uqcsbot/advent.py +++ b/uqcsbot/advent.py @@ -212,7 +212,7 @@ def make_message_arguments(self) -> Dict[str, Any]: ) leaderboard = self._build_leaderboard(self._visible_members) - scoreboard_image = render_leaderboard_to_image(leaderboard) + scoreboard_image = render_leaderboard_to_image(tuple(leaderboard)) file = discord.File(io.BytesIO(scoreboard_image), self.basename + ".png") embed.set_image(url=f"attachment://{file.filename}") diff --git a/uqcsbot/utils/advent_utils.py b/uqcsbot/utils/advent_utils.py index c8aea07..0ddcfbe 100644 --- a/uqcsbot/utils/advent_utils.py +++ b/uqcsbot/utils/advent_utils.py @@ -1,6 +1,7 @@ from typing import ( Any, DefaultDict, + Iterable, List, Literal, Dict, @@ -418,7 +419,7 @@ def render_leaderboard_to_text(leaderboard: Leaderboard) -> str: def _isolate_leaderboard_layers( - leaderboard: Leaderboard, + leaderboard: Iterable[str | ColourFragment], ) -> Tuple[str, Dict[Colour, str]]: """ Given a leaderboard made up of coloured fragments, split the @@ -448,7 +449,7 @@ def _isolate_leaderboard_layers( @lru_cache(maxsize=16) -def render_leaderboard_to_image(leaderboard: Leaderboard) -> bytes: +def render_leaderboard_to_image(leaderboard: Tuple[str | ColourFragment, ...]) -> bytes: spaces, layers = _isolate_leaderboard_layers(leaderboard) # NOTE: font choice should support as wide a range of glyphs as possible, @@ -477,7 +478,7 @@ def render_leaderboard_to_image(leaderboard: Leaderboard) -> bytes: def build_leaderboard( - columns: List[LeaderboardColumn], members: List[Member], day: Optional[Day] + columns: List[LeaderboardColumn], members: Iterable[Member], day: Optional[Day] ): """ Returns a leaderboard made up of fragments, with the given column configuration From ce80d00c6605fb74d03a570c492f05e34693fdc1 Mon Sep 17 00:00:00 2001 From: Kait <39479354+katrinafyi@users.noreply.github.com> Date: Tue, 3 Dec 2024 22:11:13 +1000 Subject: [PATCH 3/3] undo unnecessary change --- uqcsbot/utils/advent_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uqcsbot/utils/advent_utils.py b/uqcsbot/utils/advent_utils.py index 0ddcfbe..9b8afa6 100644 --- a/uqcsbot/utils/advent_utils.py +++ b/uqcsbot/utils/advent_utils.py @@ -478,7 +478,7 @@ def render_leaderboard_to_image(leaderboard: Tuple[str | ColourFragment, ...]) - def build_leaderboard( - columns: List[LeaderboardColumn], members: Iterable[Member], day: Optional[Day] + columns: List[LeaderboardColumn], members: List[Member], day: Optional[Day] ): """ Returns a leaderboard made up of fragments, with the given column configuration