Skip to content

Commit 24ff70f

Browse files
committed
Added TigaUser.update_score
1 parent 7df07d4 commit 24ff70f

File tree

7 files changed

+72
-219
lines changed

7 files changed

+72
-219
lines changed

requirements/prod_20_04.pip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ MarkupSafe==1.1.1
5959
matplotlib==2.0.2
6060
msgpack==1.0.2
6161
numpy==1.23.1
62+
numpyencoder==0.3.0
6263
odfpy==1.4.0
6364
openapi-codec==1.3.2
6465
openpyxl==3.0.0

stats/views.py

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,11 @@
2121
import json
2222
import datetime
2323
from django.utils import timezone
24-
from tigascoring.xp_scoring import compute_user_score_in_xp_v2, get_ranking_data
2524
from rest_framework.exceptions import ParseError
2625
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
2726
import math
2827
from django.utils import translation
2928

30-
from tigascoring.xp_scoring import compute_user_score_in_xp_v2, get_ranking_data, compute_user_score_in_xp_v2_fast
3129
from rest_framework.exceptions import ParseError
3230
from django.core.paginator import Paginator
3331
import math
@@ -641,13 +639,8 @@ def stats_user_score(request, user_uuid=None):
641639
pass
642640

643641
if user.score_v2_struct is None:
644-
user_score = compute_user_score_in_xp_v2(user_uuid, update=True)
645-
user.score_v2_struct = json.dumps(user_score, indent=2, sort_keys=True, default=str)
646-
user.last_score_update = datetime.datetime.now()
647-
user.save()
648-
else:
649-
user_score = json.loads(user.score_v2_struct)
650-
context = { "score_data": user_score, "score_last_update": user.last_score_update }
642+
user.update_score(commit=True)
643+
context = { "score_data": user.score_v2_struct, "score_last_update": user.last_score_update }
651644
return render(request, 'stats/user_score.html', context)
652645

653646

@@ -679,17 +672,11 @@ def stats_user_ranking(request, page=1, user_uuid=None):
679672
try:
680673
user = TigaUser.objects.get(pk=user_uuid)
681674
user.get_identicon()
682-
#user_score = compute_user_score_in_xp_v2(user_uuid, update=True)
683-
if user.score_v2_struct is None:
684-
user_score = compute_user_score_in_xp_v2(user_uuid, update=True)
685-
user.score_v2_struct = json.dumps(user_score, indent=2, sort_keys=True, default=str)
686-
user.last_score_update = datetime.datetime.now()
687-
user.save()
688-
else:
689-
user_score = json.loads( user.score_v2_struct )
690-
if user_score['total_score'] > 0:
691-
user_has_score = True
692675

676+
if user.score_v2_struct is None:
677+
user.update_score(commit=True)
678+
user_score = user.score_v2_struct
679+
user_has_score = bool(user.score_v2)
693680
except TigaUser.DoesNotExist:
694681
pass
695682
seek = request.GET.get('seek', 'f')
@@ -1060,13 +1047,9 @@ def get_user_xp_data(request):
10601047
translation.activate(locale)
10611048

10621049
if u.score_v2_struct is None:
1063-
retval = compute_user_score_in_xp_v2(user_id, update=True)
1064-
u.score_v2_struct = json.dumps(retval, indent=2, sort_keys=True, default=str)
1065-
u.last_score_update = datetime.datetime.now()
1066-
u.save()
1067-
else:
1068-
retval = json.loads(u.score_v2_struct)
1050+
u.update_score(commit=True)
10691051

1052+
retval = u.score_v2_struct
10701053
retval['last_update'] = u.last_score_update
10711054

10721055
return Response(retval)

tigascoring/xp_scoring.py

Lines changed: 1 addition & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -357,80 +357,6 @@ def get_unrelated_awards_score( user_uuid, user_uuids ):
357357
# return str(diff.days) + _(" days ago")
358358

359359

