1 from datetime import datetime, timedelta
 
   2 from django.utils.translation import ugettext as _
 
   3 from forum.badges.base import AbstractBadge
 
   4 from forum.models import Badge
 
   5 from forum.actions import *
 
   6 from forum.models import Vote, Flag
 
  10 class QuestionViewBadge(AbstractBadge):
 
  12     listen_to = (QuestionViewAction,)
 
  15     def description(self):
 
  16         return _('Asked a question with %s views') % str(self.nviews)
 
  18     def award_to(self, action):
 
  19         if action.node.extra_count == int(self.nviews):
 
  20             return action.node.author
 
  23 class PopularQuestion(QuestionViewBadge):
 
  24     name = _('Popular Question')
 
  25     nviews = settings.POPULAR_QUESTION_VIEWS
 
  28 class NotableQuestion(QuestionViewBadge):
 
  30     name = _('Notable Question')
 
  31     nviews = settings.NOTABLE_QUESTION_VIEWS
 
  33 class FamousQuestion(QuestionViewBadge):
 
  35     name = _('Famous Question')
 
  36     nviews = settings.FAMOUS_QUESTION_VIEWS
 
  39 class NodeScoreBadge(AbstractBadge):
 
  41     listen_to = (VoteAction,)
 
  43     def award_to(self, action):
 
  44         if (action.node.node_type == self.node_type) and (action.node.score == int(self.expected_score)):
 
  45             return action.node.author
 
  48 class QuestionScoreBadge(NodeScoreBadge):
 
  50     node_type = "question"
 
  53     def description(self):
 
  54         return _('Question voted up %s times') % str(self.expected_score)
 
  56 class NiceQuestion(QuestionScoreBadge):
 
  57     expected_score = settings.NICE_QUESTION_VOTES_UP
 
  58     name = _("Nice Question")
 
  60 class GoodQuestion(QuestionScoreBadge):
 
  62     expected_score = settings.GOOD_QUESTION_VOTES_UP
 
  63     name = _("Good Question")
 
  65 class GreatQuestion(QuestionScoreBadge):
 
  67     expected_score = settings.GREAT_QUESTION_VOTES_UP
 
  68     name = _("Great Question")
 
  71 class AnswerScoreBadge(NodeScoreBadge):
 
  76     def description(self):
 
  77         return _('Answer voted up %s times') % str(self.expected_score)
 
  79 class NiceAnswer(AnswerScoreBadge):
 
  80     expected_score = settings.NICE_ANSWER_VOTES_UP
 
  81     name = _("Nice Answer")
 
  83 class GoodAnswer(AnswerScoreBadge):
 
  85     expected_score = settings.GOOD_ANSWER_VOTES_UP
 
  86     name = _("Good Answer")
 
  88 class GreatAnswer(AnswerScoreBadge):
 
  90     expected_score = settings.GREAT_ANSWER_VOTES_UP
 
  91     name = _("Great Answer")
 
  94 class FavoriteQuestionBadge(AbstractBadge):
 
  96     listen_to = (FavoriteAction,)
 
  99     def description(self):
 
 100         return _('Question favorited by %s users') % str(self.expected_count)
 
 102     def award_to(self, action):
 
 103         if (action.node.node_type == "question") and (action.node.favorite_count == int(self.expected_count)):
 
 104             return action.node.author
 
 106 class FavoriteQuestion(FavoriteQuestionBadge):
 
 108     name = _("Favorite Question")
 
 109     expected_count = settings.FAVORITE_QUESTION_FAVS
 
 111 class StellarQuestion(FavoriteQuestionBadge):
 
 113     name = _("Stellar Question")
 
 114     expected_count = settings.STELLAR_QUESTION_FAVS
 
 117 class Disciplined(AbstractBadge):
 
 118     listen_to = (DeleteAction,)
 
 119     name = _("Disciplined")
 
 120     description = _('Deleted own post with score of %s or higher') % settings.DISCIPLINED_MIN_SCORE
 
 122     def award_to(self, action):
 
 123         if (action.node.author == action.user) and (action.node.score >= int(settings.DISCIPLINED_MIN_SCORE)):
 
 126 class PeerPressure(AbstractBadge):
 
 127     listen_to = (DeleteAction,)
 
 128     name = _("Peer Pressure")
 
 129     description = _('Deleted own post with score of %s or lower') % settings.PEER_PRESSURE_MAX_SCORE
 
 131     def award_to(self, action):
 
 132         if (action.node.author == action.user) and (action.node.score <= int(settings.PEER_PRESSURE_MAX_SCORE)):
 
 136 class Critic(AbstractBadge):
 
 138     listen_to = (VoteDownAction,)
 
 140     description = _('First down vote')
 
 142     def award_to(self, action):
 
 143         if (action.user.vote_down_count == 1):
 
 147 class Supporter(AbstractBadge):
 
 149     listen_to = (VoteUpAction,)
 
 150     name = _("Supporter")
 
 151     description = _('First up vote')
 
 153     def award_to(self, action):
 
 154         if (action.user.vote_up_count == 1):
 
 158 class FirstActionBadge(AbstractBadge):
 
 162     def award_to(self, action):
 
 163         if (self.listen_to[0].objects.filter(user=action.user).count() == 1):
 
 166 class CitizenPatrol(FirstActionBadge):
 
 167     listen_to = (FlagAction,)
 
 168     name = _("Citizen Patrol")
 
 169     description = _('First flagged post')
 
 171 class Organizer(FirstActionBadge):
 
 172     listen_to = (RetagAction,)
 
 173     name = _("Organizer")
 
 174     description = _('First retag')
 
 176 class Editor(FirstActionBadge):
 
 177     listen_to = (ReviseAction,)
 
 179     description = _('First edit')
 
 181 class Scholar(FirstActionBadge):
 
 182     listen_to = (AcceptAnswerAction,)
 
 184     description = _('First accepted answer on your own question')
 
 186 class Cleanup(FirstActionBadge):
 
 187     listen_to = (RollbackAction,)
 
 189     description = _('First rollback')
 
 192 class Autobiographer(AbstractBadge):
 
 194     listen_to = (EditProfileAction,)
 
 195     name = _("Autobiographer")
 
 196     description = _('Completed all user profile fields')
 
 198     def award_to(self, action):
 
 200         if user.email and user.real_name and user.website and user.location and \
 
 201                 user.date_of_birth and user.about:
 
 205 class CivicDuty(AbstractBadge):
 
 208     listen_to = (VoteUpAction, VoteDownAction)
 
 209     name = _("Civic Duty")
 
 210     description = _('Voted %s times') % settings.CIVIC_DUTY_VOTES
 
 212     def award_to(self, action):
 
 213         if (action.user.vote_up_count + action.user.vote_down_count) == int(settings.CIVIC_DUTY_VOTES):
 
 217 class Pundit(AbstractBadge):
 
 219     listen_to = (CommentAction,)
 
 221     description = _('Left %s comments') % settings.PUNDIT_COMMENT_COUNT
 
 223     def award_to(self, action):
 
 224         if action.user.nodes.filter_state(deleted=False).filter(node_type="comment").count() == int(
 
 225                 settings.PUNDIT_COMMENT_COUNT):
 
 229 class SelfLearner(AbstractBadge):
 
 230     listen_to = (VoteUpAction, )
 
 231     name = _("Self Learner")
 
 232     description = _('Answered your own question with at least %s up votes') % settings.SELF_LEARNER_UP_VOTES
 
 234     def award_to(self, action):
 
 235         if (action.node.node_type == "answer") and (action.node.author == action.node.parent.author) and (
 
 236         action.node.score == int(settings.SELF_LEARNER_UP_VOTES)):
 
 237             return action.node.author
 
 240 class StrunkAndWhite(AbstractBadge):
 
 243     listen_to = (ReviseAction,)
 
 244     name = _("Strunk & White")
 
 245     description = _('Edited %s entries') % settings.STRUNK_AND_WHITE_EDITS
 
 247     def award_to(self, action):
 
 248         if (ReviseAction.objects.filter(user=action.user).count() == int(settings.STRUNK_AND_WHITE_EDITS)):
 
 252 class Student(AbstractBadge):
 
 254     listen_to = (VoteUpAction,)
 
 256     description = _('Asked first question with at least one up vote')
 
 258     def award_to(self, action):
 
 259         if (action.node.node_type == "question") and (action.node.author.nodes.filter_state(deleted=False).filter(
 
 260                 node_type="question", score=1).count() == 1):
 
 261             return action.node.author
 
 264 class Teacher(AbstractBadge):
 
 266     listen_to = (VoteUpAction,)
 
 268     description = _('Answered first question with at least one up vote')
 
 270     def award_to(self, action):
 
 271         if (action.node.node_type == "answer") and (action.node.author.nodes.filter_state(deleted=False).filter(
 
 272                 node_type="answer", score=1).count() == 1):
 
 273             return action.node.author
 
 276 class Enlightened(AbstractBadge):
 
 279     listen_to = (VoteUpAction, AcceptAnswerAction)
 
 280     name = _("Enlightened")
 
 281     description = _('First answer was accepted with at least %s up votes') % settings.ENLIGHTENED_UP_VOTES
 
 283     def award_to(self, action):
 
 284         if (action.node.node_type == "answer") and (action.node.accepted) and (
 
 285         action.node.score >= int(settings.ENLIGHTENED_UP_VOTES)):
 
 286             return action.node.author
 
 289 class Guru(AbstractBadge):
 
 291     listen_to = (VoteUpAction, AcceptAnswerAction)
 
 293     description = _('Accepted answer and voted up %s times') % settings.GURU_UP_VOTES
 
 295     def award_to(self, action):
 
 296         if (action.node.node_type == "answer") and (action.node.accepted) and (
 
 297         action.node.score >= int(settings.GURU_UP_VOTES)):
 
 298             return action.node.author
 
 301 class Necromancer(AbstractBadge):
 
 303     listen_to = (VoteUpAction,)
 
 304     name = _("Necromancer")
 
 305     description = _('Answered a question more than %(dif_days)s days later with at least %(up_votes)s votes') % \
 
 306             {'dif_days': settings.NECROMANCER_DIF_DAYS, 'up_votes': settings.NECROMANCER_UP_VOTES}
 
 308     def award_to(self, action):
 
 309         if (action.node.node_type == "answer") and (
 
 310         action.node.added_at >= (action.node.question.added_at + timedelta(days=int(settings.NECROMANCER_DIF_DAYS)))
 
 311         ) and (action.node.score == settings.NECROMANCER_UP_VOTES):
 
 312             return action.node.author
 
 314 class Taxonomist(AbstractBadge):
 
 317     name = _("Taxonomist")
 
 318     description = _('Created a tag used by %s questions') % settings.TAXONOMIST_USE_COUNT
 
 320     def award_to(self, action):