Skip to content

Commit

Permalink
Deliver pre-rendered countdowns on the homepage.
Browse files Browse the repository at this point in the history
  • Loading branch information
davepeck committed May 16, 2024
1 parent 5c7aaf9 commit 1bd736f
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 1 deletion.
3 changes: 2 additions & 1 deletion server/vb/components/ongoing_contest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from ..models import Contest
from .button import button
from .logo import school_logo
from .utils import small_countdown_str


def _ongoing_description(contest: Contest) -> list[str]:
Expand Down Expand Up @@ -66,6 +67,6 @@ def ongoing_contest(contest: Contest) -> h.Element:
],
],
h.small_countdown(data_end_at=contest.end_at.isoformat())[
h.div(".box countdown")[""]
h.div(".box countdown")[small_countdown_str(contest.end_at)]
],
]
61 changes: 61 additions & 0 deletions server/vb/components/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import datetime
import typing as t
from dataclasses import dataclass, field, replace
from math import floor

import htpy as h
from htpy import _iter_children as _h_iter_children
Expand Down Expand Up @@ -70,3 +72,62 @@ def __iter__(self):


fragment = Fragment(None)


@dataclass(frozen=True)
class RemainingTime:
"""Render the remaining time until the given end time."""

h0: int
"""The tens digit of the hours."""

h1: int
"""The ones digit of the hours."""

m0: int
"""The tens digit of the minutes."""

m1: int
"""The ones digit of the minutes."""

s0: int
"""The tens digit of the seconds."""

s1: int
"""The ones digit of the seconds."""

@property
def ended(self) -> bool:
"""Return whether the remaining time has ended."""
return self.h0 == self.h1 == self.m0 == self.m1 == self.s0 == self.s1 == 0


def remaining_time(
end_at: datetime.datetime, when: datetime.datetime | None = None
) -> RemainingTime:
"""Render the remaining time until the given end time."""
now = when or datetime.datetime.now(datetime.UTC)
delta = end_at - now
if delta.total_seconds() <= 0:
return RemainingTime(0, 0, 0, 0, 0, 0)
hours, remainder = divmod(delta.total_seconds(), 3600)
minutes, seconds = divmod(remainder, 60)
hours, minutes, seconds = map(floor, (hours, minutes, seconds))
return RemainingTime(
h0=hours // 10,
h1=hours % 10,
m0=minutes // 10,
m1=minutes % 10,
s0=seconds // 10,
s1=seconds % 10,
)


def small_countdown_str(
end_at: datetime.datetime, when: datetime.datetime | None = None
) -> str:
"""Render the remaining time until the given end time."""
rt = remaining_time(end_at, when)
if rt.ended:
return "Just ended!"
return f"Ends in {rt.h0}{rt.h1}:{rt.m0}{rt.m1}:{rt.s0}{rt.s1}"

0 comments on commit 1bd736f

Please sign in to comment.