From de3f801d9b665c69303f3b80a2147d5399dc77b3 Mon Sep 17 00:00:00 2001 From: lsabor Date: Fri, 30 Aug 2024 13:10:07 -0700 Subject: [PATCH 1/2] update comment and question writing leaderboard calculations --- posts/views.py | 2 +- scoring/models.py | 23 +++++++++++++++---- scoring/utils.py | 57 ++++++++++++++++++++++++++++++++++------------- scoring/views.py | 11 ++++++--- 4 files changed, 70 insertions(+), 23 deletions(-) diff --git a/posts/views.py b/posts/views.py index b53e2048f9..266a32dceb 100644 --- a/posts/views.py +++ b/posts/views.py @@ -469,6 +469,6 @@ def post_related_articles_api_view(request: Request, pk): ObjectPermission.can_view(permission, raise_exception=True) # Retrieve cached articles - articles = get_post_get_similar_articles(post) + articles = [] # get_post_get_similar_articles(post) return Response(PostRelatedArticleSerializer(articles, many=True).data) diff --git a/scoring/models.py b/scoring/models.py index 721cf82dbc..a6da02444c 100644 --- a/scoring/models.py +++ b/scoring/models.py @@ -146,13 +146,28 @@ def get_questions(self) -> list[Question]: elif self.score_type == self.ScoreTypes.QUESTION_WRITING: # post must be published, and can't be resolved before the start_time # of the leaderboard + from posts.models import Post + + invalid_statuses = [ + Post.CurationStatus.DELETED, + Post.CurationStatus.DRAFT, + Post.CurationStatus.REJECTED, + ] return list( questions.filter( Q(post__published_at__lt=self.end_time) - | Q(group__post__published_at__lt=self.end_time), - Q(actual_resolve_time__gte=self.start_time) - | Q(actual_resolve_time__isnull=True), - ).distinct() + | Q(group__post__published_at__lt=self.end_time) + | Q(conditional_yes__post__published_at__lt=self.end_time) + | Q(conditional_no__post__published_at__lt=self.end_time), + # Q(scheduled_close_time__gte=self.start_time), + ) + .exclude( + Q(post__curation_status__in=invalid_statuses) + | Q(group__post__curation_status__in=invalid_statuses) + | Q(conditional_yes__post__curation_status__in=invalid_statuses) + | Q(conditional_no__post__curation_status__in=invalid_statuses), + ) + .distinct() ) if self.start_time and self.end_time: diff --git a/scoring/utils.py b/scoring/utils.py index a82d387574..02423a7162 100644 --- a/scoring/utils.py +++ b/scoring/utils.py @@ -133,6 +133,12 @@ def generate_comment_insight_leaderboard_entries( posts = Post.objects.filter( Q(projects=leaderboard.project) | Q(default_project=leaderboard.project) + ).exclude( + curation_status__in=[ + Post.CurationStatus.REJECTED, + Post.CurationStatus.DRAFT, + Post.CurationStatus.DELETED, + ] ) comments = Comment.objects.filter( on_post__in=posts, @@ -175,13 +181,14 @@ def generate_question_writing_leaderboard_entries( for question in questions: forecasts_during_period = question.user_forecasts.filter( start_time__gte=leaderboard.start_time, - start_time__lte=min( - [ - leaderboard.end_time, - question.actual_close_time or question.scheduled_close_time, - question.actual_resolve_time or question.scheduled_resolve_time, - ] - ), + # start_time__lte=min( + # [ + # leaderboard.end_time, + # question.actual_close_time or question.scheduled_close_time, + # question.actual_resolve_time or question.scheduled_resolve_time, + # ] + # ), + start_time__lte=leaderboard.end_time, ) forecasters = set([forecast.author_id for forecast in forecasts_during_period]) post = question.get_post() @@ -264,7 +271,7 @@ def update_project_leaderboard( excluded_users = exclusion_records.values_list("user", flat=True) excluded_user_ids = set([r.user.id for r in exclusion_records]) # medals - golds = silvers = bronzes = 0 + gold_rank = silver_rank = bronze_rank = 0 if ( (leaderboard.project.type != "question_series") and leaderboard.finalize_time @@ -277,23 +284,42 @@ def update_project_leaderboard( if (e.user_id and (e.user_id not in excluded_user_ids)) ] ) - golds = max(0.01 * entry_count, 1) - silvers = max(0.01 * entry_count, 1) - bronzes = max(0.03 * entry_count, 1) + gold_rank = max(np.ceil(0.01 * entry_count), 1) + silver_rank = max(np.ceil(0.02 * entry_count), 2) + bronze_rank = max(np.ceil(0.05 * entry_count), 3) rank = 1 + prev_entry = None for entry in new_entries: if (entry.user_id is None) or (entry.user_id in excluded_users): entry.excluded = True entry.medal = None entry.rank = rank + if ( + leaderboard.score_type + == Leaderboard.ScoreTypes.RELATIVE_LEGACY_TOURNAMENT + ): + if prev_entry and (entry.take == prev_entry.take): + entry.rank = prev_entry.rank + else: + if prev_entry and (entry.score == prev_entry.score): + entry.rank = prev_entry.rank continue - if rank <= golds: + if rank <= gold_rank: entry.medal = LeaderboardEntry.Medals.GOLD - elif rank <= golds + silvers: + elif rank <= silver_rank: entry.medal = LeaderboardEntry.Medals.SILVER - elif rank <= golds + silvers + bronzes: + elif rank <= bronze_rank: entry.medal = LeaderboardEntry.Medals.BRONZE entry.rank = rank + if leaderboard.score_type == Leaderboard.ScoreTypes.RELATIVE_LEGACY_TOURNAMENT: + if prev_entry and (entry.take == prev_entry.take): + entry.rank = prev_entry.rank + entry.medal = prev_entry.medal + else: + if prev_entry and (entry.score == prev_entry.score): + entry.rank = prev_entry.rank + entry.medal = prev_entry.medal + prev_entry = entry rank += 1 for new_entry in new_entries: @@ -383,7 +409,8 @@ def get_contributions( contributions.append(contribution) h_index = decimal_h_index([c.score / 10 for c in contributions]) contributions = sorted(contributions, key=lambda c: c.score, reverse=True) - return contributions[: int(h_index) + 1] + # return contributions[: int(h_index) + 1] + return contributions archived_scores = list( ArchivedScore.objects.filter( diff --git a/scoring/views.py b/scoring/views.py index 4d64adba7a..e69cc1f151 100644 --- a/scoring/views.py +++ b/scoring/views.py @@ -7,6 +7,8 @@ import scipy import numpy as np +from django.db.models import Q + from posts.models import Post from questions.models import AggregateForecast, Question from questions.types import AggregationMethod @@ -51,8 +53,11 @@ def global_leaderboard( leaderboard_data = LeaderboardSerializer(leaderboard).data user = request.user - entries = leaderboard.entries.select_related("user").order_by("rank") - entries = entries.filter(rank__lte=max(3, entries.count() * 0.05)) + entries = leaderboard.entries.select_related("user").order_by("rank", "-score") + entries = entries.filter( + Q(medal__isnull=False) + | Q(rank__lte=max(3, np.ceil(entries.exclude(excluded=True).count() * 0.05))) + ) if not user.is_staff: entries = entries.filter(excluded=False) @@ -102,7 +107,7 @@ def project_leaderboard( # serialize leaderboard_data = LeaderboardSerializer(leaderboard).data - entries = leaderboard.entries.order_by("rank").select_related("user") + entries = leaderboard.entries.order_by("rank", "-score").select_related("user") user = request.user if not user.is_staff: From 5216e368a4ecbf2dd9108474658177bbae06b5be Mon Sep 17 00:00:00 2001 From: lsabor Date: Fri, 30 Aug 2024 13:11:31 -0700 Subject: [PATCH 2/2] remove temp override --- posts/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/posts/views.py b/posts/views.py index 266a32dceb..b53e2048f9 100644 --- a/posts/views.py +++ b/posts/views.py @@ -469,6 +469,6 @@ def post_related_articles_api_view(request: Request, pk): ObjectPermission.can_view(permission, raise_exception=True) # Retrieve cached articles - articles = [] # get_post_get_similar_articles(post) + articles = get_post_get_similar_articles(post) return Response(PostRelatedArticleSerializer(articles, many=True).data)