make the time animation look nice :3 #7

Merged
stb merged 4 commits from strdst/buba:fix_time_page into main 2025-06-10 22:22:49 +02:00
3 changed files with 66 additions and 28 deletions
Showing only changes of commit 018ddfda06 - Show all commits

merge main

strdst 2025-06-03 22:56:30 +02:00

View file

@ -37,12 +37,12 @@ class DBFAnimation(BubaAnimation):
sleep(60)
@staticmethod
def countdown(train):
def countdown(dt:datetime):
now = datetime.datetime.now()
try:
dep_time = datetime.datetime.strptime(train['actualDeparture'], "%H:%M").time()
dep_time = datetime.datetime.strptime(dt, "%H:%M").time()
except TypeError as e:
return -1
return "--"
# First, assume all departure times are on the current day
dep_date = now.date()
@ -63,8 +63,9 @@ class DBFAnimation(BubaAnimation):
dep_date -= datetime.timedelta(days=1)
# Recalculate the timedelta
dep_td = datetime.datetime.combine(dep_date, dep_time) - now
return round(dep_td.total_seconds() / 60)
return BubaAnimation.countdown(datetime.datetime.combine(dep_date, dep_time))
# dep_td = datetime.datetime.combine(dep_date, dep_time) - now
# return round(dep_td.total_seconds() / 60)
@staticmethod
def short_station(station: str) -> str:
@ -83,6 +84,10 @@ class DBFAnimation(BubaAnimation):
def short_train(train: str) -> str:
if train.startswith("ICE"):
train = "ICE"
if train.startswith("EC"):
train = "EC"
if train.startswith("EN"):
train = "EN"
if train.startswith("ME"):
train = "ME"
if train.startswith("NJ"):
@ -111,13 +116,11 @@ class DBFAnimation(BubaAnimation):
if train['isCancelled']:
when = "--"
else:
when = self.countdown(train)
if when < 0:
when = 0
when = self.countdown(train['actualDeparture'])
self.buba.text(page=0, row=i + 1, col_start=0, col_end=11, text=self.short_train(train['train']))
self.buba.text(page=0, row=i + 1, col_start=12, col_end=104, text=self.short_station(train['destination']))
self.buba.text(page=0, row=i + 1, col_start=105, col_end=119,
text=str(when), align=BubaCmd.ALIGN_RIGHT)
text=when, align=BubaCmd.ALIGN_RIGHT)
self.buba.set_page(0)
for i in range(5):
self.buba.text(page=0, row=0, col_start=93, col_end=119, text=datetime.datetime.now().strftime("%H:%M"), align=BubaCmd.ALIGN_RIGHT)

View file

@ -23,31 +23,25 @@ class IcalEvents(BubaAnimation):
def update(self):
tz = timezone(os.getenv("TZ", "Europe/Berlin"))
events = icalevents.icalevents.events(self.url, sort=True)
events = icalevents.icalevents.events(self.url, tzinfo=tz, sort=True, end=datetime.now(tz)+timedelta(days=14))
for event in events:
event.start = event.start.astimezone(tz)
self.events = events
sleep(600)
@staticmethod
def ellipsis(text, max=28):
if len(text) > max:
text = text[:max - 3] + "..."
return text
def run(self):
for (page, events) in enumerate(self.chunk(self.events, 3)):
if len(self.events) > 3:
self.buba.text(page=0, row=0, col_start=0, col_end=119,
text=f"{self.title} ({page + 1}/{int(len(self.events) / 3)})", align=BubaCmd.ALIGN_LEFT)
text=f"{self.title} ({page + 1}/{int((len(self.events)+2) / 3)})", align=BubaCmd.ALIGN_LEFT)
else:
self.buba.text(page=0, row=0, col_start=0, col_end=119, text=self.title, align=BubaCmd.ALIGN_LEFT)
for (i, event) in enumerate(events):
if event.start - datetime.now(event.start.tzinfo) < timedelta(hours=24):
when = event.start.strftime("%H:%M")
for i in range(3):
if i >= len(events):
self.buba.text(page=0, row=i + 1, col_start=0, col_end=119, text="")
else:
when = event.start.strftime("%d.%m.")
self.buba.text(page=0, row=i + 1, col_start=0, col_end=103, text=self.ellipsis(event.summary))
self.buba.text(page=0, row=i + 1, col_start=104, col_end=119,
text=when, align=BubaCmd.ALIGN_RIGHT)
event = events[i]
self.buba.text(page=0, row=i + 1, col_start=0, col_end=103, text=self.ellipsis(event.summary, 25))
self.buba.text(page=0, row=i + 1, col_start=104, col_end=119,
text=self.countdown(event.start), align=BubaCmd.ALIGN_RIGHT)
sleep(10)

View file

@ -1,4 +1,5 @@
import logging
from datetime import datetime, timedelta
from itertools import islice
from threading import Thread
from time import sleep
@ -12,16 +13,56 @@ class BubaAnimation:
self.buba = buba
pass
def __repr__(self):
return f"<{type(self).__name__}>"
def run(self):
raise Exception("Your class must implement a run() method")
@staticmethod
def chunk(it, size):
"""
Return list in groups of size.
:param it: list
:param size: chunk size
:return: list of chunks
"""
it = iter(it)
return iter(lambda: tuple(islice(it, size)), ())
def run(self):
pass
@staticmethod
def countdown(dt:datetime):
"""
Compute a human-readable time specification until the target event starts. The day starts at 04:00.
:param dt: datetime timezone-aware datetime
:return:
"""
now = datetime.now(dt.tzinfo)
from_day_start = now.replace(hour=4, minute=0, second=0, microsecond=0)
now_delta = dt - now
day_delta = dt - from_day_start
if now_delta < timedelta(seconds=0):
return "now"
if now_delta < timedelta(minutes=30):
return f"{int(now_delta.seconds/60)}m"
if day_delta < timedelta(hours=24):
return f"{int((now_delta.seconds+3599)/3600)}h"
if day_delta < timedelta(days=7):
return dt.strftime("%a") # weekday
return dt.strftime("%d.%m.")
def __repr__(self):
return f"<{type(self).__name__}>"
@staticmethod
def ellipsis(text, max=28):
"""
If the text is longer that max, shorten it and add ellipsis.
:param text: to be shortened
:param max: max length
:return: shortened text
"""
if len(text) > max:
text = text[:max - 2] + "..." # we can get away with just 2, since the periods are very narrow
return text
class BubaAnimator: