From 2f1c8e58502edf538d1b8f766ef96583c215f71f Mon Sep 17 00:00:00 2001 From: Gergely Polonkai Date: Fri, 27 Nov 2015 14:42:12 +0100 Subject: [PATCH] Extend draw_word() so it tries to draw a new one If the last word is rejected by the user, draw_word() tries to draw a new one now. --- words/apps.py | 30 ++++++++++++++++++++++++------ words/tests.py | 41 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 61 insertions(+), 10 deletions(-) diff --git a/words/apps.py b/words/apps.py index 3c51f10..763f572 100644 --- a/words/apps.py +++ b/words/apps.py @@ -40,21 +40,39 @@ def _draw_word(self): last_draw = self.last_draw() duration = parse_duration(settings.DRAW_TIME) - if last_draw.timestamp + duration > timezone.now(): + if last_draw is not None \ + and (last_draw.accepted is None + or last_draw.accepted == True) \ + and last_draw.timestamp + duration > timezone.now(): return last_draw.word # Find all words # Exclude all words that has an accepted draw for this user # Choose a random one # If there are no more words, return None - word = Word.objects \ - .exclude(draws__accepted=True, draws__user=self) \ - .order_by('?') \ - .first() + if last_draw is not None: + last_word = last_draw.word + else: + last_word = None - if word is None: + all_words = Word.objects.exclude(draws__accepted=True, draws__user=self) + all_count = all_words.count() + + # If there are no more words, return None + if all_count == 0: return None + # If there is only one word, return it, regardless if it’s the + # same as the last one + if all_count == 1: + word = all_words.first() + # Otherwise, choose a word different from the last one + else: + word = last_word + + while last_word == word: + word = all_words.order_by('?').first() + Draw.objects.create(user=self, word=word, accepted=None) return word diff --git a/words/tests.py b/words/tests.py index 5fb0ddb..cf69c80 100644 --- a/words/tests.py +++ b/words/tests.py @@ -79,13 +79,14 @@ class DrawTest(TestCase): @override_settings(DRAW_TIME='1 00:00:00') def test_draw_word(self): # User has no words yet - draw = Draw.objects.create(user=self.user, - word=self.word, - accepted=None) + self.assertEquals(self.word, self.user.draw_word()) + + # User now has an unaccepted draw self.assertEquals(self.word, self.user.draw_word()) # Accept the last word and make it appear as if it would be 2 # days ago + draw = Draw.objects.get(user=self.user, word=self.word) draw.accepted = True draw.timestamp -= timedelta(days=2) draw.save() @@ -106,11 +107,43 @@ class DrawTest(TestCase): draw.accepted = True draw.timestamp -= timedelta(days=2) draw.save() - Work.objects.create(draw=draw) + work = Work.objects.create(draw=draw) # As we are out of words now, a new draw should return None self.assertIsNone(self.user.draw_word()) + # Now set the last draw to fresh again, and remove the associated work. + draw.timestamp = timezone.now() + draw.save() + work.delete() + # Also create a new word + word3 = Word.objects.create() + + # A next draw should return the same word in this case + self.assertEquals(word2, self.user.draw_word()) + + # Now let’s reject this draw and draw a new one + draw = Draw.objects.get(user=self.user, word=word2) + draw.accepted = False + draw.save() + + # The next draw should be different from the last + self.assertEquals(word3, self.user.draw_word()) + + # Now make the previous one accepted and completed, and reject + # this last one + draw.accepted = True + draw.save() + Work.objects.create(draw=draw) + + draw = Draw.objects.get(user=self.user, word=word3) + draw.accepted = False + draw.save() + + # The next draw must be this last, rejected one (as there are + # no other options) + self.assertEquals(word3, self.user.draw_word()) + def test_last_draw(self): draw = Draw.objects.create( user=self.user,