This commit is contained in:
team3
2026-09-29 00:54:58 +02:00
parent f7c9017946
commit f80b8c5826
20 changed files with 997 additions and 77 deletions

75
backend/app/punkte.py Normal file
View File

@@ -0,0 +1,75 @@
"""Erfahrung und Level — berechnet, nicht gebucht.
Punkte sind eine Formel über dem, was gerade in der Datenbank steht:
wer dabei war, bewertet, kommentiert, geantwortet und ein Herz gegeben
hat. Nimmt jemand seine Wertung zurück, sind die Punkte weg. Es gibt
kein Konto, das man pflegen oder austricksen könnte.
Je Film zählt jede Art nur einmal. Level nach Dreieckszahlen: Level L
ist erreicht, sobald L·(L−1)/2 Punkte da sind — anfangs schnell, dann
stetig langsamer, aber immer in Reichweite.
"""
from math import isqrt
from .db import connect
SCHAUEN = 10
BEWERTEN = 3
KOMMENTAR = 5
ANTWORT = 2
HERZ = 1
ZAEHLUNGEN = (
(SCHAUEN, "SELECT user_id, COUNT(*) AS n FROM watched_dabei GROUP BY user_id"),
(
BEWERTEN,
"SELECT user_id, COUNT(DISTINCT watched_id) AS n FROM ratings "
"WHERE user_id IS NOT NULL GROUP BY user_id",
),
(
KOMMENTAR,
"SELECT user_id, COUNT(DISTINCT watched_id) AS n FROM watched_notes "
"WHERE user_id IS NOT NULL AND parent_id IS NULL GROUP BY user_id",
),
(
ANTWORT,
"SELECT user_id, COUNT(DISTINCT watched_id) AS n FROM watched_notes "
"WHERE user_id IS NOT NULL AND parent_id IS NOT NULL GROUP BY user_id",
),
(
HERZ,
"SELECT h.user_id, COUNT(DISTINCT n.watched_id) AS n FROM watched_hearts h "
"JOIN watched_notes n ON n.id = h.note_id "
"WHERE h.user_id IS NOT NULL GROUP BY h.user_id",
),
)
def level(punkte):
"""Größtes L mit L·(L−1)/2 ≤ Punkte. Null Punkte sind Level 1."""
stufe = (1 + isqrt(1 + 8 * punkte)) // 2
while stufe * (stufe - 1) // 2 > punkte:
stufe -= 1
return max(1, stufe)
def stand(punkte):
stufe = level(punkte)
return {
"punkte": punkte,
"level": stufe,
# Wo das aktuelle Level begann und wo das nächste anfängt — für den Balken
"von": stufe * (stufe - 1) // 2,
"bis": stufe * (stufe + 1) // 2,
}
def alle():
"""Punktestand je user_id."""
summen = {}
with connect() as conn:
for wert, sql in ZAEHLUNGEN:
for row in conn.execute(sql):
summen[row["user_id"]] = summen.get(row["user_id"], 0) + wert * row["n"]
return {user_id: stand(p) for user_id, p in summen.items()}