Commits

jiaaro  committed 6fdafe1

added progress support (optional) - added tests for ryanwitt's changes

  • Participants
  • Parent commits 93498c2

Comments (0)

Files changed (4)

+regexp:
+\.pyc$

File badges/__init__.py

-from utils import register, registered_badges, MetaBadge
+from utils import registered_badges, MetaBadge

File badges/utils.py

 from django.core.urlresolvers import reverse
 from django.db import models
 from django.db.models.signals import post_save
+from django.contrib.auth.models import User
 
 from badges.models import Badge as BadgeModel
-from badges.models import BadgeToUser
+from badges.models import BadgeToUser, LEVEL_CHOICES
 
-from django.contrib.auth.models import User
+
+class RequiresUserOrProgress(Exception): pass
 
 registered_badges = {}
 
     Example:
 
      >>> badge_count(User.objects.filter(username='admin'))
-     [{'count': 20, 'badge__level': u'1'}, {'count': 1, 'badge__level': u'2'}, {'count': 1, 'badge__level': u'3'}]
+     [{'count': 0, 'badge__level': '1'}, {'count': 0, 'badge__level': '2'}, {'count': 0, 'badge__level': '3'}, {'count': 0, 'badge__level': '4'}]
 
     Uses a single database query.
     """
-    kwargs = {}
-    if user_or_qs is None:
-        pass
-    elif isinstance(user_or_qs, User):
-        kwargs.update(dict(user=user_or_qs))
-    else:
-        kwargs.update(dict(user__in=user_or_qs))
 
-    return BadgeToUser.objects.filter(
-        **kwargs
-    ).values(
-        'badge__level',
-    ).annotate(
-        count=models.Count('badge__level'),
-    ).order_by('badge__level')
+    badge_counts = BadgeToUser.objects.all()
+    if isinstance(user_or_qs, User):
+        badge_counts = badge_counts.filter(user=user_or_qs)
+    elif isinstance(user_or_qs, models.QuerySet):
+        badge_counts = badge_counts.filter(user__in=user_or_qs)
+
+    badge_counts = badge_counts.values('badge__level')
+    badge_counts = badge_counts.annotate(count=models.Count('badge__level'))
+
+    def get_badge_count(level):
+        bc = [bc for bc in badge_counts if bc['badge__level'] == level]
+        if bc:
+            return bc[0]
+        else:
+            # if the user has no badges at this level, return the appropriate response
+            return {'count': 0, 'badge__level': level}
+                                        
+        
+    return [get_badge_count(level_choice[0]) for level_choice in LEVEL_CHOICES]
+        
 
 class MetaBadgeMeta(type):
     
     
     one_time_only = False
     model = models.Model
+
+    progress_start = 0
+    progress_finish = 1
     
     def __init__(self):
         # whenever the server is reloaded, the badge will be initialized and
     
     def get_user(self, instance):
         return instance.user
+
+    def get_progress(self, user):
+        if BadgeToUser.objects.filter(user=user, badge=self.badge).count():
+            return 1
+        return 0
+    
+    def get_progress_percentage(self, progress=None, user=None):
+        if user is None and progress is None:
+            raise RequiresUserOrProgress("This method requires either a user or progress keyword argument")
+
+        if not progress:
+            progress = self.get_progress(user)
+        
+        # multiply by a float to get floating point precision
+        return (100.0 * progress) / (self.progress_finish - self.progress_start)
     
     def _keep_badge_updated(self):
         if getattr(self, 'badge', False):

File test_project/badges_tests/tests.py

 from django.test import TestCase
 from django.contrib.auth.models import User
 
-from badges.utils import MetaBadge, registered_badges
+from badges.utils import MetaBadge, registered_badges, RequiresUserOrProgress
 from badges.utils import register as register_badge
 from badges.signals import badge_awarded
 from badges.models import Badge
+from badges.templatetags.badges_tags import badge_count, level_title, \
+    level_count, number_awarded
 
 class BadgeTests(TestCase):
     def setUp(self):
         register_badge(self.meta_badge)
         
         self.assertTrue(registered_badges[meta_badge.id] is meta_badge_instance)
+
+    def test_badge_progress(self):
+        badge = Badge.objects.get(id=self.meta_badge.id)
+
+        user = User(username='zodiac', first_name='john', last_name='doe')
+        user.save()
+
+        self.assertEqual(badge.meta_badge.get_progress(user), 0)
+        self.assertEqual(badge.meta_badge.get_progress_percentage(user=user), 0.0)
+        self.assertRaises(RequiresUserOrProgress, badge.meta_badge.get_progress_percentage)
+
+        user.email = "icanhasemailz@example.com"
+        user.save()
+
+        self.assertEqual(badge.meta_badge.get_progress(user), 1)
+        self.assertEqual(badge.meta_badge.get_progress_percentage(user=user), 100.0)        
         
     def test_badge_earned_signal(self):
         test_self = self
         self.assertTrue( isinstance(signal_handler_kwargs.get('sender'), self.meta_badge) )
         self.assertEqual(signal_handler_kwargs.get('user'), user)
         self.assertEqual(signal_handler_kwargs.get('badge'), Badge.objects.all()[0])
+
+    def test_template_tags(self):
+        badge = Badge.objects.get(id=self.meta_badge.id)
+
+        self.assertEqual(level_count(Badge.objects.all(), '1'), 1)
+        self.assertEqual(level_count(Badge.objects.all(), '2'), 0)
+
+        self.assertEqual(level_title(badge.level), "Bronze")
+
+        user = User(username='headcase', first_name='head', last_name='case')
+        user.save()
         
+        self.assertEqual(badge_count(user), [{'count': 0, 'badge__level': '1'}, {'count': 0, 'badge__level': '2'}, {'count': 0, 'badge__level': '3'}, {'count': 0, 'badge__level': '4'}])
+
+        user.email = "oops@example.com"
+        user.save()
+
+        self.assertEqual(badge_count(user), [{'count': 1, 'badge__level': '1'}, {'count': 0, 'badge__level': '2'}, {'count': 0, 'badge__level': '3'}, {'count': 0, 'badge__level': '4'}])        
         
         
         
-                
+