Add value field to MusicGameOrder and update score calculation logic

This commit is contained in:
Edgar P. Burkhart 2025-06-15 15:09:48 +02:00
parent 178a7cab03
commit 92abcb584c
Signed by: edpibu
GPG key ID: 9833D3C5A25BD227
3 changed files with 45 additions and 25 deletions

View file

@ -0,0 +1,17 @@
# Generated by Django 5.2.3 on 2025-06-15 12:49
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("game", "0021_alter_musicgameresults_score"),
]
operations = [
migrations.AddField(
model_name="musicgameorder",
name="value",
field=models.PositiveIntegerField(default=0),
),
]

View file

@ -1,5 +1,6 @@
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.db import models from django.db import models
from django.db.models import F
from django.db.models.functions import Lower from django.db.models.functions import Lower
from django.db.models.signals import post_delete, post_save from django.db.models.signals import post_delete, post_save
from django.dispatch import receiver from django.dispatch import receiver
@ -106,6 +107,17 @@ class MusicGameOrder(models.Model):
player = models.ForeignKey(User, on_delete=models.CASCADE) player = models.ForeignKey(User, on_delete=models.CASCADE)
music_video = models.ForeignKey(MusicVideo, on_delete=models.CASCADE) music_video = models.ForeignKey(MusicVideo, on_delete=models.CASCADE)
order = models.PositiveIntegerField() order = models.PositiveIntegerField()
value = models.PositiveIntegerField(default=0)
def update_value(self):
n_right = self.musicgameanswer_set.filter(game__player=F("answer")).count()
if n_right == 0:
self.value = 1000
else:
self.value = 1000 / (
1 + ((n_right - 1) / (self.game.players.count() - 1)) ** 0.5
)
self.save()
class Meta: class Meta:
constraints = [ constraints = [
@ -117,6 +129,17 @@ class MusicGameOrder(models.Model):
ordering = ["order"] ordering = ["order"]
class AnswerManager(models.Manager):
def score(self, game, player):
qs = self.filter(game__game=game, game__player=player)
return (
qs.filter(answer=F("game__player"))
.aggregate(score=models.Sum("game__value", default=0))
.get("score")
- 500 * qs.exclude(game__player=F("answer")).count()
)
class MusicGameAnswer(models.Model): class MusicGameAnswer(models.Model):
game = models.ForeignKey(MusicGameOrder, on_delete=models.CASCADE) game = models.ForeignKey(MusicGameOrder, on_delete=models.CASCADE)
player = models.ForeignKey(User, on_delete=models.CASCADE) player = models.ForeignKey(User, on_delete=models.CASCADE)
@ -124,6 +147,8 @@ class MusicGameAnswer(models.Model):
User, on_delete=models.SET_NULL, null=True, related_name="+" User, on_delete=models.SET_NULL, null=True, related_name="+"
) )
objects = AnswerManager()
class Meta: class Meta:
constraints = [ constraints = [
models.UniqueConstraint(fields=("game", "player"), name="unique_answer"), models.UniqueConstraint(fields=("game", "player"), name="unique_answer"),

View file

@ -9,7 +9,7 @@ from django.contrib.auth.models import User
from django.contrib.messages.views import SuccessMessageMixin from django.contrib.messages.views import SuccessMessageMixin
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.db import IntegrityError from django.db import IntegrityError
from django.db.models import Count, F, Q from django.db.models import Count, Q
from django.shortcuts import get_object_or_404, redirect from django.shortcuts import get_object_or_404, redirect
from django.views import View from django.views import View
from django.views.generic import TemplateView from django.views.generic import TemplateView
@ -471,33 +471,11 @@ class GameEndView(LoginRequiredMixin, SingleObjectMixin, View):
raise PermissionDenied() raise PermissionDenied()
game.over = True game.over = True
value = {}
for go in game.musicgameorder_set.all(): for go in game.musicgameorder_set.all():
value[go.pk] = 1000 / ( go.update_value()
1
+ (
(go.musicgameanswer_set.filter(game__player=F("answer")).count())
- 1 / game.players.count()
)
** 2
)
for player in game.players.all(): for player in game.players.all():
score = sum( score = player.musicgameanswer_set.score(game, player)
[
value[ga.game.pk]
for ga in player.musicgameanswer_set.filter(game__game=game)
.exclude(game__player=player)
.filter(game__player=F("answer"))
]
)
score -= (
500
* player.musicgameanswer_set.filter(game__game=game)
.filter(game__player=player)
.exclude(game__player=F("answer"))
.count()
)
models.MusicGameResults.objects.create( models.MusicGameResults.objects.create(
game=game, player=player, score=score game=game, player=player, score=score
) )