360-
def compute_user_score_in_xp_v2_fast(user_uuid):
361-
362-
user = TigaUser.objects.get(pk=user_uuid)
363-
user_uuids = None
364-
if user.profile is not None:
365-
user_uuids = TigaUser.objects.filter(profile=user.profile).values('user_UUID')
366-
367-
result = {}
368-
result['total_score'] = 0
369-
result['user_uuid'] = user_uuid
370-
result['score_detail'] = {}
371-
372-
if user_uuids is None:
373-
user_reports = Report.objects.filter(user__user_UUID=user_uuid).order_by('-creation_time')
374-
else:
375-
user_reports = Report.objects.filter(user__user_UUID__in=user_uuids).order_by('-creation_time')
376-
377-
adults = user_reports.filter(type='adult')
378-
#bites = user_reports.filter(type='bite')
379-
sites = user_reports.filter(type='site')
380-
381-
adult_last_versions = filter(lambda x: not x.deleted and x.latest_version, adults)
382-
#bite_last_versions = filter(lambda x: not x.deleted and x.latest_version, bites)
383-
site_last_versions = filter(lambda x: not x.deleted and x.latest_version, sites)
384-
385-
results_adult = {}
386-
results_adult['score'] = 0
387-
results_adult['score_items'] = []
388-
result['score_detail']['adult'] = results_adult
389-
390-
adult_score = 0
391-
for report in adult_last_versions:
392-
result = get_adult_report_score(report, result)
393-
index = len(result['score_detail']['adult']['score_items']) - 1
394-
result['score_detail']['adult']['score'] += result['score_detail']['adult']['score_items'][index][
395-
'report_score']
396-
adult_score += result['score_detail']['adult']['score_items'][index]['report_score']
397-
result['total_score'] += adult_score
398-
399-
'''
400-
results_bite = {}
401-
results_bite['score'] = 0
402-
results_bite['score_items'] = []
403-
result['score_detail']['bite'] = results_bite
404-
405-
bite_score = 0
406-
for report in bite_last_versions:
407-
result = get_bite_report_score(report, result)
408-
index = len(result['score_detail']['bite']['score_items']) - 1
409-
result['score_detail']['bite']['score'] += result['score_detail']['bite']['score_items'][index]['report_score']
410-
bite_score += result['score_detail']['bite']['score_items'][index]['report_score']
411-
result['total_score'] += bite_score
412-
'''
413-
414-
results_site = {}
415-
results_site['score'] = 0
416-
results_site['score_items'] = []
417-
result['score_detail']['site'] = results_site
418-
419-
site_score = 0
420-
for report in site_last_versions:
421-
result = get_site_report_score(report, result)
422-
index = len(result['score_detail']['site']['score_items']) - 1
423-
result['score_detail']['site']['score'] += result['score_detail']['site']['score_items'][index]['report_score']
424-
site_score += result['score_detail']['site']['score_items'][index]['report_score']
425-
result['total_score'] += site_score
426-
427-
unrelated_score = get_unrelated_awards_score(user_uuid, user_uuids)
428-
429-
result['total_score'] += unrelated_score['score']
430-
431-
return result
432-
433-
434360
def get_uuid_replicas():
435361
profiles = TigaProfile.objects.all()
436362
exclude = []
@@ -444,7 +370,7 @@ def get_uuid_replicas():
444370
return exclude
445371

446372

447-
def compute_user_score_in_xp_v2(user_uuid, update=False):
373+
def compute_user_score_in_xp_v2(user_uuid):
448374

449375
user = TigaUser.objects.get(pk=user_uuid)
450376
user_uuids = None
@@ -620,18 +546,6 @@ def compute_user_score_in_xp_v2(user_uuid, update=False):
620546
result['score_detail']['site']['top_perc'] = (float(site_number_below_rank) / float(site_number_total)) * 100.0
621547
result['score_detail']['site']['ranked_users'] = site_number_total
622548

