mirror of
https://gitlab.crans.org/bde/nk20
synced 2025-07-19 23:51:25 +02:00
Rank calculation optimized
This commit is contained in:
@ -1,7 +1,7 @@
|
|||||||
# Copyright (C) 2018-2025 by BDE ENS Paris-Saclay
|
# Copyright (C) 2018-2025 by BDE ENS Paris-Saclay
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
from django.urls import path
|
||||||
from .views import FamilyViewSet, FamilyMembershipViewSet, ChallengeViewSet, AchievementViewSet
|
from .views import FamilyViewSet, FamilyMembershipViewSet, ChallengeViewSet, AchievementViewSet, BatchAchievementsAPIView
|
||||||
|
|
||||||
|
|
||||||
def register_family_urls(router, path):
|
def register_family_urls(router, path):
|
||||||
@ -12,3 +12,7 @@ def register_family_urls(router, path):
|
|||||||
router.register(path + '/familymembership', FamilyMembershipViewSet)
|
router.register(path + '/familymembership', FamilyMembershipViewSet)
|
||||||
router.register(path + '/challenge', ChallengeViewSet)
|
router.register(path + '/challenge', ChallengeViewSet)
|
||||||
router.register(path + '/achievement', AchievementViewSet)
|
router.register(path + '/achievement', AchievementViewSet)
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('achievements/batch/', BatchAchievementsAPIView.as_view(), name='batch_achievements')
|
||||||
|
]
|
@ -4,6 +4,14 @@
|
|||||||
from api.viewsets import ReadProtectedModelViewSet
|
from api.viewsets import ReadProtectedModelViewSet
|
||||||
from django_filters.rest_framework import DjangoFilterBackend
|
from django_filters.rest_framework import DjangoFilterBackend
|
||||||
from rest_framework.filters import SearchFilter
|
from rest_framework.filters import SearchFilter
|
||||||
|
from rest_framework.views import APIView
|
||||||
|
from rest_framework.permissions import IsAuthenticated
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from rest_framework import status
|
||||||
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
|
from django.views.decorators.http import require_POST
|
||||||
|
from django.http import JsonResponse
|
||||||
|
import json
|
||||||
|
|
||||||
from .serializers import FamilySerializer, FamilyMembershipSerializer, ChallengeSerializer, AchievementSerializer
|
from .serializers import FamilySerializer, FamilyMembershipSerializer, ChallengeSerializer, AchievementSerializer
|
||||||
from ..models import Family, FamilyMembership, Challenge, Achievement
|
from ..models import Family, FamilyMembership, Challenge, Achievement
|
||||||
@ -59,3 +67,25 @@ class AchievementViewSet(ReadProtectedModelViewSet):
|
|||||||
filter_backends = [DjangoFilterBackend, SearchFilter]
|
filter_backends = [DjangoFilterBackend, SearchFilter]
|
||||||
filterset_fields = ['name', ]
|
filterset_fields = ['name', ]
|
||||||
search_fields = ['$name', ]
|
search_fields = ['$name', ]
|
||||||
|
|
||||||
|
|
||||||
|
class BatchAchievementsAPIView(APIView):
|
||||||
|
permission_classes = [IsAuthenticated]
|
||||||
|
def post(self, request, format=None):
|
||||||
|
print("POST de la view spéciale")
|
||||||
|
family_ids = request.data.get('families', [])
|
||||||
|
challenge_ids = request.data.get('challenges', [])
|
||||||
|
|
||||||
|
families = Family.objects.filter(id__in=family_ids)
|
||||||
|
challenges = Challenge.objects.filter(id__in=challenge_ids)
|
||||||
|
|
||||||
|
for family in families:
|
||||||
|
for challenge in challenges:
|
||||||
|
a = Achievement(family=family, challenge=challenge)
|
||||||
|
a.save(update_score=False)
|
||||||
|
|
||||||
|
for family in families:
|
||||||
|
family.update_score()
|
||||||
|
Family.update_ranking()
|
||||||
|
|
||||||
|
return Response({'status': 'ok'}, status=status.HTTP_201_CREATED)
|
@ -165,7 +165,7 @@ class Achievement(models.Model):
|
|||||||
return _('Challenge {challenge} carried out by Family {family}').format(challenge=self.challenge.name, family=self.family.name, )
|
return _('Challenge {challenge} carried out by Family {family}').format(challenge=self.challenge.name, family=self.family.name, )
|
||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, update_score=True, **kwargs):
|
||||||
"""
|
"""
|
||||||
When saving, also grants points to the family
|
When saving, also grants points to the family
|
||||||
"""
|
"""
|
||||||
@ -175,8 +175,9 @@ class Achievement(models.Model):
|
|||||||
|
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
self.family.refresh_from_db()
|
if update_score:
|
||||||
self.family.update_score()
|
self.family.refresh_from_db()
|
||||||
|
self.family.update_score()
|
||||||
|
|
||||||
# Count only when getting a new achievement
|
# Count only when getting a new achievement
|
||||||
if is_new:
|
if is_new:
|
||||||
|
@ -113,33 +113,47 @@ function reset () {
|
|||||||
* Apply all transactions: all notes in `notes` buy each item in `buttons`
|
* Apply all transactions: all notes in `notes` buy each item in `buttons`
|
||||||
*/
|
*/
|
||||||
function consumeAll () {
|
function consumeAll () {
|
||||||
console.log("consumeAll lancée")
|
|
||||||
if (LOCK) { return }
|
if (LOCK) { return }
|
||||||
|
|
||||||
LOCK = true
|
LOCK = true
|
||||||
|
|
||||||
let error = false
|
let error = false
|
||||||
|
|
||||||
if (notes_display.length === 0) {
|
if (notes_display.length === 0) {
|
||||||
document.getElementById('note').classList.add('is-invalid')
|
// ... gestion erreur ...
|
||||||
$('#note_list').html(li('', '<strong>Ajoutez des familles.</strong>', 'text-danger'))
|
|
||||||
error = true
|
error = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buttons.length === 0) {
|
if (buttons.length === 0) {
|
||||||
$('#consos_list').html(li('', '<strong>Ajoutez des défis.</strong>', 'text-danger'))
|
// ... gestion erreur ...
|
||||||
error = true
|
error = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
LOCK = false
|
LOCK = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
notes_display.forEach(function (family) {
|
// Récupérer les IDs des familles et des challenges
|
||||||
buttons.forEach(function (challenge) {
|
const family_ids = notes_display.map(fam => fam.id)
|
||||||
grantAchievement(family, challenge)
|
const challenge_ids = buttons.map(chal => chal.id)
|
||||||
})
|
|
||||||
|
$.ajax({
|
||||||
|
url: '/family/api/family/achievements/batch/',
|
||||||
|
type: 'POST',
|
||||||
|
data: JSON.stringify({
|
||||||
|
families: family_ids,
|
||||||
|
challenges: challenge_ids
|
||||||
|
}),
|
||||||
|
contentType: 'application/json',
|
||||||
|
headers: {
|
||||||
|
'X-CSRFToken': CSRF_TOKEN
|
||||||
|
},
|
||||||
|
success: function () {
|
||||||
|
reset()
|
||||||
|
addMsg("Défis validés pour les familles !", 'success', 5000)
|
||||||
|
},
|
||||||
|
error: function (e) {
|
||||||
|
reset()
|
||||||
|
addMsg("Erreur lors de la création des achievements.",'danger',5000)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# Copyright (C) 2018-2025 by BDE ENS Paris-Saclay
|
# Copyright (C) 2018-2025 by BDE ENS Paris-Saclay
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
from django.urls import path
|
from django.urls import path, include
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
@ -18,4 +18,5 @@ urlpatterns = [
|
|||||||
path('challenge/detail/<int:pk>/', views.ChallengeDetailView.as_view(), name="challenge_detail"),
|
path('challenge/detail/<int:pk>/', views.ChallengeDetailView.as_view(), name="challenge_detail"),
|
||||||
path('challenge/update/<int:pk>/', views.ChallengeUpdateView.as_view(), name="challenge_update"),
|
path('challenge/update/<int:pk>/', views.ChallengeUpdateView.as_view(), name="challenge_update"),
|
||||||
path('manage/', views.FamilyManageView.as_view(), name="manage"),
|
path('manage/', views.FamilyManageView.as_view(), name="manage"),
|
||||||
|
path('api/family/', include('family.api.urls')),
|
||||||
]
|
]
|
||||||
|
Reference in New Issue
Block a user