Ejemplo n.º 1
0
    def record_balance(answer, winner, dota_id=None):
        from app.ladder.models import Player, Match, MatchPlayer
        from app.ladder.models import LadderSettings

        players = [p[0] for t in answer.teams for p in t['players']]
        players = Player.objects.filter(name__in=players)

        # check that all players from balance exist
        # (we don't allow CustomBalance results here)
        if len(players) < 10:
            return None

        with transaction.atomic():
            match = Match.objects.create(
                winner=winner,
                balance=answer,
                season=LadderSettings.get_solo().current_season,
                dota_id=dota_id,
            )

            for i, team in enumerate(answer.teams):
                for player in team['players']:
                    player = next(p for p in players if p.name == player[0])

                    MatchPlayer.objects.create(match=match,
                                               player=player,
                                               team=i)

            MatchManager.add_scores(match)
            Player.objects.update_ranks()

        return match
Ejemplo n.º 2
0
    def score_history(self):
        player = self.object

        season = LadderSettings.get_solo().current_season
        score_changes = player.scorechange_set.filter(season=season)\
            .select_related(
                'match', 'match__match',
                'match__match__balance', 'match__match__balance__result'
            )

        max_vals = Player.objects\
            .filter(matchplayer__match__season=season).distinct()\
            .aggregate(Max('score'), Max('ladder_mmr'))
        score_max = max(1, max_vals['score__max'] or player.score)
        mmr_max = max(1, max_vals['ladder_mmr__max'] or player.score)

        score = mmr = 0
        for scoreChange in reversed(score_changes):
            score += scoreChange.score_change
            mmr += scoreChange.mmr_change

            scoreChange.score = score
            scoreChange.mmr = mmr
            scoreChange.score_percent = float(score) / score_max * 100
            scoreChange.mmr_percent = float(mmr) / mmr_max * 100

        return score_changes
Ejemplo n.º 3
0
    def handle(self, *args, **options):
        with transaction.atomic():
            ladder = LadderSettings.get_solo()
            ladder.current_season += 1
            ladder.save()

            for player in Player.objects.all():
                PlayerManager.init_score(player)
Ejemplo n.º 4
0
    def get_object(self, queryset=None):
        player = super(PlayerDetail, self).get_object(queryset)

        season = LadderSettings.get_solo().current_season
        player.matches = player.matchplayer_set\
            .filter(match__season=season)\
            .select_related('match')

        return player
Ejemplo n.º 5
0
    def get_queryset(self):
        qs = super(MatchList, self).get_queryset()

        season = LadderSettings.get_solo().current_season
        qs = qs.filter(matchplayer__match__season=season).distinct()\
            .prefetch_related(Prefetch(
                'matchplayer_set',
                queryset=MatchPlayer.objects.select_related('match')
            ))
        return qs
Ejemplo n.º 6
0
    def add_scores(match):
        from app.ladder.models import ScoreChange
        from app.ladder.models import LadderSettings

        # TODO: make values like win/loss change and underdog bonus changeble in admin panel
        mmr_diff = match.balance.teams[0]['mmr'] - match.balance.teams[1]['mmr']
        underdog = 0 if mmr_diff <= 0 else 1
        underdog_bonus = abs(
            mmr_diff
        ) // MatchManager.underdog_diff * 15  # 15 mmr points for each 200 mmr diff
        underdog_bonus = min(15, underdog_bonus)  # but no more than 15 mmr

        print('mmr diff: %d' % mmr_diff)
        print('underdog: %d' % underdog)
        print('underdog bonus: %d' % underdog_bonus)
        print('')

        for matchPlayer in match.matchplayer_set.all():
            is_victory = 1 if matchPlayer.team == match.winner else -1
            is_underdog = 1 if matchPlayer.team == underdog else -1

            score_change = 1 * is_victory

            mmr_per_game = LadderSettings.get_solo().mmr_per_game
            mmr_change = mmr_per_game * is_victory
            mmr_change += underdog_bonus * is_underdog

            use_boundary = False  # TODO: get this values from LadderSettings
            if use_boundary:
                # make sure new ladder mmr is in boundaries
                player = matchPlayer.player
                new_mmr = player.ladder_mmr + mmr_change
                new_mmr = max(player.min_allowed_mmr,
                              min(new_mmr, player.max_allowed_mmr))
                mmr_change = new_mmr - player.ladder_mmr

            ScoreChange.objects.create(
                player=matchPlayer.player,
                score_change=score_change,
                mmr_change=mmr_change,
                match=matchPlayer,
                season=LadderSettings.get_solo().current_season,
            )
 def handle(self, *args, **options):
     with transaction.atomic():
         for player in Player.objects.all():
             mmr_diff = player.dota_mmr - player.ladder_mmr
             ScoreChange.objects.create(
                 player=player,
                 mmr_change=mmr_diff,
                 info='Updated MMR system',
                 season=LadderSettings.get_solo().current_season,
             )