623-
if update:
624-
if user_uuids is not None:
625-
all_users_in_profile = TigaUser.objects.filter(user_UUID__in=user_uuids)
626-
all_users_in_profile.update(score_v2=result['total_score'])
627-
all_users_in_profile.update(score_v2_adult=result['score_detail']['adult']['score'])
628-
all_users_in_profile.update(score_v2_site=result['score_detail']['site']['score'])
629-
else:
630-
user.score_v2 = result['total_score']
631-
user.score_v2_adult = result['score_detail']['adult']['score']
632-
user.score_v2_site = result['score_detail']['site']['score']
633-
user.save()
634-
635549
'''
636550
if bite_number_below_rank == 0 and bite_number_total == 0:
637551
result['score_detail']['bite']['top_perc'] = 100.0
@@ -675,14 +589,6 @@ def get_ranking_data( date_ini=None, date_end=datetime.datetime.today() ):
675589
return retval
676590

677591

678-
def compute_all_user_scores():
679-
all_users = TigaUser.objects.all()
680-
for user in all_users:
681-
score = compute_user_score_in_xp_v2( user.user_UUID )
682-
user.score_v2 = score
683-
user.save()
684-
685-
686592
def get_all_user_reports(user_uuid):
687593
user = TigaUser.objects.get(pk=user_uuid)
688594
user_uuids = None
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Generated by Django 2.2.7 on 2024-03-15 11:50
2+
3+
import django.contrib.postgres.fields.jsonb
4+
from django.db import migrations
5+
import numpyencoder.numpyencoder
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
('tigaserver_app', '0044_refactor'),
11+
]
12+
13+
operations = [
14+
migrations.AlterField(
15+
model_name='tigauser',
16+
name='score_v2_struct',
17+
field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, encoder=numpyencoder.numpyencoder.NumpyEncoder, help_text='Full cached score data', null=True),
18+
),
19+
]

tigaserver_app/models.py

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import json
44
import logging
55
from math import floor
6+
from numpyencoder import NumpyEncoder
67
from PIL import Image
78
import pydenticon
89
import os
@@ -16,14 +17,14 @@
1617
from django.contrib.gis.db.models.functions import Distance as DistanceFunction
1718
from django.contrib.gis.geos import GEOSGeometry
1819
from django.contrib.gis.measure import Distance as DistanceMeasure
20+
from django.contrib.postgres.fields import JSONField
1921
from django.db.models import Count, Q
2022
from django.db.models.signals import post_save
2123
from django.dispatch import receiver
2224
from django.template.loader import render_to_string, TemplateDoesNotExist
2325
from django.urls import reverse
24-
from django.utils import translation
26+
from django.utils import translation, timezone
2527
from django.utils.deconstruct import deconstructible
26-
from django.utils.timezone import utc
2728
from django.utils.translation import ugettext_lazy as _
2829

2930
from common.translation import get_translation_in, get_locale_for_native
@@ -214,7 +215,9 @@ class TigaUser(models.Model):
214215

215216
profile = models.ForeignKey(TigaProfile, related_name='profile_devices', null=True, blank=True, on_delete=models.SET_NULL, )
216217

217-
score_v2_struct = models.TextField(help_text="Full cached score data", null=True, blank=True)
218+
# NOTE using NumpyEncoder since compute_user_score_in_xp_v2 function get result from pandas dataframe
219+
# and some integer are np.int64, which can not be encoded with the regular json library setup.
220+
score_v2_struct = JSONField(encoder=NumpyEncoder, help_text="Full cached score data", null=True, blank=True)
218221

219222
last_score_update = models.DateTimeField(help_text="Last time score was updated", null=True, blank=True)
220223

@@ -237,6 +240,34 @@ def get_identicon(self):
237240
f.close()
238241
return settings.MEDIA_URL + "identicons/" + self.user_UUID + ".png"
239242

243+
def update_score(self, commit: bool = True) -> None:
244+
# NOTE: placing import here due to circular import
245+
from tigascoring.xp_scoring import compute_user_score_in_xp_v2
246+
247+
score_dict = compute_user_score_in_xp_v2(user_uuid=self.pk)
248+
self.score_v2_struct = score_dict
249+
250+
try:
251+
self.score_v2_adult = score_dict['score_detail']['adult']['score']
252+
except (KeyError, TypeError):
253+
self.score_v2_adult = 0
254+
255+
try:
256+
self.score_v2_bite = score_dict['score_detail']['bite']['score']
257+
except (KeyError, TypeError):
258+
self.score_v2_bite = 0
259+
260+
try:
261+
self.score_v2_site = score_dict['score_detail']['site']['score']
262+
except (KeyError, TypeError):
263+
self.score_v2_site = 0
264+
265+
self.score_v2 = sum([self.score_v2_adult, self.score_v2_bite, self.score_v2_site])
266+
self.last_score_update = timezone.now()
267+
268+
if commit:
269+
self.save()
270+
240271
n_reports = property(number_of_reports_uploaded)
241272
ios_user = property(is_ios)
242273

@@ -302,7 +333,7 @@ def __unicode__(self):
302333
return self.title_catalan
303334

304335
def active_missions(self):
305-
return self.expiration_time >= datetime.utcnow().replace(tzinfo=utc)
336+
return self.expiration_time >= datetime.utcnow().replace(tzinfo=timezone.utc)
306337

307338

308339
class MissionTrigger(models.Model):

tigaserver_app/views.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
from tigacrafting.messaging import send_message_ios, send_message_android, send_messages_ios, send_messages_android, generic_send_to_topic
3333
from tigacrafting.criteria import users_with_pictures,users_with_storm_drain_pictures, users_with_score, users_with_score_range, users_with_topic
3434
from tigascoring.maUsers import smmry
35-
from tigascoring.xp_scoring import compute_user_score_in_xp_v2
3635
from tigaserver_app.serializers import custom_render_notification,score_label
3736
import tigaserver_project.settings as conf
3837
import copy
@@ -1202,8 +1201,8 @@ def user_score_v2(request):
12021201
if user_id == -1:
12031202
raise ParseError(detail='user_id is mandatory')
12041203
user = get_object_or_404(TigaUser.objects.all(), pk=user_id)
1205-
result = compute_user_score_in_xp_v2(user_id, update=True)
1206-
return Response(result)
1204+
user.update_score(commit=True)
1205+
return Response(user.score_v2_struct)
12071206

12081207

12091208
@api_view(['GET', 'POST'])

0 commit comments

Comments
 (0)