summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeny Fadeev <evgeny.fadeev@gmail.com>2010-12-05 02:59:33 -0500
committerEvgeny Fadeev <evgeny.fadeev@gmail.com>2010-12-05 02:59:33 -0500
commita5871f943c857aae905be1791bc37ffd0618e923 (patch)
tree66d2ba2dff7542549e1b883e866edcc2b488dd68
parent031818d0b9bce845c9b59b43d55b70b1df35f8a1 (diff)
downloadaskbot-a5871f943c857aae905be1791bc37ffd0618e923.tar.gz
askbot-a5871f943c857aae905be1791bc37ffd0618e923.tar.bz2
askbot-a5871f943c857aae905be1791bc37ffd0618e923.zip
more badges
-rw-r--r--askbot/conf/badges.py18
-rw-r--r--askbot/models/__init__.py15
-rw-r--r--askbot/models/badges.py88
-rw-r--r--askbot/models/question.py14
-rw-r--r--askbot/tests/badge_tests.py62
-rw-r--r--askbot/views/users.py16
6 files changed, 190 insertions, 23 deletions
diff --git a/askbot/conf/badges.py b/askbot/conf/badges.py
index 3654da4d..85602e3a 100644
--- a/askbot/conf/badges.py
+++ b/askbot/conf/badges.py
@@ -183,3 +183,21 @@ settings.register(
description=_('Associate Editor: minimum number of edits')
)
)
+
+settings.register(
+ IntegerValue(
+ BADGES,
+ 'FAVORITE_QUESTION_BADGE_MIN_STARS',
+ default=3,
+ description=_('Favorite Question: minimum stars')
+ )
+)
+
+settings.register(
+ IntegerValue(
+ BADGES,
+ 'STELLAR_QUESTION_BADGE_MIN_STARS',
+ default=5,
+ description=_('Stellar Question: minimum stars')
+ )
+)
diff --git a/askbot/models/__init__.py b/askbot/models/__init__.py
index ea20300e..93a8790d 100644
--- a/askbot/models/__init__.py
+++ b/askbot/models/__init__.py
@@ -734,6 +734,12 @@ def user_retag_question(
tagnames = tags,
silent = silent
)
+ award_badges_signal.send(None,
+ event = 'retag_question',
+ actor = self,
+ context_object = question,
+ timestamp = timestamp
+ )
@auto_now_timestamp
def user_accept_best_answer(self, answer = None, timestamp = None):
@@ -1330,6 +1336,7 @@ def toggle_favorite_question(self, question, timestamp=None, cancel=False):
fave = FavoriteQuestion.objects.get(question=question, user=self)
fave.delete()
result = False
+ question.update_favorite_count()
except FavoriteQuestion.DoesNotExist:
if timestamp is None:
timestamp = datetime.datetime.now()
@@ -1340,7 +1347,13 @@ def toggle_favorite_question(self, question, timestamp=None, cancel=False):
)
fave.save()
result = True
- Question.objects.update_favorite_count(question)
+ question.update_favorite_count()
+ award_badges_signal.send(None,
+ event = 'select_favorite_question',
+ actor = self,
+ context_object = question,
+ timestamp = timestamp
+ )
return result
VOTES_TO_EVENTS = {
diff --git a/askbot/models/badges.py b/askbot/models/badges.py
index 363d290a..791dbd10 100644
--- a/askbot/models/badges.py
+++ b/askbot/models/badges.py
@@ -24,6 +24,7 @@ from django.utils.translation import gettext as _
from django.dispatch import Signal
from askbot.models.repute import BadgeData, Award
from askbot.models.user import Activity
+from askbot.models.question import FavoriteQuestion as Fave#name collision
from askbot import const
from askbot.conf import settings as askbot_settings
from askbot.utils.decorators import auto_now_timestamp
@@ -625,16 +626,80 @@ class AssociateEditor(EditorTypeBadge):
self.description = _('Edited %(num)s entries') % {'num': self.min_edits}
return self
+class Organizer(Badge):
+ def __init__(self):
+ super(Organizer, self).__init__(
+ key = 'organizer',
+ name = _('Organizer'),
+ level = const.BRONZE_BADGE,
+ multiple = False,
+ description = _('First retag')
+ )
-ORIGINAL_DATA = """
- (_('Organizer'), 3, _('organizer'), _('First retag'), False, 0),
+class Autobiographer(Badge):
+ def __init__(self):
+ super(Autobiographer, self).__init__(
+ key = 'autobiographer',
+ name = _('Autobiographer'),
+ level = const.BRONZE_BADGE,
+ multiple = False,
+ description = _('Completed all user profile fields')
+ )
+
+ def consider_award(self, actor = None,
+ context_object = None, timestamp = None):
+ user = context_object
+ if user.email and user.real_name and user.website \
+ and user.location and user.about:
+ return self.award(user, user, timestamp)
+ return False
+
+class FavoriteTypeBadge(Badge):
+ """subclass must use __new__ and in addition
+ must provide min_stars property for the badge
+ """
+ def __init__(self):
+ descr = _('Question favorited by %(num)s users')
+ super(FavoriteTypeBadge, self).__init__(
+ key = self.key,
+ name = self.name,
+ level = self.level,
+ multiple = True,
+ description = descr % {'num': self.min_stars}
+ )
- (_('Autobiographer'), 3, _('autobiographer'), _('Completed all user profile fields'), False, 0),
+ def consider_award(self, actor = None,
+ context_object = None, timestamp = None):
+ question = context_object
+ #model FavoriteQuestion imported under alias of Fave
+ count = Fave.objects.filter(
+ question = question
+ ).exclude(
+ user = question.author
+ ).count()
+ if count == self.min_stars:
+ return self.award(question.author, question, timestamp)
+ return False
- (_('Stellar Question'), 1, _('stellar-question'), _('Question favorited by 100 users'), True, 0),
- (_('Favorite Question'), 2, _('favorite-question'), _('Question favorited by 25 users'), True, 0),
+class StellarQuestion(FavoriteTypeBadge):
+ def __new__(cls):
+ self = super(StellarQuestion, cls).__new__(cls)
+ self.key = 'stellar-question'
+ self.name = _('Stellar Question')
+ self.level = const.GOLD_BADGE
+ self.min_stars = askbot_settings.STELLAR_QUESTION_BADGE_MIN_STARS
+ return self
+class FavoriteQuestion(FavoriteTypeBadge):
+ def __new__(cls):
+ self = super(FavoriteQuestion, cls).__new__(cls)
+ self.key = 'favorite-question'
+ self.name = _('Favorite Question')
+ self.level = const.SILVER_BADGE
+ self.min_stars = askbot_settings.FAVORITE_QUESTION_BADGE_MIN_STARS
+ return self
+ORIGINAL_DATA = """
(_('Generalist'), 2, _('generalist'), _('Active in many different tags'), False, 0),
(_('Expert'), 2, _('expert'), _('Very active in one tag'), False, 0),
(_('Taxonomist'), 2, _('taxonomist'), _('Created a tag used by 50 questions'), True, 0)
@@ -646,6 +711,7 @@ ORIGINAL_DATA = """
BADGES = {
'strunk-and-white': AssociateEditor,#legacy slug name
+ 'autobiographer': Autobiographer,
'critic': Critic,
'citizen-patrol': CitizenPatrol,
'civic-duty': CivicDuty,
@@ -654,6 +720,7 @@ BADGES = {
'editor': Editor,
'enlightened': Enlightened,
'famous-question': FamousQuestion,
+ 'favorite-question': FavoriteQuestion,
'good-answer': GoodAnswer,
'good-question': GoodQuestion,
'great-answer': GreatAnswer,
@@ -663,6 +730,7 @@ BADGES = {
'nice-answer': NiceAnswer,
'nice-question': NiceQuestion,
'notable-question': NotableQuestion,
+ 'organizer': Organizer,
'peer-pressure': PeerPressure,
'popular-question': PopularQuestion,
'pundit': Pundit,
@@ -670,6 +738,7 @@ BADGES = {
'student': Student,
'supporter': Supporter,
'self-learner': SelfLearner,
+ 'stellar-question': StellarQuestion,
'teacher': Teacher,
}
@@ -678,9 +747,15 @@ BADGES = {
#most likely - from manipulator functions that are added to the User objects
EVENTS_TO_BADGES = {
'accept_best_answer': (Scholar, Guru, Enlightened),
+ 'delete_post': (Disciplined, PeerPressure,),
+ 'downvote': (Critic, CivicDuty),#no regard for question or answer for now
'edit_answer': (Editor, AssociateEditor),
'edit_question': (Editor, AssociateEditor),
'flag_post': (CitizenPatrol,),
+ 'post_answer': (Necromancer,),
+ 'retag_question': (Organizer,),
+ 'select_favorite_question': (FavoriteQuestion, StellarQuestion,),
+ 'update_user_profile': (Autobiographer,),
'upvote_answer': (
Teacher, NiceAnswer, GoodAnswer,
GreatAnswer, Supporter, SelfLearner, CivicDuty,
@@ -690,9 +765,6 @@ EVENTS_TO_BADGES = {
NiceQuestion, GoodQuestion,
GreatQuestion, Student, Supporter, CivicDuty
),
- 'downvote': (Critic, CivicDuty),#no regard for question or answer for now
- 'delete_post': (Disciplined, PeerPressure,),
- 'post_answer': (Necromancer,),
'view_question': (PopularQuestion, NotableQuestion, FamousQuestion,),
}
diff --git a/askbot/models/question.py b/askbot/models/question.py
index e4a0e799..e3bf5882 100644
--- a/askbot/models/question.py
+++ b/askbot/models/question.py
@@ -281,11 +281,6 @@ class QuestionManager(models.Manager):
"""
self.filter(id=question.id).update(view_count = question.view_count + 1)
- def update_favorite_count(self, question):
- """
- update favourite_count for given question
- """
- self.filter(id=question.id).update(favourite_count = FavoriteQuestion.objects.filter(question=question).count())
class Question(content.Content, DeletableContent):
post_type = 'question'
@@ -328,6 +323,15 @@ class Question(content.Content, DeletableContent):
self.answer_count = self.get_answers().count()
if save:
self.save()
+
+ def update_favorite_count(self):
+ """
+ update favourite_count for given question
+ """
+ self.favourite_count = FavoriteQuestion.objects.filter(
+ question=self
+ ).count()
+ self.save()
def get_similar_questions(self):
diff --git a/askbot/tests/badge_tests.py b/askbot/tests/badge_tests.py
index 516270f8..e8fe8bcc 100644
--- a/askbot/tests/badge_tests.py
+++ b/askbot/tests/badge_tests.py
@@ -3,6 +3,7 @@ from django.test.client import Client
from askbot.tests.utils import AskbotTestCase
from askbot.conf import settings
from askbot import models
+from askbot.models.badges import award_badges_signal
class BadgeTests(AskbotTestCase):
@@ -13,6 +14,9 @@ class BadgeTests(AskbotTestCase):
self.client = Client()
def assert_have_badge(self, badge_key, recipient = None, expected_count = 1):
+ """note - expected_count matches total number of
+ badges within test, not the one that was awarded between the calls
+ to this assertion"""
filters = {'badge__slug': badge_key, 'user': recipient}
count = models.Award.objects.filter(**filters).count()
self.assertEquals(count, expected_count)
@@ -407,3 +411,61 @@ class BadgeTests(AskbotTestCase):
revision_comment = 'sdgdfgsgfs'
)
self.assert_have_badge('strunk-and-white', self.u2, 1)
+
+ def test_organizer_badge(self):
+ question = self.post_question(user = self.u1)
+ self.u1.retag_question(question = question, tags = 'blah boom')
+ self.assert_have_badge('organizer', self.u1, 1)
+ self.u1.retag_question(question = question, tags = 'blah pooh')
+ self.assert_have_badge('organizer', self.u1, 1)
+
+ def test_autobiographer_badge(self):
+ self.u1.real_name = 'blah'
+ self.u1.website = 'cnn.com'
+ self.u1.location = 'irvine'
+ self.u1.about = 'blah'
+ self.u1.save()
+ award_badges_signal.send(None,
+ event = 'update_user_profile',
+ actor = self.u1,
+ context_object = self.u1
+ )
+ self.assert_have_badge('autobiographer', self.u1, 1)
+ award_badges_signal.send(None,
+ event = 'update_user_profile',
+ actor = self.u1,
+ context_object = self.u1
+ )
+ self.assert_have_badge('autobiographer', self.u1, 1)
+
+ def test_stellar_badge1(self):
+ question = self.post_question(user = self.u1)
+ settings.update('STELLAR_QUESTION_BADGE_MIN_STARS', 2)
+ self.u2.toggle_favorite_question(question)
+ self.assert_have_badge('stellar-question', self.u1, 0)
+ self.u3.toggle_favorite_question(question)
+ self.assert_have_badge('stellar-question', self.u1, 1)
+
+ def test_stellar_badge2(self):
+ question = self.post_question(user = self.u1)
+ settings.update('STELLAR_QUESTION_BADGE_MIN_STARS', 2)
+ self.u2.toggle_favorite_question(question)
+ self.assert_have_badge('stellar-question', self.u1, 0)
+ self.u1.toggle_favorite_question(question)
+ """no gaming"""
+ self.assert_have_badge('stellar-question', self.u1, 0)
+
+ def test_stellar_badge3(self):
+ question = self.post_question(user = self.u1)
+ settings.update('STELLAR_QUESTION_BADGE_MIN_STARS', 2)
+ self.u2.toggle_favorite_question(question)
+ self.assert_have_badge('stellar-question', self.u1, 0)
+ self.u3.toggle_favorite_question(question)
+ #award now
+ self.assert_have_badge('stellar-question', self.u1, 1)
+ self.u3.toggle_favorite_question(question)
+ #dont take back
+ self.assert_have_badge('stellar-question', self.u1, 1)
+ self.u3.toggle_favorite_question(question)
+ #dont reaward
+ self.assert_have_badge('stellar-question', self.u1, 1)
diff --git a/askbot/views/users.py b/askbot/views/users.py
index 51103f91..fd1836f4 100644
--- a/askbot/views/users.py
+++ b/askbot/views/users.py
@@ -32,7 +32,7 @@ from askbot import const
from askbot.conf import settings as askbot_settings
from askbot import models
from askbot import exceptions
-from askbot.models import signals
+from askbot.models.badges import award_badges_signal
from askbot.skins.loaders import ENV
from askbot.templatetags import extra_tags
@@ -262,14 +262,12 @@ def edit_user(request, id):
user.about = sanitize_html(form.cleaned_data['about'])
user.save()
- # send user updated singal if full fields have been updated
- if user.email and user.real_name and user.website \
- and user.location and user.date_of_birth and user.about:
- signals.user_updated.send(
- sender=user.__class__,
- instance=user,
- updated_by=user
- )
+ # send user updated signal if full fields have been updated
+ award_badges_signal.send(None,
+ event = 'update_user_profile',
+ actor = user,
+ context_object = user
+ )
return HttpResponseRedirect(user.get_profile_url())
else:
form = forms.EditUserForm(user)