Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
tree: 79bf3e40a3
Fetching contributors…

Cannot retrieve contributors at this time

218 lines (178 sloc) 7.311 kb
# -*- coding: utf-8 -*-
"""
solace.badges
~~~~~~~~~~~~~
This module implements the badge system.
:copyright: (c) 2010 by the Solace Team, see AUTHORS for more details.
:license: BSD, see LICENSE for more details.
"""
from operator import attrgetter
from solace.i18n import lazy_gettext, _
from solace.utils.remoting import RemoteObject
def try_award(event, *args):
"""Tries to avard a badge for the given event. The events correspond
to the `on_X` callbacks on the badges, just without the `on_` prefix.
"""
lookup = attrgetter('on_' + event)
for badge in badge_list:
cb = lookup(badge)
if cb is None:
continue
user = cb(*args)
if user is not None:
if isinstance(user, tuple):
user, payload = user
else:
payload = None
if badge.single_awarded and badge in user.badges:
continue
user._badges.append(UserBadge(badge, payload))
# inactive or banned users don't get messages.
if user.is_active and not user.is_banned:
UserMessage(user, _(u'You earned the “%s” badge') % badge.name)
_numeric_levels = dict(zip(('bronce', 'silver', 'gold', 'platin'),
range(4)))
class Badge(RemoteObject):
"""Represents a badge.
It can react to the following events::
on_vote = lambda user, post, delta
on_accept = lambda user, post, answer
on_reply = lambda user, post
on_new_topic = lambda user, topic
on_edit = lambda user, post
"""
remote_object_type = 'solace.badge'
public_fields = ('level', 'identifier', 'name', 'description')
def __init__(self, level, identifier, name, description=None,
single_awarded=False,
on_vote=None, on_accept=None, on_reply=None,
on_new_topic=None, on_edit=None):
assert level in ('bronce', 'silver', 'gold', 'platin')
assert len(identifier) <= 30
self.level = level
self.identifier = identifier
self.name = name
self.single_awarded = single_awarded
self.description = description
self.on_vote = on_vote
self.on_accept = on_accept
self.on_reply = on_reply
self.on_new_topic = on_new_topic
self.on_edit = on_edit
@property
def numeric_level(self):
return _numeric_levels[self.level]
def get_url_values(self):
return 'badges.show_badge', {'identifier': self.identifier}
def __repr__(self):
return '<%s \'%s\' (%s)>' % (
type(self).__name__,
self.name.encode('utf-8'),
('bronce', 'silver', 'gold', 'platin')[self.numeric_level]
)
def _try_award_special_answer(post, badge, votes_required):
"""Helper for nice and good answer."""
pid = str(post.id)
user = post.author
for user_badge in user._badges:
if user_badge.badge == badge and \
user_badge.payload == pid:
return
if post.is_answer and post.votes >= votes_required:
return user, pid
def _try_award_self_learner(post):
"""Helper for the self learner badge."""
pid = str(post.id)
user = post.author
for user_badge in user._badges:
if user_badge.badge == SELF_LEARNER and \
user_badge.payload == pid:
return
if post.is_answer and post.author == post.topic.author \
and post.votes >= 3:
return user, pid
def _try_award_reversal(post):
"""Helper for the reversal badge."""
pid = str(post.id)
user = post.author
for user_badge in user._badges:
if user_badge.badge == REVERSAL and \
user_badge.payload == pid:
return
if post.is_answer and post.votes >= 20 and \
post.topic.votes <= -5:
return user, pid
CRITIC = Badge('bronce', 'critic', lazy_gettext(u'Critic'),
lazy_gettext(u'First down vote'),
single_awarded=True,
on_vote=lambda user, post, delta:
user if delta < 0 and user != post.author else None
)
SELF_CRITIC = Badge('silver', 'self-critic', lazy_gettext(u'Self-Critic'),
lazy_gettext(u'First downvote on own reply or question'),
single_awarded=True,
on_vote=lambda user, post, delta:
user if delta < 0 and user == post.author else None
)
EDITOR = Badge('bronce', 'editor', lazy_gettext(u'Editor'),
lazy_gettext(u'First edited post'),
single_awarded=True,
on_edit=lambda user, post: user
)
INQUIRER = Badge('bronce', 'inquirer', lazy_gettext(u'Inquirer'),
lazy_gettext(u'First asked question'),
single_awarded=True,
on_new_topic=lambda user, topic: user
)
TROUBLESHOOTER = Badge('silver', 'troubleshooter',
lazy_gettext(u'Troubleshooter'),
lazy_gettext(u'First answered question'),
single_awarded=True,
on_accept=lambda user, topic, post: post.author if post else None
)
NICE_ANSWER = Badge('bronce', 'nice-answer', lazy_gettext(u'Nice Answer'),
lazy_gettext(u'Answer was upvoted 10 times'),
on_accept=lambda user, topic, post: _try_award_special_answer(post,
NICE_ANSWER, 10) if post else None,
on_vote=lambda user, post, delta: _try_award_special_answer(post,
NICE_ANSWER, 10)
)
GOOD_ANSWER = Badge('silver', 'good-answer', lazy_gettext(u'Good Answer'),
lazy_gettext(u'Answer was upvoted 25 times'),
on_accept=lambda user, topic, post: _try_award_special_answer(post,
GOOD_ANSWER, 25) if post else None,
on_vote=lambda user, post, delta: _try_award_special_answer(post,
GOOD_ANSWER, 25)
)
GREAT_ANSWER = Badge('gold', 'great-answer', lazy_gettext(u'Great Answer'),
lazy_gettext(u'Answer was upvoted 75 times'),
on_accept=lambda user, topic, post: _try_award_special_answer(post,
GOOD_ANSWER, 75) if post else None,
on_vote=lambda user, post, delta: _try_award_special_answer(post,
GOOD_ANSWER, 75)
)
UNIQUE_ANSWER = Badge('platin', 'unique-answer', lazy_gettext(u'Unique Answer'),
lazy_gettext(u'Answer was upvoted 150 times'),
on_accept=lambda user, topic, post: _try_award_special_answer(post,
GOOD_ANSWER, 150) if post else None,
on_vote=lambda user, post, delta: _try_award_special_answer(post,
GOOD_ANSWER, 150)
)
REVERSAL = Badge('gold', 'reversal', lazy_gettext(u'Reversal'),
lazy_gettext(u'Provided answer of +20 score to a question of -5 score'),
on_accept=lambda user, topic, post: _try_award_reversal(post) if post else None,
on_vote=lambda user, post, delta: _try_award_reversal(post)
)
SELF_LEARNER = Badge('silver', 'self-learner', lazy_gettext(u'Self-Learner'),
lazy_gettext(u'Answered your own question with at least 4 upvotes'),
on_accept=lambda user, topic, post: _try_award_self_learner(post) if post else None,
on_vote=lambda user, post, delta: _try_award_self_learner(post)
)
#: list of all badges
badge_list = [CRITIC, EDITOR, INQUIRER, TROUBLESHOOTER, NICE_ANSWER,
GOOD_ANSWER, SELF_LEARNER, SELF_CRITIC, GREAT_ANSWER,
UNIQUE_ANSWER, REVERSAL]
#: all the badges by key
badges_by_id = dict((x.identifier, x) for x in badge_list)
# circular dependencies
from solace.models import UserBadge, UserMessage
Jump to Line
Something went wrong with that request. Please try again.