[Checkins] SVN: lovely.rating/trunk/src/lovely/rating/ added support for timestamp based stats

Bernd Dorn bernd.dorn at lovelysystems.com
Fri Feb 9 09:01:01 EST 2007


Log message for revision 72483:
  added support for timestamp based stats

Changed:
  U   lovely.rating/trunk/src/lovely/rating/README.txt
  U   lovely.rating/trunk/src/lovely/rating/interfaces.py
  U   lovely.rating/trunk/src/lovely/rating/manager.py

-=-
Modified: lovely.rating/trunk/src/lovely/rating/README.txt
===================================================================
--- lovely.rating/trunk/src/lovely/rating/README.txt	2007-02-09 13:10:15 UTC (rev 72482)
+++ lovely.rating/trunk/src/lovely/rating/README.txt	2007-02-09 14:01:00 UTC (rev 72483)
@@ -102,6 +102,57 @@
   >>> sorted([rating.__repr__() for rating in manager.getRatings('usability')])
   ["<Rating u'Okay' by u'kartnaller'>", "<Rating u'Okay' by u'srichter'>"]
 
+The getRatings method supports filtering the ratings by timestamp.
+
+  >>> from datetime import datetime, timedelta
+  >>> from pytz import UTC
+  >>> now = datetime.now(UTC)
+  >>> oneDay = timedelta(days=1)
+
+Since we have created all ratings in this test all should be within
+this day and before now.
+
+  >>> ratings = manager.getRatings('usability', dtMax=now, dtMin=now-oneDay)
+  >>> len(sorted(ratings))
+  2
+
+The same result for an undefined dtMax or dtMin.
+
+  >>> ratings = manager.getRatings('usability', dtMin=now-oneDay)
+  >>> len(sorted(ratings))
+  2
+  >>> ratings = manager.getRatings('usability', dtMax=now)
+  >>> len(sorted(ratings))
+  2
+
+Let us set a timestamp on a rating just for testing (Note, this is
+private API)
+
+  >>> r = manager.getRatings('usability', dtMax=now)[0]
+  >>> r
+  <Rating u'Okay' by u'kartnaller'>
+  >>> r._timestamp = r._timestamp - oneDay
+  >>> twoDays = timedelta(days=2)
+  >>> threeHours = timedelta(hours=3)
+
+Get all ratings that are at most 3 hours old.
+
+  >>> ratings = manager.getRatings('usability', dtMin=now-threeHours)
+  >>> sorted(ratings)
+  [<Rating u'Okay' by u'srichter'>]
+  
+Get all ratings that are at least 3 hours old.
+
+  >>> ratings = manager.getRatings('usability', dtMax=now-threeHours)
+  >>> sorted(ratings)
+  [<Rating u'Okay' by u'kartnaller'>] 
+
+Get all ratings from the last two days.
+
+  >>> ratings = manager.getRatings('usability', dtMin=now-twoDays)
+  >>> sorted(ratings)
+  [<Rating u'Okay' by u'srichter'>, <Rating u'Okay' by u'kartnaller'>]
+
 You can also ask for the rating of a particular user:
 
   >>> manager.getRating('usability', u'srichter')
@@ -172,3 +223,6 @@
    ((u'Poor', Decimal("1")), 0),
    ((u'Crap', Decimal("0")), 0)]
 
+The computeAverage, countScores and countAmountRatings methods also
+support the dtMin and dtMax arguments as described in the getRatings
+method.

Modified: lovely.rating/trunk/src/lovely/rating/interfaces.py
===================================================================
--- lovely.rating/trunk/src/lovely/rating/interfaces.py	2007-02-09 13:10:15 UTC (rev 72482)
+++ lovely.rating/trunk/src/lovely/rating/interfaces.py	2007-02-09 14:01:00 UTC (rev 72483)
@@ -66,10 +66,13 @@
         If no rating exists, do nothing and simply return.
         """
 
-    def getRatings(id):
+    def getRatings(id, dtMin=None, dtMax=None):
         """Get all ratings for a particular definition.
 
         The result will be a sequence of ``IRating`` objects.
