]> git.openstreetmap.org Git - osqa.git/blob - forum/management/commands/once_award_badges.py
deleting the test file
[osqa.git] / forum / management / commands / once_award_badges.py
1 #!/usr/bin/env python
2 #encoding:utf-8
3 #-------------------------------------------------------------------------------
4 # Name:        Award badges command
5 # Purpose:     This is a command file croning in background process regularly to
6 #              query database and award badges for user's special acitivities.
7 #
8 # Author:      Mike, Sailing
9 #
10 # Created:     18/01/2009
11 # Copyright:   (c) Mike 2009
12 # Licence:     GPL V2
13 #-------------------------------------------------------------------------------
14
15 from datetime import datetime, date
16 from django.db import connection
17 from django.shortcuts import get_object_or_404
18 from django.contrib.contenttypes.models import ContentType
19
20 from forum.models import *
21 from forum.const import *
22 from base_command import BaseCommand
23 """
24 (1, '炼狱法师', 3, '炼狱法师', '删除自己有3个以上赞成票的帖子', 1, 0),
25 (2, '压力白领', 3, '压力白领', '删除自己有3个以上反对票的帖子', 1, 0),
26 (3, '优秀回答', 3, '优秀回答', '回答好评10次以上', 1, 0),
27 (4, '优秀问题', 3, '优秀问题', '问题好评10次以上', 1, 0),
28 (5, '评论家', 3, '评论家', '评论10次以上', 0, 0),
29 (6, '流行问题', 3, '流行问题', '问题的浏览量超过1000人次', 1, 0),
30 (7, '巡逻兵', 3, '巡逻兵', '第一次标记垃圾帖子', 0, 0),
31 (8, '清洁工', 3, '清洁工', '第一次撤销投票', 0, 0),
32 (9, '批评家', 3, '批评家', '第一次反对票', 0, 0),
33 (10, '小编', 3, '小编', '第一次编辑更新', 0, 0),
34 (11, '村长', 3, '村长', '第一次重新标签', 0, 0),
35 (12, '学者', 3, '学者', '第一次标记答案', 0, 0),
36 (13, '学生', 3, '学生', '第一次提问并且有一次以上赞成票', 0, 0),
37 (14, '支持者', 3, '支持者', '第一次赞成票', 0, 0),
38 (15, '教师', 3, '教师', '第一次回答问题并且得到一个以上赞成票', 0, 0),
39 (16, '自传作者', 3, '自传作者', '完整填写用户资料所有选项', 0, 0),
40 (17, '自学成才', 3, '自学成才', '回答自己的问题并且有3个以上赞成票', 1, 0),
41 (18, '最有价值回答', 1, '最有价值回答', '回答超过100次赞成票', 1, 0),
42 (19, '最有价值问题', 1, '最有价值问题', '问题超过100次赞成票', 1, 0),
43 (20, '万人迷', 1, '万人迷', '问题被100人以上收藏', 1, 0),
44 (21, '著名问题', 1, '著名问题', '问题的浏览量超过10000人次', 1, 0),
45 (22, 'alpha用户', 2, 'alpha用户', '内测期间的活跃用户', 0, 0),
46 (23, '极好回答', 2, '极好回答', '回答超过25次赞成票', 1, 0),
47 (24, '极好问题', 2, '极好问题', '问题超过25次赞成票', 1, 0),
48 (25, '受欢迎问题', 2, '受欢迎问题', '问题被25人以上收藏', 1, 0),
49 (26, '优秀市民', 2, '优秀市民', '投票300次以上', 0, 0),
50 (27, '编辑主任', 2, '编辑主任', '编辑了100个帖子', 0, 0),
51 (28, '通才', 2, '通才', '在多个标签领域活跃', 0, 0),
52 (29, '专家', 2, '专家', '在一个标签领域活跃出众', 0, 0),
53 (30, '老鸟', 2, '老鸟', '活跃超过一年的用户', 0, 0),
54 (31, '最受关注问题', 2, '最受关注问题', '问题的浏览量超过2500人次', 1, 0),
55 (32, '学问家', 2, '学问家', '第一次回答被投赞成票10次以上', 0, 0),
56 (33, 'beta用户', 2, 'beta用户', 'beta期间活跃参与', 0, 0),
57 (34, '导师', 2, '导师', '被指定为最佳答案并且赞成票40以上', 1, 0),
58 (35, '巫师', 2, '巫师', '在提问60天之后回答并且赞成票5次以上', 1, 0),
59 (36, '分类专家', 2, '分类专家', '创建的标签被50个以上问题使用', 1, 0);
60
61
62 TYPE_ACTIVITY_ASK_QUESTION=1
63 TYPE_ACTIVITY_ANSWER=2
64 TYPE_ACTIVITY_COMMENT_QUESTION=3
65 TYPE_ACTIVITY_COMMENT_ANSWER=4
66 TYPE_ACTIVITY_UPDATE_QUESTION=5
67 TYPE_ACTIVITY_UPDATE_ANSWER=6
68 TYPE_ACTIVITY_PRIZE=7
69 TYPE_ACTIVITY_MARK_ANSWER=8
70 TYPE_ACTIVITY_VOTE_UP=9
71 TYPE_ACTIVITY_VOTE_DOWN=10
72 TYPE_ACTIVITY_CANCEL_VOTE=11
73 TYPE_ACTIVITY_DELETE_QUESTION=12
74 TYPE_ACTIVITY_DELETE_ANSWER=13
75 TYPE_ACTIVITY_MARK_OFFENSIVE=14
76 TYPE_ACTIVITY_UPDATE_TAGS=15
77 TYPE_ACTIVITY_FAVORITE=16
78 TYPE_ACTIVITY_USER_FULL_UPDATED = 17
79 """
80
81 BADGE_AWARD_TYPE_FIRST = {
82     TYPE_ACTIVITY_MARK_OFFENSIVE : 7,
83     TYPE_ACTIVITY_CANCEL_VOTE: 8,
84     TYPE_ACTIVITY_VOTE_DOWN : 9,
85     TYPE_ACTIVITY_UPDATE_QUESTION : 10,
86     TYPE_ACTIVITY_UPDATE_ANSWER : 10,
87     TYPE_ACTIVITY_UPDATE_TAGS : 11,
88     TYPE_ACTIVITY_MARK_ANSWER : 12,
89     TYPE_ACTIVITY_VOTE_UP : 14,
90     TYPE_ACTIVITY_USER_FULL_UPDATED: 16
91
92 }
93
94 class Command(BaseCommand):
95     def handle_noargs(self, **options):
96         try:
97             try:
98                 self.alpha_user()
99                 self.beta_user()
100                 self.first_type_award()
101                 self.first_ask_be_voted()
102                 self.first_answer_be_voted()
103                 self.first_answer_be_voted_10()
104                 self.vote_count_300()
105                 self.edit_count_100()
106                 self.comment_count_10()
107             except Exception, e:
108                 print e
109         finally:
110             connection.close()
111
112     def alpha_user(self):
113         """
114         Before Jan 25, 2009(Chinese New Year Eve and enter into Beta for CNProg), every registered user
115         will be awarded the "Alpha" badge if he has any activities.
116         """
117         alpha_end_date = date(2009, 1, 25)
118         if date.today() < alpha_end_date:
119             badge = get_object_or_404(Badge, id=22)
120             for user in User.objects.all():
121                 award = Award.objects.filter(user=user, badge=badge)
122                 if award and not badge.multiple:
123                     continue
124                 activities = Activity.objects.filter(user=user)
125                 if len(activities) > 0:
126                     new_award = Award(user=user, badge=badge)
127                     new_award.save()
128
129     def beta_user(self):
130         """
131         Before Feb 25, 2009, every registered user
132         will be awarded the "Beta" badge if he has any activities.
133         """
134         beta_end_date = date(2009, 2, 25)
135         if date.today() < beta_end_date:
136             badge = get_object_or_404(Badge, id=33)
137             for user in User.objects.all():
138                 award = Award.objects.filter(user=user, badge=badge)
139                 if award and not badge.multiple:
140                     continue
141                 activities = Activity.objects.filter(user=user)
142                 if len(activities) > 0:
143                     new_award = Award(user=user, badge=badge)
144                     new_award.save()
145
146     def first_type_award(self):
147         """
148         This will award below badges for users first behaviors:
149
150         (7, '巡逻兵', 3, '巡逻兵', '第一次标记垃圾帖子', 0, 0),
151         (8, '清洁工', 3, '清洁工', '第一次撤销投票', 0, 0),
152         (9, '批评家', 3, '批评家', '第一次反对票', 0, 0),
153         (10, '小编', 3, '小编', '第一次编辑更新', 0, 0),
154         (11, '村长', 3, '村长', '第一次重新标签', 0, 0),
155         (12, '学者', 3, '学者', '第一次标记答案', 0, 0),
156         (14, '支持者', 3, '支持者', '第一次赞成票', 0, 0),
157         (16, '自传作者', 3, '自传作者', '完整填写用户资料所有选项', 0, 0),
158         """
159         activity_types = ','.join('%s' % item for item in BADGE_AWARD_TYPE_FIRST.keys())
160         # ORDER BY user_id, activity_type
161         query = "SELECT id, user_id, activity_type, content_type_id, object_id FROM activity WHERE is_auditted = 0 AND activity_type IN (%s) ORDER BY user_id, activity_type" % activity_types
162
163         cursor = connection.cursor()
164         try:
165             cursor.execute(query)
166             rows = cursor.fetchall()
167             # collect activity_id in current process
168             activity_ids = []
169             last_user_id = 0
170             last_activity_type = 0
171             for row in rows:
172                 activity_ids.append(row[0])
173                 user_id = row[1]
174                 activity_type = row[2]
175                 content_type_id = row[3]
176                 object_id = row[4]
177
178                 # if the user and activity are same as the last, continue
179                 if user_id == last_user_id and activity_type == last_activity_type:
180                     continue;
181
182                 user = get_object_or_404(User, id=user_id)
183                 badge = get_object_or_404(Badge, id=BADGE_AWARD_TYPE_FIRST[activity_type])
184                 content_type = get_object_or_404(ContentType, id=content_type_id)
185
186                 count = Award.objects.filter(user=user, badge=badge).count()
187                 if count and not badge.multiple:
188                     continue
189                 else:
190                     # new award
191                     award = Award(user=user, badge=badge, content_type=content_type, object_id=object_id)
192                     award.save()
193
194                 # set the current user_id and activity_type to last
195                 last_user_id = user_id
196                 last_activity_type = activity_type
197
198             # update processed rows to auditted
199             self.update_activities_auditted(cursor, activity_ids)
200         finally:
201             cursor.close()
202
203     def first_ask_be_voted(self):
204         """
205         For user asked question and got first upvote, we award him following badge:
206
207         (13, '学生', 3, '学生', '第一次提问并且有一次以上赞成票', 0, 0),
208         """
209         query = "SELECT act.user_id, q.vote_up_count, act.object_id FROM " \
210                     "activity act, question q WHERE act.activity_type = %s AND " \
211                     "act.object_id = q.id AND " \
212                     "act.user_id NOT IN (SELECT distinct user_id FROM award WHERE badge_id = %s)" % (TYPE_ACTIVITY_ASK_QUESTION, 13)
213         cursor = connection.cursor()
214         try:
215             cursor.execute(query)
216             rows = cursor.fetchall()
217
218             badge = get_object_or_404(Badge, id=13)
219             content_type = ContentType.objects.get_for_model(Question)
220             awarded_users = []
221             for row in rows:
222                 user_id = row[0]
223                 vote_up_count = row[1]
224                 object_id = row[2]
225                 if vote_up_count > 0 and user_id not in awarded_users:
226                     user = get_object_or_404(User, id=user_id)
227                     award = Award(user=user, badge=badge, content_type=content_type, object_id=object_id)
228                     award.save()
229                     awarded_users.append(user_id)
230         finally:
231             cursor.close()
232
233     def first_answer_be_voted(self):
234         """
235         When user answerd questions and got first upvote, we award him following badge:
236
237         (15, '教师', 3, '教师', '第一次回答问题并且得到一个以上赞成票', 0, 0),
238         """
239         query = "SELECT act.user_id, a.vote_up_count, act.object_id FROM " \
240                     "activity act, answer a WHERE act.activity_type = %s AND " \
241                     "act.object_id = a.id AND " \
242                     "act.user_id NOT IN (SELECT distinct user_id FROM award WHERE badge_id = %s)" % (TYPE_ACTIVITY_ANSWER, 15)
243         cursor = connection.cursor()
244         try:
245             cursor.execute(query)
246             rows = cursor.fetchall()
247
248             awarded_users = []
249             badge = get_object_or_404(Badge, id=15)
250             content_type = ContentType.objects.get_for_model(Answer)
251             for row in rows:
252                 user_id = row[0]
253                 vote_up_count = row[1]
254                 object_id = row[2]
255                 if vote_up_count > 0 and user_id not in awarded_users:
256                     user = get_object_or_404(User, id=user_id)
257                     award = Award(user=user, badge=badge, content_type=content_type, object_id=object_id)
258                     award.save()
259                     awarded_users.append(user_id)
260         finally:
261             cursor.close()
262
263     def first_answer_be_voted_10(self):
264         """
265         (32, '学问家', 2, '学问家', '第一次回答被投赞成票10次以上', 0, 0)
266         """
267         query = "SELECT act.user_id, act.object_id FROM " \
268                     "activity act, answer a WHERE act.object_id = a.id AND " \
269                     "act.activity_type = %s AND " \
270                     "a.vote_up_count >= 10 AND " \
271                     "act.user_id NOT IN (SELECT user_id FROM award WHERE badge_id = %s)" % (TYPE_ACTIVITY_ANSWER, 32)
272         cursor = connection.cursor()
273         try:
274             cursor.execute(query)
275             rows = cursor.fetchall()
276
277             awarded_users = []
278             badge = get_object_or_404(Badge, id=32)
279             content_type = ContentType.objects.get_for_model(Answer)
280             for row in rows:
281                 user_id = row[0]
282                 if user_id not in awarded_users:
283                     user = get_object_or_404(User, id=user_id)
284                     object_id = row[1]
285                     award = Award(user=user, badge=badge, content_type=content_type, object_id=object_id)
286                     award.save()
287                     awarded_users.append(user_id)
288         finally:
289             cursor.close()
290
291     def vote_count_300(self):
292         """
293         (26, '优秀市民', 2, '优秀市民', '投票300次以上', 0, 0)
294         """
295         query = "SELECT count(*) vote_count, user_id FROM activity WHERE " \
296                     "activity_type = %s OR " \
297                     "activity_type = %s AND " \
298                     "user_id NOT IN (SELECT user_id FROM award WHERE badge_id = %s) " \
299                     "GROUP BY user_id HAVING vote_count >= 300" % (TYPE_ACTIVITY_VOTE_UP, TYPE_ACTIVITY_VOTE_DOWN, 26)
300
301         self.__award_for_count_num(query, 26)
302
303     def edit_count_100(self):
304         """
305         (27, '编辑主任', 2, '编辑主任', '编辑了100个帖子', 0, 0)
306         """
307         query = "SELECT count(*) vote_count, user_id FROM activity WHERE " \
308                     "activity_type = %s OR " \
309                     "activity_type = %s AND " \
310                     "user_id NOT IN (SELECT user_id FROM award WHERE badge_id = %s) " \
311                     "GROUP BY user_id HAVING vote_count >= 100" % (TYPE_ACTIVITY_UPDATE_QUESTION, TYPE_ACTIVITY_UPDATE_ANSWER, 27)
312
313         self.__award_for_count_num(query, 27)
314
315     def comment_count_10(self):
316         """
317         (5, '评论家', 3, '评论家', '评论10次以上', 0, 0),
318         """
319         query = "SELECT count(*) vote_count, user_id FROM activity WHERE " \
320                     "activity_type = %s OR " \
321                     "activity_type = %s AND " \
322                     "user_id NOT IN (SELECT user_id FROM award WHERE badge_id = %s) " \
323                     "GROUP BY user_id HAVING vote_count >= 10" % (TYPE_ACTIVITY_COMMENT_QUESTION, TYPE_ACTIVITY_COMMENT_ANSWER, 5)
324         self.__award_for_count_num(query, 5)
325
326     def __award_for_count_num(self, query, badge):
327         cursor = connection.cursor()
328         try:
329             cursor.execute(query)
330             rows = cursor.fetchall()
331
332             awarded_users = []
333             badge = get_object_or_404(Badge, id=badge)
334             for row in rows:
335                 vote_count = row[0]
336                 user_id = row[1]
337
338                 if user_id not in awarded_users:
339                     user = get_object_or_404(User, id=user_id)
340                     award = Award(user=user, badge=badge)
341                     award.save()
342                     awarded_users.append(user_id)
343         finally:
344             cursor.close()
345
346 def main():
347     pass
348
349 if __name__ == '__main__':
350     main()