covid: add top3 subcommand

This commit is contained in:
ducklet 2021-03-29 19:06:27 +02:00
parent 14b4a350ee
commit dfc9420a3f

View file

@ -8,7 +8,7 @@ from typing import *
import requests import requests
from ..functions import localizedtz, reply from ..functions import localizedtz, react, reply
from ..models import Job, Message from ..models import Job, Message
from ..tz import cest from ..tz import cest
@ -181,7 +181,7 @@ class Store:
for row in self.connection.execute(sql, params): for row in self.connection.execute(sql, params):
yield Probe.from_row(row) yield Probe.from_row(row)
def find_one(self, term) -> Optional["Probe"]: def find_one(self, term: str = "%") -> Optional["Probe"]:
cond = """ cond = """
where county_name like ? where county_name like ?
or state_name like ? or state_name like ?
@ -317,11 +317,11 @@ async def update_store(job: Job):
store.add(load_data()) store.add(load_data())
def pfloat(n): def pfloat(n: float):
return f"{n:_.02f}".replace(".", ",") return f"{n:_.02f}".replace(".", ",")
def as_html(probe, tzname: str, lc: str) -> str: def as_html(probe: Probe, tzname: str, lc: str) -> str:
# now = datetime.now(tz=timezone.utc) # now = datetime.now(tz=timezone.utc)
# since = now - probe.ts # since = now - probe.ts
# fmt = "%A" if since.days < 7 else "%x" # fmt = "%A" if since.days < 7 else "%x"
@ -348,6 +348,76 @@ def as_html(probe, tzname: str, lc: str) -> str:
) )
def top3html(states: List[Probe], counties: List[Probe], tzname: str, lc: str) -> str:
assert len(states) == len(counties) == 3
posmoji = ("🥇", "🥈", "🥉")
date = localizedtz(states[0].ts, "%A, %x", tzname=tzname, lc=lc)
return (
f"<i>Höchste 7-Tage-Inzidenz von {date}</i>: "
+ ", ".join(
(
f"{medal} {escape(probe.county_name)}"
+ f" (📈 {pfloat(probe.cases7_per_100k)})"
)
for probe, medal in zip(counties, posmoji)
)
+ ""
+ ", ".join(
(
f"{medal} {escape(probe.state_name)}"
+ f" (📈 {pfloat(probe.state_cases7_per_100k)})"
)
for probe, medal in zip(states, posmoji)
)
)
async def top3(store: Store, message: Message):
latest = store.find_one()
def top_probes(scope: str, n=3):
sql = f"""
select *
from current
where ts = ?
group by {scope}_name
order by {scope}_cases7_per_100k desc
limit {n}
"""
return [
Probe.from_row(row)
for row in store.connection.execute(sql, [latest.ts.timestamp()])
]
states = top_probes("state")
counties = top_probes("county")
if states and counties:
roomconf = message.app.config.l6n[message.room.room_id]
await reply(
message,
html=top3html(
states, counties, tzname=roomconf["timezone"], lc=roomconf["locale"]
),
)
else:
await react(message, emoji="🐛")
async def search(store: Store, message: Message):
assert message.args
term = "%".join(message.args)
if (probe := store.find_one(f"%{term}%")) :
roomconf = message.app.config.l6n[message.room.room_id]
await reply(
message,
html=as_html(probe, tzname=roomconf["timezone"], lc=roomconf["locale"]),
)
else:
await reply(message, "No such county or state.", in_thread=True)
async def handle(message: Message): async def handle(message: Message):
if message.command not in ("cov", "covid") or not message.args: if message.command not in ("cov", "covid") or not message.args:
return return
@ -359,12 +429,8 @@ async def handle(message: Message):
# return # return
store: Store = message.app.shared["covid.store"] store: Store = message.app.shared["covid.store"]
term = "%".join(message.args)
if (probe := store.find_one(f"%{term}%")) : if message.args.get(0) == "top3":
roomconf = message.app.config.l6n[message.room.room_id] await top3(store, message)
await reply(
message,
html=as_html(probe, tzname=roomconf["timezone"], lc=roomconf["locale"]),
)
else: else:
await reply(message, "No such county or state.", in_thread=True) await search(store, message)