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
41 class NodeScoreBadge(AbstractBadge):
43 listen_to = (VoteAction,)
45 def award_to(self, action):
46 if (action.node.node_type == self.node_type) and (action.node.score == int(self.expected_score)):
47 return action.node.author
50 class QuestionScoreBadge(NodeScoreBadge):
52 node_type = "question"
55 def description(self):
56 return _('Question voted up %s times') % str(self.expected_score)
58 class NiceQuestion(QuestionScoreBadge):
59 expected_score = settings.NICE_QUESTION_VOTES_UP
60 name = _("Nice Question")
62 class GoodQuestion(QuestionScoreBadge):
64 expected_score = settings.GOOD_QUESTION_VOTES_UP
65 name = _("Good Question")
67 class GreatQuestion(QuestionScoreBadge):
69 expected_score = settings.GREAT_QUESTION_VOTES_UP
70 name = _("Great Question")
73 class AnswerScoreBadge(NodeScoreBadge):
78 def description(self):
79 return _('Answer voted up %s times') % str(self.expected_score)
81 class NiceAnswer(AnswerScoreBadge):
82 expected_score = settings.NICE_ANSWER_VOTES_UP
83 name = _("Nice Answer")
85 class GoodAnswer(AnswerScoreBadge):
87 expected_score = settings.GOOD_ANSWER_VOTES_UP
88 name = _("Good Answer")
90 class GreatAnswer(AnswerScoreBadge):
92 expected_score = settings.GREAT_ANSWER_VOTES_UP
93 name = _("Great Answer")
97 class FavoriteQuestionBadge(AbstractBadge):
99 listen_to = (FavoriteAction,)
102 def description(self):
103 return _('Question favorited by %s users') % str(self.expected_count)
105 def award_to(self, action):
106 if (action.node.node_type == "question") and (action.node.favorite_count == int(self.expected_count)):
107 return action.node.author
109 class FavoriteQuestion(FavoriteQuestionBadge):
111 name = _("Favorite Question")
112 expected_count = settings.FAVORITE_QUESTION_FAVS
114 class StellarQuestion(FavoriteQuestionBadge):
116 name = _("Stellar Question")
117 expected_count = settings.STELLAR_QUESTION_FAVS
121 class Disciplined(AbstractBadge):
122 listen_to = (DeleteAction,)
123 name = _("Disciplined")
124 description = _('Deleted own post with score of %s or higher') % settings.DISCIPLINED_MIN_SCORE
126 def award_to(self, action):
127 if (action.node.author == action.user) and (action.node.score >= int(settings.DISCIPLINED_MIN_SCORE)):
130 class PeerPressure(AbstractBadge):
131 listen_to = (DeleteAction,)
132 name = _("Peer Pressure")
133 description = _('Deleted own post with score of %s or lower') % settings.PEER_PRESSURE_MAX_SCORE
135 def award_to(self, action):
136 if (action.node.author == action.user) and (action.node.score <= int(settings.PEER_PRESSURE_MAX_SCORE)):
140 class Critic(AbstractBadge):
142 listen_to = (VoteDownAction,)
144 description = _('First down vote')
146 def award_to(self, action):
147 if (action.user.vote_down_count == 1):
151 class Supporter(AbstractBadge):
153 listen_to = (VoteUpAction,)
154 name = _("Supporter")
155 description = _('First up vote')
157 def award_to(self, action):
158 if (action.user.vote_up_count == 1):
162 class FirstActionBadge(AbstractBadge):
166 def award_to(self, action):
167 if (self.listen_to[0].objects.filter(user=action.user).count() == 1):
170 class CitizenPatrol(FirstActionBadge):
171 listen_to = (FlagAction,)
172 name = _("Citizen Patrol")
173 description = _('First flagged post')
175 class Organizer(FirstActionBadge):
176 listen_to = (RetagAction,)
177 name = _("Organizer")
178 description = _('First retag')
180 class Editor(FirstActionBadge):
181 listen_to = (ReviseAction,)
183 description = _('First edit')
185 class Scholar(FirstActionBadge):
186 listen_to = (AcceptAnswerAction,)
188 description = _('First accepted answer on your own question')
190 class Cleanup(FirstActionBadge):
191 listen_to = (RollbackAction,)
193 description = _('First rollback')
196 class Autobiographer(AbstractBadge):
198 listen_to = (EditProfileAction,)
199 name = _("Autobiographer")
200 description = _('Completed all user profile fields')
202 def award_to(self, action):
204 if user.email and user.real_name and user.website and user.location and \
205 user.date_of_birth and user.about:
210 class CivicDuty(AbstractBadge):
213 listen_to = (VoteUpAction, VoteDownAction)
214 name = _("Civic Duty")
215 description = _('Voted %s times') % settings.CIVIC_DUTY_VOTES
217 def award_to(self, action):
218 if (action.user.vote_up_count + action.user.vote_down_count) == int(settings.CIVIC_DUTY_VOTES):
222 class Pundit(AbstractBadge):
224 listen_to = (CommentAction,)
226 description = _('Left %s comments') % settings.PUNDIT_COMMENT_COUNT
228 def award_to(self, action):
229 if (action.user.nodes.filter(node_type="comment", deleted=None)) == int(settings.CIVIC_DUTY_VOTES):
233 class SelfLearner(AbstractBadge):
234 listen_to = (VoteUpAction, )
235 name = _("Self Learner")
236 description = _('Answered your own question with at least %s up votes') % settings.SELF_LEARNER_UP_VOTES
238 def award_to(self, action):
239 if (action.node.node_type == "answer") and (action.node.author == action.node.parent.author) and (
240 action.node.score == int(settings.SELF_LEARNER_UP_VOTES)):
241 return action.node.author
244 class StrunkAndWhite(AbstractBadge):
247 listen_to = (ReviseAction,)
248 name = _("Strunk & White")
249 description = _('Edited %s entries') % settings.STRUNK_AND_WHITE_EDITS
251 def award_to(self, action):
252 if (ReviseAction.objects.filter(user=action.user).count() == int(settings.STRUNK_AND_WHITE_EDITS)):
256 class Student(AbstractBadge):
258 listen_to = (VoteUpAction,)
260 description = _('Asked first question with at least one up vote')
262 def award_to(self, action):
263 if (action.node.node_type == "question") and (action.node.author.nodes.filter_state(deleted=False).filter(node_type="question", score=1).count() == 1):
264 return action.node.author
267 class Teacher(AbstractBadge):
269 listen_to = (VoteUpAction,)
271 description = _('Answered first question with at least one up vote')
273 def award_to(self, action):
274 if (action.node.node_type == "answer") and (action.node.author.nodes.filter_state(deleted=False).filter(node_type="answer", score=1).count() == 1):
275 return action.node.author
278 class Enlightened(AbstractBadge):
281 listen_to = (VoteUpAction, AcceptAnswerAction)
282 name = _("Enlightened")
283 description = _('First answer was accepted with at least %s up votes') % settings.ENLIGHTENED_UP_VOTES
285 def award_to(self, action):
286 if (action.node.node_type == "answer") and (action.node.accepted) and (
287 action.node.score >= int(settings.ENLIGHTENED_UP_VOTES)):
288 return action.node.author
291 class Guru(AbstractBadge):
293 listen_to = (VoteUpAction, AcceptAnswerAction)
295 description = _('Accepted answer and voted up %s times') % settings.GURU_UP_VOTES
297 def award_to(self, action):
298 if (action.node.node_type == "answer") and (action.node.accepted) and (
299 action.node.score >= int(settings.ENLIGHTENED_UP_VOTES)):
300 return action.node.author
303 class Necromancer(AbstractBadge):
305 listen_to = (VoteUpAction,)
306 name = _("Necromancer")
307 description = _('Answered a question more than %(dif_days)s days later with at least %(up_votes)s votes') % \
308 {'dif_days': settings.NECROMANCER_DIF_DAYS, 'up_votes': settings.NECROMANCER_UP_VOTES}
310 def award_to(self, action):
311 if (action.node.node_type == "answer") and (
312 action.node.added_at >= (action.node.question.added_at + timedelta(days=int(settings.NECROMANCER_DIF_DAYS)))):
313 return action.node.author
315 class Taxonomist(AbstractBadge):
318 name = _("Taxonomist")
319 description = _('Created a tag used by %s questions') % settings.TAXONOMIST_USE_COUNT
321 def award_to(self, action):