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 (int(action.node.score) == int(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):