+
+        The optional dtMin and dtMax arguments can be used to filter
+        the result based on their timestamps
         """
 
     def getRating(id, user):
@@ -79,17 +82,17 @@
         a ``ValueError``.
         """
 
-    def computeAverage(id):
+    def computeAverage(id, dtMin=None, dtMax=None):
         """Compute the average rating value for the specified definition."""
 
-    def countScores(id):
+    def countScores(id, dtMin=None, dtMax=None):
         """Count how many times each value was giving for a definition.
 
         The result will be a list of tuples of the type ``(score,
         amount)``. ``score`` is in turn a tuple of ``(name, value)``.
         """
         
-    def countAmountRatings(id):
+    def countAmountRatings(id, dtMin=None, dtMax=None):
         """Counts the total amount of ratings for one definition"""
 
 

Modified: lovely.rating/trunk/src/lovely/rating/manager.py
===================================================================
--- lovely.rating/trunk/src/lovely/rating/manager.py	2007-02-09 13:10:15 UTC (rev 72482)
+++ lovely.rating/trunk/src/lovely/rating/manager.py	2007-02-09 14:01:00 UTC (rev 72483)
@@ -24,6 +24,7 @@
 from zope.app.container import contained
 
 from lovely.rating import IRatable, IRatingsManager, IRatingDefinition, rating
+import itertools
 
 class RatingsManager(contained.Contained, persistent.Persistent):
     zope.interface.implements(IRatingsManager)
@@ -71,28 +72,37 @@
             del self._storage[id]
         return True
 
-    def getRatings(self, id):
+    def getRatings(self, id, dtMin=None, dtMax=None):
         """See interfaces.IRatingsManager"""
         # Just get the definition to make sure it exists.
         defn = self._getDefinition(id)
+        ratings = list(self._storage.get(id, {}).values())
+        f = None
+        if dtMin is not None:
+            if dtMax is not None:
+                f = lambda r: r.timestamp>=dtMin and r.timestamp<=dtMax
+            else:
+                f = lambda r: r.timestamp>=dtMin
+        elif dtMax is not None:
+            f = lambda r: r.timestamp<=dtMax
+        if f:
+            ratings = itertools.ifilter(f, ratings)
+        return list(ratings)
 
-        return list(self._storage.get(id, {}).values())
-
     def getRating(self, id, user):
         """See interfaces.IRatingsManager"""
         # Just get the definition to make sure it exists.
         defn = self._getDefinition(id)
-
         if id not in self._storage or user not in self._storage[id]:
             return
 
         return self._storage[id][user]
 
-    def computeAverage(self, id):
+    def computeAverage(self, id, dtMin=None, dtMax=None):
         """See interfaces.IRatingsManager"""
         # Just get the definition to make sure it exists.
         defn = self._getDefinition(id)
-        ratings = self._storage.get(id, {}).values()
+        ratings = list(self.getRatings(id, dtMin, dtMax))
         total = sum([defn.scoreSystem.getNumericalValue(rating.value)
                     for rating in ratings])
         try:
@@ -100,21 +110,22 @@
         except ZeroDivisionError:
             return -1
 
-    def countScores(self, id):
+    def countScores(self, id, dtMin=None, dtMax=None):
         """See interfaces.IRatingsManager"""
         defn = self._getDefinition(id)
-
+        ratings = list(self._storage.get(id, {}).values())
         value_count = {}
-        for rating in self._storage.get(id, {}).values():
+        for rating in ratings:
             value_count.setdefault(rating.value, 0)
             value_count[rating.value] += 1
 
         return [(score, value_count.get(score[0], 0))
                 for score in defn.scoreSystem.scores]
 
-    def countAmountRatings(self, id):
+    def countAmountRatings(self, id, dtMin=None, dtMax=None):
         """See interfaces.IRatingManager"""
-        return len(self._storage.get(id, {}))
+        ratings = list(self._storage.get(id, {}).values())
+        return len(ratings)
         
 
     def __repr__(self):



More information about the Checkins mailing list