Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

advent: increase interaction timeout and optimise #213

Merged
merged 3 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions uqcsbot/advent.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -141,7 +141,7 @@

class LeaderboardView(discord.ui.View):
TRUNCATED_COUNT = 20
TIMEOUT = 180 # seconds
TIMEOUT = timedelta(hours=24).total_seconds()

def __init__(
self,
Expand Down Expand Up @@ -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}")

Expand Down
22 changes: 17 additions & 5 deletions uqcsbot/utils/advent_utils.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
from typing import (
Any,
DefaultDict,
Iterable,
List,
Literal,
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
Expand All @@ -33,8 +36,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.
Expand Down Expand Up @@ -408,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
Expand Down Expand Up @@ -437,7 +448,8 @@ def _isolate_leaderboard_layers(
return spaces_str, cast(Dict[str, Any], layers)


def render_leaderboard_to_image(leaderboard: Leaderboard) -> bytes:
@lru_cache(maxsize=16)
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,
Expand All @@ -462,7 +474,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(
Expand Down
Loading