Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move auto_annotate logic into ExpertReportAnnotation model #271

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 81 additions & 23 deletions tigacrafting/models.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import copy
from typing import Optional

from django.db import models

from django.db import models
from django.db.utils import IntegrityError
from django.contrib.auth import get_user_model
from datetime import datetime, timedelta
from django.core.validators import MaxValueValidator, MinValueValidator
Expand All @@ -12,6 +13,8 @@
import tigacrafting.html_utils as html_utils
import pytz

from .messages import other_insect_msg_dict, albopictus_msg_dict, albopictus_probably_msg_dict, culex_msg_dict, notsure_msg_dict

User = get_user_model()

def score_computation(n_total, n_yes, n_no, n_unknown = 0, n_undefined =0):
Expand Down Expand Up @@ -414,6 +417,42 @@
result = '<span class="label label-default" style="background-color:' + ('red' if self.get_score() == 2 else ('orange' if self.get_score() == 1 else ('white' if self.get_score() == 0 else ('grey' if self.get_score() == -1 else 'black')))) + ';">' + self.get_category() + '</span>'
return result

def _can_be_simplified(self) -> bool:
# If the user is the superexpert -> False
if self.user.userstat.is_superexpert():
return False

# If the user is the supervisor of that country -> False
if self.user.userstat.national_supervisor_of:
if self.user.userstat.national_supervisor_of == self.report.country:
return False

MAX_N_OF_EXPERTS_ASSIGNED_PER_REPORT = 3

# Return False if no simplified_annotation found or if the objects to be
# created is suposed to be the last.
total_completed_annotations_qs = self.report.expert_report_annotations.all()
return (
total_completed_annotations_qs.filter(simplified_annotation=False).exists() or
total_completed_annotations_qs.count() < MAX_N_OF_EXPERTS_ASSIGNED_PER_REPORT - 1
)

def _get_auto_message(self) -> Optional[str]:
report_locale = self.report.app_language

msg_dict = other_insect_msg_dict
if not self.category:
return msg_dict.get(report_locale or 'en')

if self.category.pk == 4: # albopictus
msg_dict = albopictus_msg_dict if self.validation_value == self.VALIDATION_CATEGORY_DEFINITELY else albopictus_probably_msg_dict
elif self.category.pk == 10: # culex
msg_dict = culex_msg_dict
elif self.category.pk == 9: # not sure
msg_dict = notsure_msg_dict

return msg_dict.get(report_locale or 'en')

def save(self, *args, **kwargs):
if not kwargs.pop('skip_lastmodified', False):
self.last_modified = timezone.now()
Expand All @@ -427,38 +466,57 @@
if self.category.pk == 5: # aegypti
self.aegypti_certainty_category = 2

# On create only
if self._state.adding:
if not self.edited_user_notes:
self.edited_user_notes = self._get_auto_message() or ""

self.simplified_annotation = self._can_be_simplified()
if self.simplified_annotation:
self.message_for_user = ""
self.best_photo = None

super(ExpertReportAnnotation, self).save(*args, **kwargs)

if self.validation_complete and self.validation_complete_executive:
cloned_instance = copy.deepcopy(self)
cloned_instance.simplified_annotation = True
cloned_instance.tiger_certainty_notes = 'exec_auto'
cloned_instance.validation_complete = True
cloned_instance.validation_complete_executive = False
cloned_instance.best_photo = None
cloned_instance.edited_user_notes = ""
cloned_instance.message_for_user = ""
cloned_instance.revise = False

for dummy_user in User.objects.filter(username__in=["innie", "minnie"]):
replica_usernames = ["innie", "minnie"]
if self.user.userstat.is_superexpert():
replica_usernames.append('manny')
else:
try:
cloned_instance.pk = None
cloned_instance.user = dummy_user
cloned_instance.save()
except IntegrityError:
# Case unique constraint raises
ExpertReportAnnotation.objects.update_or_create(

Check warning on line 487 in tigacrafting/models.py

View check run for this annotation

Codecov / codecov/patch

tigacrafting/models.py#L487

Added line #L487 was not covered by tests
user=User.objects.get(username="super_reritja"),
report=self.report,
defaults={
"validation_complete": True
}
)
except User.DoesNotExist:

Check warning on line 494 in tigacrafting/models.py

View check run for this annotation

Codecov / codecov/patch

