Permalink
Browse files

added support for time limits on points_for_object

  • Loading branch information...
1 parent 018ed90 commit 8efb7cdc66fe6086ec4d9d5ef744943224091206 @paltman paltman committed Jan 29, 2011
Showing with 93 additions and 12 deletions.
  1. +12 −5 agon/models.py
  2. +32 −6 agon/templatetags/agon_tags.py
  3. +49 −1 agon/tests.py
View
@@ -207,7 +207,7 @@ def award_points(target, key, reason="", source=None):
return apv
-def points_awarded(target):
+def points_awarded(target, since=None):
"""
Determine out how many points the given target has recieved.
"""
@@ -222,7 +222,14 @@ def points_awarded(target):
"target_object_id": target.pk,
}
- try:
- return TargetStat.objects.get(**lookup_params).points
- except TargetStat.DoesNotExist:
- return 0
+ if since is None:
+ try:
+ return TargetStat.objects.get(**lookup_params).points
+ except TargetStat.DoesNotExist:
+ return 0
+ else:
+ return AwardedPointValue.objects.filter(
+ **lookup_params
+ ).filter(
+ timestamp__gte=since
+ ).aggregate(models.Sum("points")).get("points__sum", 0)
@@ -93,31 +93,53 @@ def top_objects(parser, token):
class PointsForObjectNode(template.Node):
+
@classmethod
def handle_token(cls, parser, token):
bits = token.split_contents()
if len(bits) == 2:
return cls(bits[1])
- elif len(bits) == 4 or len(bits) == 7:
+ elif len(bits) == 4:
# len(bits) == 7 will support interval timeframing
if bits[2] != "as":
- raise template.TemplateSyntaxError("Second argument to %r "
+ raise template.TemplateSyntaxError("Second argument to '%s' "
"should be 'as'" % bits[0])
- return cls(bits[1], bits[3])
- raise template.TemplateSyntaxError("%r takes 1 or 3 arguments." % bits[0])
+ return cls(bits[1], context_var=bits[3])
+ elif len(bits) == 7:
+ if bits[2] != "limit" and bits[5] != "as":
+ raise template.TemplateSyntaxError("Second argument to '%s' "
+ "should be 'as' and fifth argument should be 'limit" % bits[0])
+ return cls(
+ bits[1],
+ limit_num=bits[3],
+ limit_unit=bits[4],
+ context_var=bits[6]
+ )
+ raise template.TemplateSyntaxError("'%s' takes 1, 3, or 6 arguments." % bits[0])
- def __init__(self, obj, context_var=None):
+ def __init__(self, obj, context_var=None, limit_num=None, limit_unit=None):
self.obj = template.Variable(obj)
self.context_var = context_var
+ self.limit_num = limit_num
+ self.limit_unit = limit_unit
def render(self, context):
obj = self.obj.resolve(context)
- points = points_awarded(obj)
+
+ since = None
+ if self.limit_num is not None and self.limit_unit is not None:
+ since = datetime.datetime.now() - datetime.timedelta(
+ **{self.limit_unit: int(self.limit_num)}
+ )
+
+ points = points_awarded(obj, since=since)
+
if self.context_var is not None:
context[self.context_var] = points
return ""
return unicode(points)
+
@register.tag
def points_for_object(parser, token):
"""
@@ -128,5 +150,9 @@ def points_for_object(parser, token):
or
{% points_for_object user as points %}
+
+ or
+
+ {% points_for_object user limit 7 days as points %}
"""
return PointsForObjectNode.handle_token(parser, token)
View
@@ -1,3 +1,4 @@
+from datetime import timedelta
from threading import Thread
from django.conf import settings
@@ -332,4 +333,51 @@ def test_bad_model_arg(self):
self.assertEqual(str(e), "'auth.U' does not result in a model. Is it correct?")
-
+class PointsForObjectTagTestCase(BasePointsTestCase, TestCase):
+ """
+ points_for_object
+ """
+
+ def test_no_args(self):
+ try:
+ Template("{% load agon_tags %}{% points_for_object %}")
+ except TemplateSyntaxError, e:
+ self.assertEqual(str(e), "'points_for_object' takes 1, 3, or 6 arguments.")
+
+ def test_type_as(self):
+ try:
+ self.setup_users(1)
+ t = Template('{% load agon_tags %}{% points_for_object user a points %}')
+ t.render(Context({"user": self.users[0]}))
+ except TemplateSyntaxError, e:
+ self.assertEqual(str(e), "Second argument to 'points_for_object' should be 'as'")
+
+ def test_user_object_without_as(self):
+ self.setup_users(1)
+ award_points(self.users[0], 15)
+ t = Template('{% load agon_tags %}{% points_for_object user %} Points')
+ self.assertEqual(t.render(Context({"user": self.users[0]})), "15 Points")
+
+ def test_user_object_with_as(self):
+ self.setup_users(1)
+ award_points(self.users[0], 10)
+ t = Template('{% load agon_tags %}{% points_for_object user as points %}{{ points }} Points')
+ self.assertEqual(t.render(Context({"user": self.users[0]})), "10 Points")
+
+ def test_user_object_with_limit(self):
+ self.setup_users(1)
+ ap = award_points(self.users[0], 10)
+ ap.timestamp = ap.timestamp - timedelta(days=14)
+ ap.save()
+ award_points(self.users[0], 18)
+ t = Template('{% load agon_tags %}{% points_for_object user limit 7 days as points %}{{ points }} Points')
+ self.assertEqual(t.render(Context({"user": self.users[0]})), "18 Points")
+
+ def test_user_object_with_limit_30_days(self):
+ self.setup_users(1)
+ ap = award_points(self.users[0], 10)
+ ap.timestamp = ap.timestamp - timedelta(days=14)
+ ap.save()
+ award_points(self.users[0], 18)
+ t = Template('{% load agon_tags %}{% points_for_object user limit 30 days as points %}{{ points }} Points')
+ self.assertEqual(t.render(Context({"user": self.users[0]})), "28 Points")

0 comments on commit 8efb7cd

Please sign in to comment.