def test_frenzy_loss(self): """ If user loses while affected by frenzy he should lose frenzy.percents more points """ initial_points = 100 loss_points = -10 warranty_points = -3 player_frenzy = self._get_player(1).get_extension(ChallengeUser) player_dummy = self._get_player(2).get_extension(ChallengeUser) scoring.setup_scoring() Coin.add('points') scoring.score_simple(player_frenzy, 'points', initial_points) formula = Formula.get('chall-lost') formula.expression = 'points=' + str(loss_points) formula.save() formula = Formula.get('chall-warranty') formula.expression = 'points=' + str(warranty_points) formula.save() # Apply frenzy frenzy = Spell.objects.create(name='challenge-affect-scoring', available=True, price=25, percents=66, type='o') obs = PlayerSpellDue.objects.create(player=player_frenzy, source=player_frenzy, spell=frenzy, due=datetime.now() + timedelta(days=1)) # Win challenge with dummy player to see the amount of points lost by the player affected with frenzy chall = Challenge.create(user_from=player_frenzy, user_to=player_dummy, ignore_questions=True) chall.set_won_by_player(player_dummy) # Player should lose frenzy.percents more points with frenzy applied target_points = initial_points + loss_points + frenzy.percents / 100.0 * loss_points + warranty_points self.assertEqual(player_frenzy.player_ptr.points, target_points)
def score_simple(player, coin, amount, game=None, formula=None, external_id=None, percents=100): """ Give amount of coin to the player. """ if not isinstance(game, Game) and game is not None: game = game.get_instance() if not isinstance(player, Player): raise InvalidScoreCall() user = player.user coin = Coin.get(coin) formula = Formula.get(formula) computed_amount = 1.0 * amount * percents / 100 hs = History.objects.create(user=user, coin=coin, amount=computed_amount, game=game, formula=formula, external_id=external_id, percents=percents) # update user.points asap if coin.id == 'points': player.points += computed_amount player.save() update_points(player, game) logging.debug("Scored %s with %f %s" % (user, computed_amount, coin)) return hs
def test_scoring_loss(self): initial_points = 10 winner = self._get_player(1).get_extension(ChallengeUser) loser = self._get_player(2).get_extension(ChallengeUser) # Setup scoring scoring.setup_scoring() Coin.add('points') # Give initial points scoring.score_simple(winner, 'points', initial_points) scoring.score_simple(loser, 'points', initial_points) # Set formula loss_points = -2 formula = Formula.get('chall-lost') formula.expression = 'points=' + str(loss_points) formula.save() # Play challenge chall = Challenge.create(user_from=winner, user_to=loser, ignore_questions=True) chall.set_won_by_player(winner) self.assertEqual(loser.player_ptr.points, initial_points + loss_points) # loss_points is negative
def calculate(formula, **params): """ Calculate formula and return a dictionary of coin and amounts """ formula = Formula.get(formula) if formula is None: raise InvalidFormula(formula) ret = {} try: frml = formula.formula.format(**params) # Apparently, Python does not allow assignments inside eval # Using this workaround for now ass = frml.split(';') for a in ass: asp = a.split('=') coin = asp[0].strip() expr = '='.join(asp[1:]) try: result = eval(expr) except ZeroDivisionError as e: result = 0 ret[coin] = result except Exception as e: raise FormulaParsingError(e) return ret
def test_charge(self): """ Test for Charge spell """ initial_points = 100 win_points = 10 player_charge = self._get_player(1).get_extension(ChallengeUser) player_dummy = self._get_player(2).get_extension(ChallengeUser) scoring.setup_scoring() Coin.add('points') scoring.score_simple(player_charge, 'points', initial_points) formula = Formula.get('chall-won') formula.expression = 'points=' + str(win_points) formula.save() # Apply charge charge = Spell.objects.create(name='challenge-affect-scoring-won', available=True, price=10, percents=33, type='p') obs = PlayerSpellDue.objects.create(player=player_charge, source=player_charge, spell=charge, due=datetime.now() + timedelta(days=1)) chall = Challenge.create(user_from=player_charge, user_to=player_dummy, ignore_questions=True) chall.set_won_by_player(player_charge) # Player should win weakness.percents more points with charge applied target_points = initial_points + win_points + charge.percents / 100.0 * win_points self.assertEqual(player_charge.player_ptr.points, target_points)
def score_simple(player, coin, amount, game=None, formula=None, external_id=None, percents=100): """ Give amount of coin to the player. """ if not isinstance(game, Game) and game is not None: game = game.get_instance() if not isinstance(player, Player): raise InvalidScoreCall() user = player.user player = user.get_profile() user = player.user coin = Coin.get(coin) formula = Formula.get(formula) computed_amount = 1.0 * amount * percents / 100 hs = History.add(user=user, coin=coin, amount=computed_amount, game=game, formula=formula, external_id=external_id, percents=percents) # update user.points asap if coin.name == 'points': if player.magic.has_modifier('top-disguise'): computed_amount = 1.0 * computed_amount * player.magic.modifier_percents('top-disguise') / 100 player.points += computed_amount player.save() update_points(player, game) logging.debug("Scored %s with %f %s" % (user, computed_amount, coin)) return hs
def karma_group_view(request, group): group_id = group group = get_object_or_404(PlayerGroup, pk=group) players = group.players.all() if request.method == 'POST': form = KarmaBonusForm(request.POST, players=players) if form.is_valid(): formula = Formula.get('bonus-karma') if formula is None: messages.error(request, 'No such formula, bonus-karma') else: for player, entry in zip(players, form.fields): # get amount of karma points for current player karma_points = form.cleaned_data[entry] # if karma points are zero then skip if karma_points == 0: continue # compute formula and calculate amount of bonus given amount = eval(formula.expression.format(**{'karma_points': karma_points}).split('=')[1]) # apply scoring scoring.score(player, None, formula, external_id=request.user.get_profile().id, **{'karma_points': karma_points}) # add activity (parse formula expression to get the coin from formula) add_activity(player, _( 'received {amount} {coin} bonus for {karma_points} Karma Points'), amount=amount, coin=formula.expression.split('=')[0], karma_points=karma_points, reason='Bonus for Karma') messages.info(request, 'Successfully given bonus') return redirect('karma_group', **{'group': group_id}) else: form = KarmaBonusForm(players=players) return render_to_response('cpanel/karma_group.html', {'form':form, 'group':group}, context_instance=RequestContext(request))
def score_simple(player, coin, amount, game=None, formula=None, external_id=None, percents=100 ): """ Give amount of coin to the player. """ if not isinstance(game, Game) and game is not None: game = game.get_instance() if not isinstance(player, Player): raise InvalidScoreCall() user = player.user player = user.get_profile() user = player.user coin = Coin.get(coin) formula = Formula.get(formula) computed_amount = 1.0 * amount * percents / 100 hs = History.add(user=user, coin=coin, amount=computed_amount, game=game, formula=formula, external_id=external_id, percents=percents) # update user.points asap if coin.name == 'points': if player.magic.has_modifier('top-disguise'): computed_amount = 1.0 * computed_amount * player.magic.modifier_percents('top-disguise') / 100 player.points += computed_amount player.save() update_points(player, game) logging.debug("Scored %s with %f %s" % (user, computed_amount, coin)) return hs
def bonus(request, player_id): player = get_object_or_404(Player, pk=player_id) if request.method == 'POST': form = BonusForm(request.POST) if form.is_valid(): coin, amount = form.cleaned_data['coin'], form.cleaned_data['amount'] formula = Formula.get('bonus-%s' % coin.name) if formula is None: messages.error(request, 'No such formula, bonus-%s' % coin.name) else: scoring.score(player, None, formula, external_id=request.user.get_profile().id, **{coin.name: amount}) if form.cleaned_data['reason']: add_activity(player, _('received {amount} {coin} bonus for {reason}'), amount=amount, coin=coin, reason=form.cleaned_data['reason']) messages.info(request, 'Successfully given bonus') return redirect('player_profile', id=player.id) else: form = BonusForm() bonuses = scoring.History.objects.filter(user=player, formula__name__startswith='bonus-').order_by('-timestamp') penalties = scoring.History.objects.filter(user=player, formula__name__startswith='penalty-').order_by('-timestamp') return render_to_response('cpanel/bonus.html', {'target_player': player, 'form': form, 'bonuses': bonuses, 'penalties': penalties}, context_instance=RequestContext(request) )
def calculate(formula, **params): """ Calculate formula and return a dictionary of coin and amounts """ formula = Formula.get(formula) if formula is None: raise InvalidFormula(formula) if not formula.formula: return {} ret = {} try: frml = formula.formula.format(**params) # Apparently, Python does not allow assignments inside eval # Using this workaround for now ass = frml.split(";") for a in ass: asp = a.split("=") coin = asp[0].strip() expr = "=".join(asp[1:]) try: result = eval(expr) except ZeroDivisionError as e: result = 0 ret[coin] = result except Exception as e: logging.exception(e) raise FormulaParsingError(formula) return ret
def test_weakness_and_charge(self): """ If both Weakness and Charge are active, a player should win weakness.percents + charge.percents less/more points after winning a challenge """ initial_points = 100 win_points = 10 player = self._get_player(1).get_extension(ChallengeUser) player_dummy = self._get_player(2).get_extension(ChallengeUser) scoring.setup_scoring() Coin.add('points') scoring.score_simple(player, 'points', initial_points) formula = Formula.get('chall-won') formula.expression = 'points=' + str(win_points) formula.save() # Apply charge charge = Spell.objects.create(name='challenge-affect-scoring-won', available=True, price=10, percents=33, type='p') obs = PlayerSpellDue.objects.create(player=player, source=player, spell=charge, due=datetime.now() + timedelta(days=1)) # Apply weakness weakness = Spell.objects.create(name='challenge-affect-scoring-won', available=True, price=10, percents=-66, type='p') obs = PlayerSpellDue.objects.create(player=player, source=player, spell=weakness, due=datetime.now() + timedelta(days=1)) chall = Challenge.create(user_from=player, user_to=player_dummy, ignore_questions=True) chall.set_won_by_player(player) percents = (charge.percents + weakness.percents) / 100.0 target_points = initial_points + win_points + percents * win_points self.assertEqual(player.player_ptr.points, target_points)
def unset(user, game, formula, external_id=None, **params): """ Remove all history records by the external_id, formula and game given to the user """ formula = Formula.get(formula) for history in History.objects.filter(user=user, game=game.get_instance(), formula=formula, external_id=external_id): if history.coin.name == 'points': user.points -= history.amount history.delete() user.save() update_points(user, game)
def rollback(user, game, formula, external_id=None, **params): if game != None: game = game.get_instance() formula = Formula.get(formula) for history in History.objects.filter(user=user, game=game, formula=formula, external_id=external_id): if history.coin.name == 'points': user.points -= history.amount history.delete() user.save()
def rollback(user, game, formula, external_id=None, **params): if game is not None: game = game.get_instance() formula = Formula.get(formula) user = user.user.get_profile() # make sure you are working on fresh Player for history in History.objects.filter(user=user, game=game, formula=formula, external_id=external_id): if history.coin.name == 'points': user.points -= history.amount history.delete() user.save()
def calculate(formula, **params): """ Calculate formula and return a dictionary of coin and amounts """ formula = Formula.get(formula) if formula is None: raise InvalidFormula(formula) if not formula.expression: return {} return calculate_expression(formula.expression, formula, **params)
def setup(): """ Prepare database for Scoring """ for cc in CORE_POINTS: if not Coin.get(cc): Coin.add(cc, name=cc) # special case, gold is integer gold = Coin.get('gold') gold.integer = True gold.save() # iterate through games and register formulas for game in get_games(): for formula in game.get_formulas(): if not Formula.get(formula.id): Formula.add(formula) # add wouso formulas for formula in God.get_system_formulas(): if not Formula.get(formula.id): Formula.add(formula)
def unset(user, game, formula, external_id=None, **params): """ Remove all history records by the external_id, formula and game given to the user """ formula = Formula.get(formula) user = user.user.get_profile() # make sure you are working on fresh Player for history in History.objects.filter(user=user, game=game.get_instance(), formula=formula, external_id=external_id): if history.coin.name == 'points': user.points -= history.amount history.delete() user.save() update_points(user, game)
def activity_handler(cls, sender, **kwargs): action = kwargs.get('action', None) rules = filter(lambda x : x[2]==action, cls.SECURITY_RULES) for rule in rules: # check if rule is not disabled if not BoolSetting.objects.get(pk__startswith='disable-%s' % rule[0]).get_value(): (guilty, player, external_id) = SecurityInspector.check(rule[0], **kwargs) if guilty: formula = Formula.get('%s-infraction' % rule[0], 'general-infraction') cls.penalise(player, formula, external_id)
def calculate(formula, **params): """ Calculate formula and return a dictionary of coin and amounts """ formula = Formula.get(formula) if formula is None: raise InvalidFormula(formula) if not formula.definition: return {} return calculate_definition(formula.definition, formula, **params)
def karma_group_view(request, id): group = get_object_or_404(PlayerGroup, pk=id) players = group.players.all() if request.method == 'POST': form = KarmaBonusForm(request.POST, players=players) if form.is_valid(): formula = Formula.get('bonus-karma') if formula is None: messages.error(request, 'No such formula, bonus-karma') else: for player, entry in zip(players, form.fields): # Get amount of karma points for current player karma_points = form.cleaned_data[entry] # Skip if there are no karma points if karma_points == 0: continue # Compute formula and calculate amount of bonus given amount = eval( formula.expression.format(**{ 'karma_points': karma_points }).split('=')[1]) # Apply scoring scoring.score(player, None, formula, external_id=request.user.get_profile().id, **{'karma_points': karma_points}) # Add activity (parse formula expression to get the coin from formula) add_activity( player, _('received {amount} {coin} bonus for {karma_points} Karma Points' ), amount=amount, coin=formula.expression.split('=')[0], karma_points=karma_points, reason='Bonus for Karma') messages.info(request, 'Successfully given bonus') return redirect('karma_group', id=id) else: form = KarmaBonusForm(players=players) return render_to_response('cpanel/karma_group.html', { 'form': form, 'group': group }, context_instance=RequestContext(request))
def activity_handler(cls, sender, **kwargs): action = kwargs.get('action', None) rules = filter(lambda x: x[2] == action, cls.SECURITY_RULES) for rule in rules: # check if rule is not disabled if not BoolSetting.objects.filter(pk__startswith='%s' % rule[0]): (guilty, player, external_id) = SecurityInspector.check(rule[0], **kwargs) if guilty: formula = Formula.get('%s-infraction' % rule[0], 'general-infraction') cls.penalise(player, formula, external_id)
def timer(user, game, formula, default=300, **params): """ Compute a timer value, or return default """ formula = Formula.get(formula) if formula is None: raise InvalidFormula(formula) if not formula.expression: return default values = calculate(formula, **params) if 'tlimit' in values: return values['tlimit'] return default
def timer(user, game, formula, default=300, **params): """ Compute a timer value, or return default """ formula = Formula.get(formula) if formula is None: raise InvalidFormula(formula) if not formula.definition: return default values = calculate(formula, **params) if values.has_key('tlimit'): return values['tlimit'] return default
def timer(user, game, formula, default=300, **params): """ Compute a timer value, or return default """ formula = Formula.get(formula) if formula is None: raise InvalidFormula(formula) if not formula.formula: return default values = calculate(formula, **params) if values.has_key("tlimit"): return values["tlimit"] return default
def testScoring(self): chall = Challenge.create(user_from=self.chall_user, user_to=self.chall_user2, ignore_questions=True) chall.user_from.seconds_took = 10 chall.user_from.score = 100 chall.user_from.save() chall.user_to.seconds_took = 10 chall.user_to.score = 10 chall.user_to.save() # TODO: improve usage of formulas inside tests. formula = Formula.get('chall-won') formula.expression = 'points=10 + min(10, int(3 * {winner_points}/{loser_points}))' formula.save() chall.played()
def bonus(request, player_id): player = get_object_or_404(Player, pk=player_id) if request.method == 'POST': form = BonusForm(request.POST) if form.is_valid(): coin, amount = form.cleaned_data['coin'], form.cleaned_data[ 'amount'] formula = Formula.get('bonus-%s' % coin.name) if formula is None: messages.error(request, 'No such formula, bonus-%s' % coin.name) else: scoring.score(player, None, formula, external_id=request.user.get_profile().id, **{coin.name: amount}) if form.cleaned_data['reason']: add_activity( player, _('received {amount} {coin} bonus for {reason}'), amount=amount, coin=coin, reason=form.cleaned_data['reason']) messages.info(request, 'Successfully given bonus') return redirect('details_player', pk=player.id) else: form = BonusForm() bonuses = scoring.History.objects.filter( user=player, formula__name__startswith='bonus-').order_by('-timestamp') penalties = scoring.History.objects.filter( user=player, formula__name__startswith='penalty-').order_by('-timestamp') return render_to_response('cpanel/bonus.html', { 'target_player': player, 'form': form, 'bonuses': bonuses, 'penalties': penalties }, context_instance=RequestContext(request))
def history_for(user, game, external_id=None, formula=None, coin=None): """ Return all history entries for given (user, game) pair. """ # TODO: check usage fltr = {} if external_id: fltr['external_id'] = external_id if formula: fltr['formula'] = Formula.get(formula) if coin: fltr['coin'] = Coin.get(coin) if not isinstance(game, Game): game = game.get_instance() if not isinstance(user, User): user = user.user try: return History.objects.filter(user=user, game=game, **fltr) except History.DoesNotExist: return None
def history_for(user, game, external_id=None, formula=None, coin=None): """ Return all history entries for given (user, game) pair. """ # TODO: check usage fltr = {} if external_id: fltr["external_id"] = external_id if formula: fltr["formula"] = Formula.get(formula) if coin: fltr["coin"] = Coin.get(coin) if not isinstance(game, Game): game = game.get_instance() if not isinstance(user, User): user = user.user try: return History.objects.filter(user=user, game=game, **fltr) except History.DoesNotExist: return None
def test_weakness(self): """ Test for Weakness spell """ initial_points = 100 win_points = 10 player_weakness = self._get_player(1).get_extension(ChallengeUser) player_dummy = self._get_player(2).get_extension(ChallengeUser) scoring.setup_scoring() Coin.add('points') scoring.score_simple(player_weakness, 'points', initial_points) formula = Formula.get('chall-won') formula.expression = 'points=' + str(win_points) formula.save() # Apply weakness weakness = Spell.objects.create(name='challenge-affect-scoring-lost', available=True, price=10, percents=-66, type='n') obs = PlayerSpellDue.objects.create(player=player_weakness, source=player_weakness, spell=weakness, due=datetime.now() + timedelta(days=1)) # Win challenge with player_weakness chall = Challenge.create(user_from=player_weakness, user_to=player_dummy, ignore_questions=True) chall.set_won_by_player(player_weakness) # Player should win weakness.percents less points with weakness applied target_points = initial_points + win_points + weakness.percents / 100.0 * win_points self.assertEqual(player_weakness.player_ptr.points, target_points)