Commit f49158e0 authored by Julien Palard's avatar Julien Palard
Browse files

Drop now useless userstats.

parent bbdbf32d
......@@ -12,7 +12,8 @@ This project requires Python 3.6 at least.
pip install -r requirements.txt
./manage.py migrate
./manage.py loaddata initial # To get some users and exercises
# (Initial data can be updated using: ./manage.py dumpdata > website/fixtures/initial.json)
# (Initial data can be updated using:
./manage.py dumpdata -e contenttypes -e auth.Permission -e sessions.session > website/fixtures/initial.json)
./manage.py createsuperuser
./manage.py runserver
```
......
......@@ -132,15 +132,6 @@ class MyUserAdmin(UserAdmin):
list_display = UserAdmin.list_display + ("date_joined", "points", "rank")
ordering = ("-date_joined",)
def points(self, obj):
return obj.userstats.points
def rank(self, obj):
return obj.userstats.rank
def get_queryset(self, request):
return super().get_queryset(request).select_related("userstats")
admin.site.register(Answer, AnswerAdmin)
admin.site.register(Exercise, ExerciseAdmin)
......
......@@ -7,7 +7,7 @@ from channels.generic.websocket import AsyncJsonWebsocketConsumer
from django.utils.timezone import now
from moulinette.tasks import check_answer, run_snippet
from website.models import Answer, Exercise, Snippet, UserStats, User
from website.models import Answer, Exercise, Snippet, User
from website.utils import markdown_to_bootstrap
from website.serializers import AnswerSerializer, SnippetSerializer
......@@ -73,12 +73,9 @@ def db_update_answer(answer_id: int, is_valid: bool, correction_message: str):
answer.is_valid = is_valid
answer.corrected_at = now()
answer.save()
rank = None
if answer.is_valid and answer.user_id:
user_stats, _ = UserStats.objects.get_or_create(user=answer.user)
user_stats.recompute()
rank = user_stats.rank
else:
rank = None
rank = answer.user.recompute_rank()
return answer, rank
......
This diff is collapsed.
from django.core.management.base import BaseCommand, CommandError
from website.models import UserStats, Exercise
from website.models import User, Exercise
class Command(BaseCommand):
help = "Recompute all user stats"
def handle(self, *args, **options):
UserStats.objects.recompute()
User.objects.recompute_ranks()
self.stdout.write(self.style.SUCCESS("Successfully recomputed all stats"))
# Generated by Django 3.1.3 on 2020-12-04 12:07
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('website', '0002_auto_20201204_1148'),
]
operations = [
migrations.AlterModelManagers(
name='user',
managers=[
],
),
migrations.AddField(
model_name='user',
name='points',
field=models.FloatField(default=0),
),
migrations.AddField(
model_name='user',
name='rank',
field=models.PositiveIntegerField(blank=True, null=True),
),
migrations.DeleteModel(
name='UserStats',
),
]
import logging
from datetime import timedelta
from django.contrib.auth.models import AbstractUser
import django.contrib.auth.models
from django.db import models
from django.db.models import Count, IntegerField, Value, Q
from django.urls import reverse
......@@ -12,8 +12,27 @@ from django_extensions.db.fields import AutoSlugField
logger = logging.getLogger(__name__)
class User(AbstractUser):
pass
class UserManager(django.contrib.auth.models.UserManager):
def recompute_ranks(self):
for user in User.objects.all():
user.recompute_rank()
class User(django.contrib.auth.models.AbstractUser):
objects = UserManager()
points = models.FloatField(default=0) # Computed sum of solved exercise positions.
rank = models.PositiveIntegerField(blank=True, null=True)
def recompute_rank(self) -> int:
"""Reconpute, and return, the user rank."""
self.points = sum(
exercise.position
for exercise in Exercise.objects.with_user_stats(user=self)
if exercise.user_successes
)
self.rank = User.objects.filter(points__gt=self.points).count() + 1
self.save()
return self.rank
class ExerciseQuerySet(models.QuerySet):
......@@ -90,37 +109,6 @@ class ExerciseQuerySet(models.QuerySet):
)
class UserStatsQuerySet(models.QuerySet):
def recompute(self):
for user in User.objects.all():
user_stats, _ = UserStats.objects.get_or_create(user=user)
user_stats.recompute()
def for_user(self, user):
"""Shortcut to get (or create) a UserStats for a given user."""
user_stats, created = UserStats.objects.get_or_create(user=user)
if created:
user_stats.recompute()
return user_stats
class UserStats(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
points = models.FloatField(default=0) # Computed sum of solved exercise positions.
rank = models.PositiveIntegerField(blank=True, null=True)
objects = UserStatsQuerySet.as_manager()
def recompute(self):
self.points = sum(
exercise.position
for exercise in Exercise.objects.with_user_stats(user=self.user)
if exercise.user_successes
)
self.save()
self.rank = UserStats.objects.filter(points__gt=self.points).count() + 1
self.save()
class Exercise(models.Model):
title = models.CharField(max_length=255)
author = models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, null=True)
......
......@@ -18,14 +18,14 @@
{% endblocktrans %}
</p>
<p>
{% if rank is not None %}
{% blocktrans trimmed with rank=rank.rank %}
You're ranking {{ rank }} over {{ participants }} participants.
{% endblocktrans %}
{% if user.rank is not None %}
{% blocktrans trimmed with rank=user.rank %}
You're ranking {{ rank }} over {{ participants }} participants.
{% endblocktrans %}
{% else %}
{% blocktrans trimmed %}
You're not ranked yet.
{% endblocktrans %}
{% blocktrans trimmed %}
You're not ranked yet.
{% endblocktrans %}
{% endif %}
</p>
<h2>{% trans "Preferences" %}</h2>
......
......@@ -14,7 +14,7 @@ from django.utils.translation import gettext
from django.views.generic.detail import DetailView
from django.views.generic.edit import UpdateView
from django.views.generic.list import ListView
from website.models import Exercise, Answer, UserStats, User
from website.models import Exercise, Answer, User
from website.forms import AnswerForm
......@@ -61,7 +61,6 @@ class ProfileView(LoginRequiredMixin, UpdateView):
context["submit_qty"] = sum(
exercise.user_tries for exercise in context["exercises"]
)
context["rank"] = UserStats.objects.for_user(self.request.user)
context["participants"] = User.objects.count()
context["languages"] = settings.LANGUAGES
......@@ -147,13 +146,10 @@ class ExerciseView(DetailView):
}
)
context["object"].wording = gettext(context["object"].wording)
try:
if user.is_anonymous:
context["current_rank"] = 999999
else:
context["current_rank"] = self.request.user.userstats.rank
except User.userstats.RelatedObjectDoesNotExist:
if user.is_anonymous:
context["current_rank"] = 999999
else:
context["current_rank"] = self.request.user.rank
if user.is_anonymous:
context["is_valid"] = False
else:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment