Commit 2c00c7d077ff106cf94b0af346231c3e43d291bc
1 parent
c95e5d254d
Exists in
master
Refactored soem code. Moved study sorting into the User model
Showing 2 changed files with 33 additions and 33 deletions Side-by-side Diff
flashcards/models.py
View file @
2c00c7d
... | ... | @@ -12,11 +12,12 @@ |
12 | 12 | from django.db.models import * |
13 | 13 | from django.utils.log import getLogger |
14 | 14 | from django.utils.timezone import now, make_aware |
15 | -from flashy.settings import QUARTER_START | |
15 | +from flashy.settings import QUARTER_START, QUARTER_END | |
16 | 16 | from simple_email_confirmation import SimpleEmailConfirmationUserMixin |
17 | 17 | from fields import MaskField |
18 | 18 | from cached_property import cached_property |
19 | 19 | from flashy.settings import IN_PRODUCTION |
20 | +from math import e | |
20 | 21 | |
21 | 22 | # Hack to fix AbstractUser before subclassing it |
22 | 23 | |
... | ... | @@ -137,6 +138,30 @@ |
137 | 138 | self.email_address_set.confirm(confirmation_key, save=True) |
138 | 139 | self.confirmed_email = True |
139 | 140 | self.save() |
141 | + | |
142 | + def by_retention(self, sections, material_date_begin, material_date_end): | |
143 | + section_pks = map(lambda i: i['pk'], sections.values('pk')) | |
144 | + user_flashcard_filter = UserFlashcard.objects.filter( | |
145 | + user=self, flashcard__section__pk__in=section_pks, | |
146 | + flashcard__material_date__gte=material_date_begin, | |
147 | + flashcard__material_date__lte=material_date_end | |
148 | + ) | |
149 | + | |
150 | + if not user_flashcard_filter.exists(): | |
151 | + raise ValidationError("No matching flashcard found in your decks") | |
152 | + | |
153 | + return user_flashcard_filter.prefetch_related('userflashcardquiz_set').annotate( | |
154 | + study_count=Count('pk'), | |
155 | + days_since=Case( | |
156 | + When(userflashcardquiz__when=None, then=interval_days(Now(), F('pulled'))), | |
157 | + default=interval_days(Now(), Max('userflashcardquiz__when')), | |
158 | + output_field=FloatField() | |
159 | + ), | |
160 | + retention_score=Case( | |
161 | + default=Value(e, output_field=FloatField()) ** (F('days_since')*(-0.1/(F('study_count')+1))), | |
162 | + output_field=FloatField() | |
163 | + ) | |
164 | + ).order_by('retention_score') | |
140 | 165 | |
141 | 166 | |
142 | 167 | class UserFlashcard(Model): |
flashcards/views.py
View file @
2c00c7d
... | ... | @@ -19,13 +19,10 @@ |
19 | 19 | from django.core.mail import send_mail |
20 | 20 | from django.contrib.auth import authenticate |
21 | 21 | from django.contrib.auth.tokens import default_token_generator |
22 | -from django.db.models import Count, Max, F, Value, When, Case, DateTimeField, FloatField | |
23 | 22 | from rest_framework.status import HTTP_204_NO_CONTENT, HTTP_201_CREATED, HTTP_200_OK |
24 | 23 | from rest_framework.response import Response |
25 | 24 | from rest_framework.exceptions import AuthenticationFailed, NotAuthenticated, ValidationError, PermissionDenied |
26 | 25 | from simple_email_confirmation import EmailAddress |
27 | -from math import e | |
28 | -from django.utils.timezone import now | |
29 | 26 | |
30 | 27 | |
31 | 28 | def log_event(request, event=''): |
32 | 29 | |
33 | 30 | |
34 | 31 | |
35 | 32 | |
... | ... | @@ -394,38 +391,16 @@ |
394 | 391 | serializer = QuizRequestSerializer(data=request.data) |
395 | 392 | serializer.is_valid(raise_exception=True) |
396 | 393 | data = serializer.validated_data |
397 | - user_flashcard_filter = UserFlashcard.objects.filter( | |
398 | - user=request.user, flashcard__section__pk__in=data['sections'], | |
399 | - flashcard__material_date__gte=data['material_date_begin'], | |
400 | - flashcard__material_date__lte=data['material_date_end'] | |
401 | - ) | |
402 | 394 | |
403 | - if not user_flashcard_filter.exists(): | |
404 | - raise ValidationError("No matching flashcard found in your decks") | |
405 | - | |
406 | - quiz_filter = user_flashcard_filter.prefetch_related('userflashcardquiz_set').annotate( | |
407 | - study_count=Count('pk'), | |
408 | - days_since=Case( | |
409 | - When(userflashcardquiz__when=None, then=interval_days(Now(), F('pulled'))), | |
410 | - default=interval_days(Now(), Max('userflashcardquiz__when')), | |
411 | - output_field=FloatField() | |
412 | - ), | |
413 | - retention_score=Case( | |
414 | - default=Value(e, output_field=FloatField()) ** (F('days_since')*(-0.1/(F('study_count')+1))), | |
415 | - output_field=FloatField() | |
416 | - ) | |
417 | - ).order_by('retention_score') | |
418 | - | |
419 | - user_flashcard = quiz_filter.first() | |
395 | + user_flashcard = request.user.by_retention(**data).first() | |
420 | 396 | mask = user_flashcard.get_mask().get_random_blank() |
421 | - if not mask: | |
422 | - blanked_word = "" | |
423 | - log_event(request, mask) | |
424 | - else: | |
397 | + blanked_word = "" | |
398 | + if mask: | |
425 | 399 | blanked_word = user_flashcard.flashcard.text[slice(*mask)] |
426 | - user_flashcard_quiz = UserFlashcardQuiz(user_flashcard=user_flashcard, | |
427 | - blanked_word=blanked_word) | |
400 | + | |
401 | + user_flashcard_quiz = UserFlashcardQuiz(user_flashcard=user_flashcard, blanked_word=blanked_word) | |
428 | 402 | user_flashcard_quiz.save() |
403 | + | |
429 | 404 | response = QuizResponseSerializer(instance=user_flashcard_quiz, mask=mask) |
430 | 405 | log_event(request, response) |
431 | 406 | return Response(response.data, status=HTTP_200_OK) |