feat: compute scores from ratings via management command
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details

This commit is contained in:
Luca 2024-02-14 18:58:16 +01:00
parent e3a82cb705
commit 8b1b807ef3
4 changed files with 66 additions and 1 deletions

View File

@ -1 +1 @@
__version__ = "0.13.1"
__version__ = "0.14.0"

View File

View File

@ -0,0 +1,65 @@
import math
import statistics
from operator import itemgetter
from django.core.management.base import BaseCommand, CommandError
from django_scopes import scope
from pretalx.event.models import Event
from pretalx.submission.models import Submission
from ...models import Rating, Score
RATINGS_MIN = 30
SCALE = list(map(float, map(itemgetter(0), Rating.RATING_CHOICES)))
MEAN = statistics.mean(SCALE)
STD = math.sqrt(statistics.mean([(i - MEAN) ** 2 for i in SCALE]))
class Command(BaseCommand):
help = "Compute submission scores from ratings"
def add_arguments(self, parser):
parser.add_argument("event")
def handle(self, *args, **kwargs):
try:
event = Event.objects.get(slug=kwargs["event"])
except Event.DoesNotExist:
raise CommandError(f"no event found with slug '{kwargs['event']}'")
with scope(event=event):
submissions = {}
for juror in event.jurors.prefetch_related("ratings"):
ratings = {
r.submission.code: int(r.rating)
for r in juror.ratings.exclude(rating="")
}
values = list(ratings.values())
if len(values) < RATINGS_MIN:
mean = MEAN
std = STD
else:
mean = sum(values) / len(values)
std = math.sqrt(
sum([(i - mean) ** 2 for i in values]) / len(values)
)
for code in ratings:
if code not in submissions:
submissions[code] = []
submissions[code].append((ratings[code] - mean) / std * STD + MEAN)
for submission in Submission.objects.prefetch_related("score").filter(
code__in=submissions.keys()
):
try:
score = submission.score
except Submission.score.RelatedObjectDoesNotExist:
score = Score(submission=submission)
ratings = submissions[submission.code]
score.value = sum(ratings) / len(ratings)
score.save()