tigacrafting/models.py#L494

Added line #L494 was not covered by tests
pass

try:
fieldnames = [
field.name for field in ExpertReportAnnotation._meta.fields if field.name not in ('id', 'user', 'report')
]
obj_dict = {
fname: getattr(self, fname) for fname in fieldnames
}
for dummy_user in User.objects.filter(username__in=replica_usernames):
ExpertReportAnnotation.objects.update_or_create(
user=User.objects.get(username="super_reritja"),
user=dummy_user,
report=self.report,
defaults={
"validation_complete": True
**obj_dict,
'tiger_certainty_category': self.tiger_certainty_category,
'simplified_annotation': True,
'tiger_certainty_notes': 'exec_auto',
'validation_complete': True,
'validation_complete_executive': False,
'best_photo': None,
'edited_user_notes': "",
'message_for_user': "",
'revise': False
}
)
except User.DoesNotExist:
pass

def delete(self, *args, **kwargs):
if self.validation_complete_executive:
Expand Down
68 changes: 11 additions & 57 deletions tigacrafting/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,6 @@

#-----------------------------------#

from .messages import culex_msg_dict as culex
from .messages import albopictus_msg_dict as albopictus
from .messages import albopictus_probably_msg_dict as albopictus_probably
from .messages import notsure_msg_dict as notsure
from .messages import other_insect_msg_dict as other_insect
from .messaging import send_finished_validation_notification

logger_notification = logging.getLogger('mosquitoalert.notification')
Expand Down Expand Up @@ -1134,58 +1129,17 @@ def auto_annotate(
category: Categories,
validation_value: Optional[Literal[ExpertReportAnnotation.VALIDATION_CATEGORY_PROBABLY, ExpertReportAnnotation.VALIDATION_CATEGORY_DEFINITELY]]
) -> ExpertReportAnnotation:

tiger_aegypti_cert_to_cat = {
"4": { "t": 2, "a": -2 }, #albopictus
"5": { "t": -2, "a": 2 } #aegypti
}
try:
cats = tiger_aegypti_cert_to_cat[str(category.id)]
except KeyError:
cats = {"t": -2, "a": -2}
users = []
users.append(User.objects.get(username="innie"))
users.append(User.objects.get(username="minnie"))
users.append(User.objects.get(username="manny"))
super_reritja = User.objects.get(username="super_reritja")
photo = report.photos.first()
report_locale = report.app_language
if category.id == 4: #albopictus
if str(validation_value) == "2":
user_notes = albopictus.get(report_locale, albopictus['en'])
else:
user_notes = albopictus_probably.get(report_locale, albopictus_probably['en'])
elif category.id == 10: #culex
user_notes = culex.get(report_locale, culex['en'])
elif category.id == 9: # not sure
user_notes = notsure.get(report_locale, notsure['en'])
else: #other_insect
user_notes = other_insect.get(report_locale, other_insect['en'])
for u in users:
if not ExpertReportAnnotation.objects.filter(report=report).filter(user=u).exists():
new_annotation = ExpertReportAnnotation(report=report, user=u)
if u.username == 'innie':
new_annotation.edited_user_notes = user_notes
new_annotation.best_photo_id = photo.id
new_annotation.simplified_annotation = False
else:
new_annotation.simplified_annotation = True
new_annotation.tiger_certainty_notes = 'auto'
new_annotation.tiger_certainty_category = cats['t']
new_annotation.aegypti_certainty_category = cats['a']
new_annotation.status = 1
new_annotation.category = category
new_annotation.validation_complete = True
if category.specify_certainty_level:
new_annotation.validation_value = validation_value
new_annotation.save()
try:
roger_annotation = ExpertReportAnnotation.objects.get(user=super_reritja, report=report)
except ExpertReportAnnotation.DoesNotExist:
roger_annotation = ExpertReportAnnotation(user=super_reritja, report=report)

roger_annotation.validation_complete = True
roger_annotation.save()
roger_annotation, _ = ExpertReportAnnotation.objects.get_or_create(
user=User.objects.get(username="super_reritja"),
report=report,
defaults={
'category': category,
'validation_value': int(validation_value) if validation_value else None,
'validation_complete': True,
'validation_complete_executive': True,
'best_photo': report.photos.first(),
}
)

send_finished_validation_notification(roger_annotation)

Expand Down
Loading