Add heavy metal visual theme and venue badge levels

This commit is contained in:
kai
2026-08-27 09:41:15 +02:00
parent fd8c216cc8
commit 0343d9c966
5 changed files with 120 additions and 26 deletions
+32 -19
View File
@@ -81,11 +81,11 @@ BADGE_DEFINITIONS = (
("admin", "Admin", "🏴‍☠️", None, "Verantwortung für Pingu Concerts", "special"),
("beta_tester", "Beta Tester", "🧪", None, "In der Beta dabei", "beta"),
("first_gig", "Erster Gig", "🎸", 1, "Dein erstes besuchtes Konzert", "attendance"),
("regular", "Stammgast", "🤘", 5, "5 Konzerte besucht", "attendance"),
("ten_gigs", "Zehnerrunde", "🔥", 10, "10 Konzerte besucht", "attendance"),
("tour_veteran", "Tourveteran", "", 25, "25 Konzerte besucht", "attendance"),
("fifty_gigs", "Fünfzig Konzerte", "💀", 50, "50 Konzerte besucht", "attendance"),
("hundred_gigs", "Hunderterclub", "👑", 100, "100 Konzerte besucht", "attendance"),
("regular", "Stammgast", "🤘", 5, "5 Konzerte am selben Veranstaltungsort besucht", "attendance"),
("ten_gigs", "Stammgast · Level 10", "🔥", 10, "10 Konzerte am selben Veranstaltungsort besucht", "attendance"),
("tour_veteran", "Stammgast · Level 25", "", 25, "25 Konzerte am selben Veranstaltungsort besucht", "attendance"),
("fifty_gigs", "Stammgast · Level 50", "💀", 50, "50 Konzerte am selben Veranstaltungsort besucht", "attendance"),
("hundred_gigs", "Stammgast · Level 100", "👑", 100, "100 Konzerte am selben Veranstaltungsort besucht", "attendance"),
)
ATTENDANCE_BADGE_CODES = tuple(
badge_code
@@ -1085,31 +1085,43 @@ def remove_uploaded_file(path: str | None, destination_dir: str, url_prefix: str
return True
def attended_concert_count(user_id: int) -> int:
def attended_concert_stats(user_id: int) -> tuple[int, int]:
with get_db_connection() as connection:
with connection.cursor() as cursor:
cursor.execute(
"""
SELECT COUNT(*)
FROM concert_attendance
JOIN concerts ON concerts.id = concert_attendance.concert_id
WHERE concert_attendance.user_id = %s
AND concert_attendance.status = 'attending'
AND COALESCE(
concerts.end_datetime,
concerts.start_datetime
) < CURRENT_TIMESTAMP
WITH attended AS (
SELECT concerts.venue_id
, concerts.event_type
FROM concert_attendance
JOIN concerts ON concerts.id = concert_attendance.concert_id
WHERE concert_attendance.user_id = %s
AND concert_attendance.status = 'attending'
AND COALESCE(concerts.end_datetime, concerts.start_datetime) < CURRENT_TIMESTAMP
), venue_counts AS (
SELECT venue_id, COUNT(*) AS visit_count
FROM attended
WHERE venue_id IS NOT NULL AND event_type <> 'other'
GROUP BY venue_id
)
SELECT
(SELECT COUNT(*) FROM attended),
COALESCE((SELECT MAX(visit_count) FROM venue_counts), 0)
""",
(user_id,),
)
return cursor.fetchone()[0]
total, max_same_venue = cursor.fetchone()
return total, max_same_venue
def grant_earned_badges(user_id: int, attended_count: int, registered_at):
def grant_earned_badges(user_id: int, attended_count: int, max_same_venue, registered_at):
highest_attendance_badge = None
for badge_code, _name, _icon, threshold, _description, category in BADGE_DEFINITIONS:
if category == "attendance" and attended_count >= threshold:
qualifies = category == "attendance" and attended_count >= threshold
if category == "attendance" and threshold >= 5:
qualifies = max_same_venue >= threshold
if qualifies:
highest_attendance_badge = badge_code
with get_db_connection() as connection:
@@ -2205,10 +2217,11 @@ def render_profile(
connections["incoming"].append(item)
else:
connections["outgoing"].append(item)
attended_count = attended_concert_count(profile["id"])
attended_count, max_same_venue = attended_concert_stats(profile["id"])
grant_earned_badges(
profile["id"],
attended_count,
max_same_venue,
profile["registered_at"],
)
profile = load_profile(username)