# Description: Add functions for the numbers of up and down votes; update docs
#  and tests
# Author: Bernhard Reiter <ockham@raz.or.at>
# Forwarded: http://code.google.com/p/django-voting/issues/detail?id=31

--- a/docs/overview.txt
+++ b/docs/overview.txt
@@ -76,13 +76,16 @@
       ``0`` (remove vote).
 
     * ``get_score(obj)`` -- Gets the total score for ``obj`` and the
-      total number of votes it's received.
+      total number of votes it's received, as well as the numbers of
+      up and down votes.
 
-      Returns a dictionary with ``score`` and ``num_votes`` keys.
+      Returns a dictionary with ``score``, ``num_votes``,
+      ``num_up_votes``, and ``num_down_votes`` keys.
 
     * ``get_scores_in_bulk(objects)`` -- Gets score and vote count
       details for all the given objects. Score details consist of a
-      dictionary which has ``score`` and ``num_vote`` keys.
+      dictionary which has ``score``, ``num_votes``, ``num_up_votes``,
+      and ``num_down_votes`` keys.
 
       Returns a dictionary mapping object ids to score details.
 
@@ -130,17 +133,17 @@
 helper function::
 
     >>> Vote.objects.get_score(widget)
-    {'score': 1, 'num_votes': 1}
+    {'score': 1, 'num_votes': 1, 'num_up_votes': 1, 'num_down_votes': 0}
 
 If the same user makes another vote on the same object, their vote
 is either modified or deleted, as appropriate::
 
     >>> Vote.objects.record_vote(widget, user, -1)
     >>> Vote.objects.get_score(widget)
-    {'score': -1, 'num_votes': 1}
+    {'score': -1, 'num_votes': 1, 'num_up_votes': 0, 'num_down_votes': 1}
     >>> Vote.objects.record_vote(widget, user, 0)
     >>> Vote.objects.get_score(widget)
-    {'score': 0, 'num_votes': 0}
+    {'score': 0, 'num_votes': 0, 'num_up_votes': 0, 'num_down_votes': 0}
 
 
 Generic Views
@@ -289,7 +292,9 @@
 
     * ``score``: an object containing a ``score`` property, which
       holds the object's updated score, and a ``num_votes`` property,
-      which holds the total number of votes cast for the object.
+      which holds the total number of votes cast for the object, as well
+      as a ``num_up_votes`` and a ``num_down_votes`` property holding
+      the numbers of up and down votes cast for the object, respectively.
 
     * ``error_message``: if the vote was not successfully processed,
       this property will contain an error message.
@@ -308,9 +313,10 @@
 score_for_object
 ~~~~~~~~~~~~~~~~
 
-Retrieves the total score for an object and the number of votes
-it's received, storing them in a context variable which has ``score``
-and ``num_votes`` properties.
+Retrieves the total score for an object and the numbers of total,
+up, and down votes it's received, storing them in a context variable
+which has ``score``, ``num_votes``, ``num_up_votes``, and
+``num_down_votes`` properties.
 
 Example usage::
 
@@ -322,9 +328,9 @@
 scores_for_objects
 ~~~~~~~~~~~~~~~~~~
 
-Retrieves the total scores and number of votes cast for a list of
-objects as a dictionary keyed with the objects' ids and stores it in a
-context variable.
+Retrieves the total scores and numbers of total, up and down votes cast
+for a list of objects as a dictionary keyed with the objects' ids and
+stores it in a context variable.
 
 Example usage::
 
--- a/voting/managers.py
+++ b/voting/managers.py
@@ -52,6 +52,8 @@
         return {
             'score': int(result[0]),
             'num_votes': int(result[1]),
+            'num_up_votes': (int(result[1])+int(result[0]))/2,
+            'num_down_votes': (int(result[1])-int(result[0]))/2,
         }
 
     def get_scores_in_bulk(self, objects):
@@ -92,6 +94,8 @@
             vote_dict[row['object_id']] = {
                 'score': int(row['score']),
                 'num_votes': int(row['num_votes']),
+                'num_up_votes': (int(row['num_votes'])+int(row['score']))/2,
+                'num_down_votes': (int(row['num_votes'])-int(row['score']))/2,
             }
 
         return vote_dict
--- a/voting/tests/tests.py
+++ b/voting/tests/tests.py
@@ -14,28 +14,28 @@
 >>> for username in ['u1', 'u2', 'u3', 'u4']:
 ...     users.append(User.objects.create_user(username, '%s@test.com' % username, 'test'))
 >>> Vote.objects.get_score(i1)
-{'score': 0, 'num_votes': 0}
+{'num_up_votes': 0, 'score': 0, 'num_down_votes': 0, 'num_votes': 0}
 >>> Vote.objects.record_vote(i1, users[0], +1)
 >>> Vote.objects.get_score(i1)
-{'score': 1, 'num_votes': 1}
+{'num_up_votes': 1, 'score': 1, 'num_down_votes': 0, 'num_votes': 1}
 >>> Vote.objects.record_vote(i1, users[0], -1)
 >>> Vote.objects.get_score(i1)
-{'score': -1, 'num_votes': 1}
+{'num_up_votes': 0, 'score': -1, 'num_down_votes': 1, 'num_votes': 1}
 >>> Vote.objects.record_vote(i1, users[0], 0)
 >>> Vote.objects.get_score(i1)
-{'score': 0, 'num_votes': 0}
+{'num_up_votes': 0, 'score': 0, 'num_down_votes': 0, 'num_votes': 0}
 >>> for user in users:
 ...     Vote.objects.record_vote(i1, user, +1)
 >>> Vote.objects.get_score(i1)
-{'score': 4, 'num_votes': 4}
+{'num_up_votes': 4, 'score': 4, 'num_down_votes': 0, 'num_votes': 4}
 >>> for user in users[:2]:
 ...     Vote.objects.record_vote(i1, user, 0)
 >>> Vote.objects.get_score(i1)
-{'score': 2, 'num_votes': 2}
+{'num_up_votes': 2, 'score': 2, 'num_down_votes': 0, 'num_votes': 2}
 >>> for user in users[:2]:
 ...     Vote.objects.record_vote(i1, user, -1)
 >>> Vote.objects.get_score(i1)
-{'score': 0, 'num_votes': 4}
+{'num_up_votes': 2, 'score': 0, 'num_down_votes': 2, 'num_votes': 4}
 
 >>> Vote.objects.record_vote(i1, user, -2)
 Traceback (most recent call last):
@@ -80,7 +80,7 @@
 [(<Item: test3>, -4), (<Item: test4>, -3), (<Item: test2>, -2)]
 
 >>> Vote.objects.get_scores_in_bulk([i1, i2, i3, i4])
-{1: {'score': 0, 'num_votes': 4}, 2: {'score': -2, 'num_votes': 4}, 3: {'score': -4, 'num_votes': 4}, 4: {'score': -3, 'num_votes': 3}}
+{1: {'num_up_votes': 2, 'score': 0, 'num_down_votes': 2, 'num_votes': 4}, 2: {'num_up_votes': 1, 'score': -2, 'num_down_votes': 3, 'num_votes': 4}, 3: {'num_up_votes': 0, 'score': -4, 'num_down_votes': 4, 'num_votes': 4}, 4: {'num_up_votes': 0, 'score': -3, 'num_down_votes': 3, 'num_votes': 3}}
 >>> Vote.objects.get_scores_in_bulk([])
 {}
 """
