-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add leaderboard and overview of achievements (#3686)
* Add leaderboard for overall score * Update achievement score, make percentage cached * Update achievement_score * Implement pagination achievements * Fix tests
- Loading branch information
1 parent
47454c3
commit 36170fa
Showing
9 changed files
with
140 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
from lego.utils.pagination import CursorPagination | ||
|
||
|
||
class AchievementLeaderboardPagination(CursorPagination): | ||
page_size = 25 | ||
max_page_size = 25 | ||
ordering = "-achievements_score" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
from lego.apps.achievements.constants import ( | ||
EVENT_IDENTIFIER, | ||
EVENT_PRICE_IDENTIFIER, | ||
EVENT_RANK_IDENTIFIER, | ||
MEETING_IDENTIFIER, | ||
PENALTY_IDENTIFIER, | ||
POLL_IDENTIFIER, | ||
QUOTE_IDENTIFIER, | ||
) | ||
|
||
ACHIEVEMENT_RARITIES = { | ||
EVENT_IDENTIFIER: [0, 1, 2, 3, 4, 6], | ||
EVENT_RANK_IDENTIFIER: [7, 8, 9], | ||
QUOTE_IDENTIFIER: [1], | ||
EVENT_PRICE_IDENTIFIER: [2, 3, 5], | ||
MEETING_IDENTIFIER: [1], | ||
POLL_IDENTIFIER: [0, 2, 4], | ||
PENALTY_IDENTIFIER: [0, 3, 5, 6], | ||
} | ||
|
||
delta = 0.1 | ||
# Remember to update this rarity list when adding new achievement | ||
MAX_POSSIBLE_SCORE = sum( | ||
max(rarity_list) + 1 + (max(rarity_list) * delta) | ||
for key, rarity_list in ACHIEVEMENT_RARITIES.items() | ||
if key != EVENT_RANK_IDENTIFIER | ||
) | ||
|
||
|
||
def calculate_user_rank(user): | ||
score = 0.0 | ||
if not user.achievements.exists(): | ||
return 0 | ||
user_achievements = user.achievements.all() | ||
for achievement in user_achievements: | ||
rarity_list = ACHIEVEMENT_RARITIES.get(achievement.identifier, []) | ||
|
||
value = rarity_list[achievement.level] | ||
score += value + 1 + (achievement.level * delta) | ||
|
||
return score if MAX_POSSIBLE_SCORE else 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
from rest_framework import mixins, permissions, viewsets | ||
from rest_framework.response import Response | ||
|
||
from lego.apps.achievements.pagination import AchievementLeaderboardPagination | ||
from lego.apps.users.models import User | ||
from lego.apps.users.serializers.users import PublicUserWithGroupsSerializer | ||
|
||
|
||
class LeaderBoardViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): | ||
serializer_class = PublicUserWithGroupsSerializer | ||
permission_classes = [permissions.IsAuthenticated] | ||
pagination_class = AchievementLeaderboardPagination | ||
|
||
def get_queryset(self): | ||
return ( | ||
User.objects.filter(achievements__isnull=False) | ||
.order_by("-achievements_score") | ||
.distinct() | ||
) | ||
|
||
def list(self, request, *args, **kwargs): | ||
queryset = self.get_queryset() | ||
page = self.paginate_queryset(queryset) | ||
if page is not None: | ||
serializer = self.get_serializer(page, many=True) | ||
return self.get_paginated_response(serializer.data) | ||
serializer = self.get_serializer(queryset, many=True) | ||
return Response(serializer.data) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
from django.apps import apps | ||
from django.db import migrations, models | ||
|
||
|
||
def populate_achievements_score(apps, schema_editor): | ||
from lego.apps.achievements.utils.calculation_utils import calculate_user_rank | ||
|
||
User = apps.get_model("users", "User") | ||
|
||
for user in User.objects.all(): | ||
user.achievements_score = calculate_user_rank(user) | ||
user.save(update_fields=["achievements_score"]) | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
("users", "0044_alter_membership_role_alter_membershiphistory_role"), | ||
] | ||
|
||
operations = [ | ||
migrations.AddField( | ||
model_name="user", | ||
name="achievements_score", | ||
field=models.FloatField(default=0), | ||
), | ||
migrations.RunPython(populate_achievements_score), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters