From f67f9ce4b93c8b1d74ffe157294b91717668d6d4 Mon Sep 17 00:00:00 2001 From: Stefan Harmuth Date: Sun, 26 Jan 2025 10:00:58 +0100 Subject: [PATCH] counting the stars --- aoc_bot.py | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/aoc_bot.py b/aoc_bot.py index 9e1a872..f6d8b14 100644 --- a/aoc_bot.py +++ b/aoc_bot.py @@ -2,6 +2,8 @@ from __future__ import annotations import argparse import os.path +from collections import defaultdict + import requests import sys from datetime import datetime, timedelta, timezone @@ -41,6 +43,7 @@ class LeaderboardCache: self.__aoc_user_agent = aoc_user_agent self.__last_fetch_year = 2015 self.__stats = {} + self.__stars = {} self.update_stats() def fetch_leaderboard(self, year: int) -> dict: @@ -66,11 +69,12 @@ class LeaderboardCache: continue year_keys = {} - year_stats = {"year": {}, "days": {}, "member_name_len": 0} + year_stats = {"year": {}, "days": {}, "stars": {}, "member_name_len": 0} for member_id, member_data in self.__cache[year]["members"].items(): member_key = (int(member_data["local_score"]), member_data["name"]) year_keys[member_id] = member_key year_stats["year"][member_key] = [" "] * 25 + year_stats["stars"][member_data["name"]] = member_data["stars"] year_stats["member_name_len"] = max(year_stats["member_name_len"], len(member_data["name"])) member_count = len(self.__cache[year]["members"]) @@ -119,6 +123,13 @@ class LeaderboardCache: self.__stats[year] = year_stats + star_stats = defaultdict(int) + for year, year_stats in self.__stats.items(): + for member, stars in year_stats["stars"].items(): + star_stats[member] += stars + + self.__stars = star_stats + def update(self) -> dict: now = datetime.now(timezone.utc) if now.month == 12: # on season @@ -176,6 +187,14 @@ class LeaderboardCache: def get_years(self) -> list[str]: return list(sorted(self.__stats.keys())) + def get_year_stars(self, year: str): + for member, stars in sorted(self.__stats[year]["stars"].items(), key=lambda x: x[1], reverse=True): + yield member, stars + + def get_all_stars(self): + for member, stars in sorted(self.__stars.items(), key=lambda x: x[1], reverse=True): + yield member, stars + def get_year_items(self, year: str) -> (str, int, str): for (score, member_name), solve_string in sorted(self.__stats[year]["year"].items(), reverse=True): yield member_name, score, solve_string @@ -187,6 +206,9 @@ class LeaderboardCache: def get_year_member_name_len(self, year: str) -> int: return self.__stats[year]["member_name_len"] + def get_all_member_name_len(self) -> int: + return max(self.__stats[x]["member_name_len"] for x in self.__stats) + class AOCBot: def __init__(self, config_file: str = "config.json"): @@ -352,6 +374,28 @@ class AOCBot: break self.__irc_bot.privmsg(self.__irc_channel, format_string % (member_name, score, "".join(solve_string))) + def command_stars(self, msg_from: str, message: str): + if not self.check_spam(msg_from, "stars"): + return + + if not message: + max_name_len = self.__cache.get_all_member_name_len() + star_gen = self.__cache.get_all_stars() + else: + year = message + if not self.__cache.has_year(year): + self.__irc_bot.privmsg(self.__irc_channel, "Unknown year: %s" % year) + return + + max_name_len = self.__cache.get_year_member_name_len(year) + star_gen = self.__cache.get_year_stars(year) + + for count, (member, stars) in enumerate(star_gen): + if stars == 0: + break + line = "%2d. %-" + str(max_name_len) + "s %4d Stars" + self.__irc_bot.privmsg(self.__irc_channel, line % (count + 1, member, stars)) + def update_leaderboard(self): new_stars = self.__cache.update() self.__last_update = datetime.now(timezone.utc) @@ -370,6 +414,10 @@ class AOCBot: def on_raw(self, msg_from: str, msg_type: str, msg_to: str, message: str): print("[%s] <%s> (%s) -> <%s>: %s" % (datetime.now().strftime("%H:%M:%S"), msg_from, msg_type, msg_to, message)) + def on_quit(self, msg_from: str, msg_type: str, msg_to: str, message: str): + if msg_from == self.__irc_bot.getUser().identifier: + sys.exit(0) + def flush_output(self): sys.stdout.flush() sys.stderr.flush() @@ -411,10 +459,12 @@ class AOCBot: print("[AoCBot] Registering Commands") self.__irc_bot.on(ServerMessage.RAW, self.on_raw) + self.__irc_bot.on(ServerMessage.MSG_QUIT, self.on_quit) self.__irc_bot.register_channel_command("!info", self.__irc_channel, self.command_info) self.__irc_bot.register_channel_command("!help", self.__irc_channel, self.command_help) self.__irc_bot.register_channel_command("!day", self.__irc_channel, self.command_day) self.__irc_bot.register_channel_command("!year", self.__irc_channel, self.command_year) + self.__irc_bot.register_channel_command("!stars", self.__irc_channel, self.command_stars) print("[AoCBot] Starting Main Loop") self.__irc_bot.run()