1010from posts .models import Post
1111from projects .models import Project
1212from questions .models import Question
13+ from questions .types import AggregationMethod
1314from scoring .models import Score , LeaderboardEntry , Leaderboard , MedalExclusionRecord
1415from scoring .score_math import evaluate_question
1516from utils .the_math .formulas import string_location_to_bucket_index
@@ -58,34 +59,33 @@ def generate_scoring_leaderboard_entries(
5859 questions : list [Question ],
5960 leaderboard : Leaderboard ,
6061) -> list [LeaderboardEntry ]:
61- # TODO: add aggregate scores
6262 scores : QuerySet [Score ] = Score .objects .filter (
63- user__isnull = False ,
6463 question__in = questions ,
6564 score_type = Leaderboard .ScoreTypes .get_base_score (leaderboard .score_type ),
6665 )
67- user_entries : dict [int , LeaderboardEntry ] = {}
66+ entries : dict [int | AggregationMethod , LeaderboardEntry ] = {}
6867 now = timezone .now ()
6968 for score in scores :
70- user_id = score .user_id
71- if user_id not in user_entries :
72- user_entries [user_id ] = LeaderboardEntry (
73- user_id = user_id ,
69+ identifier = score .user_id or score .aggregation_method
70+ if identifier not in entries :
71+ entries [identifier ] = LeaderboardEntry (
72+ user_id = score .user_id ,
73+ aggregation_method = score .aggregation_method ,
7474 score = 0 ,
7575 coverage = 0 ,
7676 contribution_count = 0 ,
7777 calculated_on = now ,
7878 )
79- user_entries [ user_id ].score += score .score
80- user_entries [ user_id ].coverage += score .coverage
81- user_entries [ user_id ].contribution_count += 1
79+ entries [ identifier ].score += score .score
80+ entries [ identifier ].coverage += score .coverage
81+ entries [ identifier ].contribution_count += 1
8282 if leaderboard .score_type == Leaderboard .ScoreTypes .PEER_GLOBAL :
83- for entry in user_entries .values ():
83+ for entry in entries .values ():
8484 entry .score /= max (30 , entry .coverage )
8585 elif leaderboard .score_type == Leaderboard .ScoreTypes .PEER_GLOBAL_LEGACY :
86- for entry in user_entries .values ():
86+ for entry in entries .values ():
8787 entry .score /= max (40 , entry .contribution_count )
88- return sorted (user_entries .values (), key = lambda entry : entry .score , reverse = True )
88+ return sorted (entries .values (), key = lambda entry : entry .score , reverse = True )
8989
9090
9191def generate_comment_insight_leaderboard_entries (
@@ -221,20 +221,27 @@ def update_project_leaderboard(
221221 start_time__lte = leaderboard .finalize_time
222222 )
223223 excluded_users = exclusion_records .values_list ("user" , flat = True )
224+ excluded_user_ids = set ([r .user .id for r in exclusion_records ])
224225 # medals
225226 golds = silvers = bronzes = 0
226227 if (
227228 (leaderboard .project .type != "question_series" )
228229 and leaderboard .finalize_time
229230 and (timezone .now () > leaderboard .finalize_time )
230231 ):
231- entry_count = len (new_entries )
232+ entry_count = len (
233+ [
234+ e
235+ for e in new_entries
236+ if (e .user_id and (e .user_id not in excluded_user_ids ))
237+ ]
238+ )
232239 golds = max (0.01 * entry_count , 1 )
233240 silvers = max (0.01 * entry_count , 1 )
234241 bronzes = max (0.03 * entry_count , 1 )
235242 rank = 1
236243 for entry in new_entries :
237- if entry .user . id in excluded_users :
244+ if ( entry .user_id is None ) or ( entry . user_id in excluded_users ) :
238245 entry .excluded = True
239246 entry .medal = None
240247 entry .rank = rank
@@ -251,7 +258,9 @@ def update_project_leaderboard(
251258 for new_entry in new_entries :
252259 new_entry .leaderboard = leaderboard
253260 for previous_entry in previous_entries :
254- if previous_entry .user == new_entry .user :
261+ if (previous_entry .user_id == new_entry .user_id ) and (
262+ previous_entry .aggregation_method == new_entry .aggregation_method
263+ ):
255264 new_entry .id = previous_entry .id
256265 seen .add (previous_entry )
257266 break
0 commit comments