Ejemplo n.º 8
0
def score_change(instance, **kwargs):
    player = instance.player

    season = LadderSettings.get_solo().current_season
    vals = player.scorechange_set.filter(season=season).aggregate(
        Sum('mmr_change'), Sum('score_change'))

    player.ladder_mmr = vals['mmr_change__sum']
    player.score = vals['score_change__sum']

    player.save()
Ejemplo n.º 9
0
    def balance_custom(teams):
        from app.balancer.models import BalanceAnswer

        mmr_exponent = LadderSettings.get_solo().balance_exponent
        answer = balance_from_teams(teams, mmr_exponent)

        answer = BalanceAnswer.objects.create(
            teams=answer['teams'],
            mmr_diff=answer['mmr_diff'],
            mmr_diff_exp=answer['mmr_diff_exp'],
        )

        return answer
Ejemplo n.º 10
0
    def get_context_data(self, **kwargs):
        context = super(LadderStats, self).get_context_data(**kwargs)

        all_time = Match.objects.all()
        this_season = Match.objects.filter(
            season=LadderSettings.get_solo().current_season)
        last_days = Match.objects.filter(date__gte=datetime.now() -
                                         timedelta(days=3))

        context.update({
            'all_time': self.get_stats(all_time),
            'this_season': self.get_stats(this_season),
            'last_days': self.get_stats(last_days),
        })
        return context
Ejemplo n.º 11
0
    def init_score(player, reset_mmr=False):
        from app.ladder.models import ScoreChange
        from app.ladder.models import LadderSettings

        if reset_mmr:
            initial_mmr = PlayerManager.dota_to_ladder_mmr(player.dota_mmr)
        else:
            # take mmr from last season
            initial_mmr = player.ladder_mmr

        ScoreChange.objects.create(
            player=player,
            score_change=25,
            mmr_change=initial_mmr,
            info='Season started',
            season=LadderSettings.get_solo().current_season,
        )

        player.min_allowed_mmr = initial_mmr - 1000
        player.max_allowed_mmr = initial_mmr + 1000
        player.save()
Ejemplo n.º 12
0
    def balance_teams(players, role_balancing=True):
        from app.balancer.models import BalanceResult, BalanceAnswer

        # balance teams and save result
        # TODO: make mmr_exponent changable from admin panel
        mmr_exponent = LadderSettings.get_solo().balance_exponent
        if role_balancing:
            answers = role_balance_teams(players, mmr_exponent)
        else:
            players = [(p.name, p.ladder_mmr) for p in players]
            answers = balance_teams(players, mmr_exponent)

        with transaction.atomic():
            result = BalanceResult.objects.create(mmr_exponent=mmr_exponent)
            for answer in answers:
                BalanceAnswer.objects.create(
                    teams=answer['teams'],
                    mmr_diff=answer['mmr_diff'],
                    mmr_diff_exp=answer['mmr_diff_exp'],
                    result=result)

        return result
Ejemplo n.º 13
0
    def update_ranks(self):
        from app.ladder.models import LadderSettings

        # recalculate player rankings by particular field (ladder_mmr or score)
        def update_ranks_by(field):
            players.sort(key=lambda p: getattr(p, field), reverse=True)

            ranks = [1]
            for i in range(1, len(players)):
                curr_val = getattr(players[i], field)
                prev_val = getattr(players[i - 1], field)
                ranks.append(ranks[i - 1] if curr_val == prev_val else i + 1)

            for i, player in enumerate(players):
                setattr(player, f'rank_{field}', ranks[i])
                player.save()

        season = LadderSettings.get_solo().current_season
        players = self.filter(matchplayer__match__season=season).distinct()
        players = players or self.all()
        players = list(players)  # evaluate

        update_ranks_by('ladder_mmr')
        update_ranks_by('score')