Skip to content

Commit 1c67200

Browse files
committed
Speed up RankingData population
1 parent 9399694 commit 1c67200

File tree

2 files changed

+37
-47
lines changed

2 files changed

+37
-47
lines changed

tigascoring/xp_scoring.py

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -610,38 +610,6 @@ def compute_user_score_in_xp_v2(user_uuid, update=False):
610610
return result
611611

612612

613-
def get_ranking_data( date_ini=None, date_end=datetime.datetime.today() ):
614-
retval = {}
615-
qs_reports = Report.objects.filter(creation_time__lte=datetime.datetime.today())
616-
if date_ini is not None:
617-
qs_reports = qs_reports.filter( creation_time__gte=date_ini )
618-
619-
uuid_replicas = get_uuid_replicas()
620-
qs_overall = TigaUser.objects.exclude(score_v2=0).exclude(user_UUID__in=uuid_replicas)
621-
622-
overall_df = pd.DataFrame(list(qs_overall.values_list('score_v2', 'user_UUID')), columns=['score_v2', 'user_UUID'])
623-
overall_sorted_df = overall_df.sort_values('score_v2', inplace=False)
624-
overall_sorted_df["rank"] = overall_sorted_df['score_v2'].rank(method='dense', ascending=False)
625-
overall_sorted_df.sort_values('rank', inplace=True)
626-
min_max_overall = get_min_max(overall_sorted_df, 'score_v2')
627-
min = min_max_overall['min']
628-
max = min_max_overall['max']
629-
retval['data'] = []
630-
for index, row in overall_sorted_df.iterrows():
631-
score = row['score_v2']
632-
user_class = get_user_class( max, min, score)
633-
retval['data'].append(
634-
{
635-
"score_v2": score,
636-
"user_uuid":row['user_UUID'],
637-
"identicon": '/media/identicons/' + row['user_UUID'] + '.png',
638-
"class": user_class,
639-
"rank": int(row['rank'])
640-
}
641-
)
642-
return retval
643-
644-
645613
def compute_all_user_scores():
646614
all_users = TigaUser.objects.all()
647615
for user in all_users:

util_scripts/init_ranking_data.py

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,49 @@
99
os.chdir(proj_path)
1010

1111
from django.core.wsgi import get_wsgi_application
12+
from django.db import transaction
13+
from django.db.models import Window, F, Min, Max
14+
from django.db.models.functions import DenseRank
15+
from django.utils import timezone
1216

1317
application = get_wsgi_application()
1418

15-
from tigascoring.xp_scoring import get_ranking_data
16-
from tigaserver_app.models import RankingData
17-
import datetime
19+
from tigascoring.xp_scoring import get_user_class
20+
from tigaserver_app.models import RankingData, TigaUser
1821

22+
@transaction.atomic
1923
def init_ranking_data():
20-
data = get_ranking_data()
24+
# Step 1: Clear existing ranking data
2125
RankingData.objects.all().delete()
22-
hydrated = []
23-
for d in data['data']:
24-
#hydrate models
25-
r = RankingData(
26-
user_uuid=d['user_uuid'],
27-
class_value=d['class']['value'],
28-
rank=d['rank'],
29-
score_v2=d['score_v2']
26+
27+
# Step 2: Get ranked users from TigaUser
28+
users_qs = TigaUser.objects.exclude(score_v2=0)
29+
ranked_users = users_qs.annotate(
30+
rank=Window(expression=DenseRank(), order_by=F('score_v2').desc())
31+
).order_by('-score_v2')
32+
33+
scores = users_qs.aggregate(
34+
min_score=Min('score_v2'),
35+
max_score=Max('score_v2')
36+
)
37+
min_score = scores['min_score']
38+
max_score = scores['max_score']
39+
40+
# Step 3: Populate RankingData
41+
last_update = timezone.now()
42+
ranking_data_instances = []
43+
for user in ranked_users.iterator():
44+
ranking_data_instances.append(
45+
RankingData(
46+
user_uuid=user.pk,
47+
class_value=get_user_class(min=min_score, max=max_score, user_score=user.score_v2)['value'],
48+
rank=user.rank,
49+
score_v2=user.score_v2,
50+
last_update=last_update
51+
)
3052
)
31-
hydrated.append(r)
32-
RankingData.objects.bulk_create(hydrated)
33-
RankingData.objects.all().update(last_update=datetime.datetime.now())
53+
54+
# Bulk create for efficiency
55+
RankingData.objects.bulk_create(ranking_data_instances)
3456

3557
init_ranking_data()

0 commit comments

Comments
 (0)