def test_team_elo(self): """Test du calcul de l'elo de l'équipe. Cas basiques""" elo_team1 = calc_team_elo([self.players[0]]) elo_team2 = calc_team_elo([self.players[1]]) self.assertEqual(elo_team1, self.players[0].get_elo()) self.assertEqual(elo_team2, self.players[1].get_elo()) elo_team1 = calc_team_elo([self.players[0], self.players[1]]) elo_team2 = calc_team_elo([self.players[2], self.players[3]]) self.assertEqual(elo_team1, 2050) self.assertEqual(elo_team2, 2300) elo_team1 = calc_team_elo( [self.players[0], self.players[1], self.players[4]]) elo_team2 = calc_team_elo( [self.players[2], self.players[3], self.players[5]]) self.assertEqual(round(elo_team1, 0), 2475) self.assertEqual(round(elo_team2, 0), 2309) elo_team1 = calc_team_elo([ self.players[0], self.players[1], self.players[4], self.players[7] ]) elo_team2 = calc_team_elo([ self.players[2], self.players[3], self.players[5], self.players[6] ]) self.assertEqual(round(elo_team1, 0), 2400) self.assertEqual(round(elo_team2, 0), 2325)
def test_prob_winning(self): """Test probabilité de gagner (>50%)""" team1 = [ self.players[0], self.players[1], self.players[4], self.players[7] ] team2 = [ self.players[2], self.players[3], self.players[5], self.players[6] ] self.assertEqual( round( prob_winning(calc_team_elo(team1) - calc_team_elo(team2)) * 100, 2), 66.61) self.assertEqual( round( prob_winning(calc_team_elo(team2) - calc_team_elo(team1)) * 100, 2), 33.39)
def test_prob_winnng_under50(self): """Test probabilité de gagner (<50%)""" team1 = [ self.players[0], self.players[1], self.players[6], self.players[7] ] team2 = [ self.players[2], self.players[3], self.players[4], self.players[5] ] # Probability is the same for everyone in the team self.assertEqual( round( prob_winning(calc_team_elo(team1) - calc_team_elo(team2)) * 100, 2), 1.24) self.assertEqual( round( prob_winning(calc_team_elo(team2) - calc_team_elo(team1)) * 100, 2), 98.76)
def balance_teams(request): if request.method == "POST": form = TeamsForm(request.POST) if form.is_valid() and len(form.cleaned_data["players"]) > 1: team_balancer = TeamBalancer(form.cleaned_data["players"]) teams = team_balancer.get_teams() context = {'form': form} context.update({ 'team1': teams[0], 'team2': teams[1], 'elo_team1': calc_team_elo(teams[0]), 'elo_team2': calc_team_elo(teams[1]) }) teams_eq = team_balancer.get_balanced_teams() if teams_eq[0] not in teams: delta_elo = calc_team_elo(teams_eq[0]) - calc_team_elo( teams_eq[1]) pw = prob_winning(delta_elo) * 100 context.update({ 'team1eq': teams_eq[0], 'team2eq': teams_eq[1], 'pw_team1eq': pw, 'pw_team2eq': 100 - pw }) else: context.update({'team1eq': None, 'team2eq': None}) # Add winning probability for teams delta_elo = calc_team_elo(teams[0]) - calc_team_elo(teams[1]) pw = prob_winning(delta_elo) * 100 if pw > 60 or pw < 40: color_cls = "is-danger" elif pw > 55 or pw < 45: color_cls = "is-warning" else: color_cls = "is-success" context.update({ "pw_team1": pw, "pw_team2": 100 - pw, "color_cls": color_cls }) return render(request, "gametracker/balance_teams.html", context) else: return render(request, "gametracker/balance_teams.html", {'form': form}) else: form = TeamsForm() return render(request, "gametracker/balance_teams.html", { 'form': form, 'team1': None, 'team2': None })
def update_elo(date=datetime.min): # Delete ELoLogs newer than the provided date elos_to_be_deleted = EloLog.objects.filter(date__gte=date) elos_to_be_deleted.delete() # Only get the queryset once, to avoid unnecessary calls to .save() persons = {p.name: p for p in Person.objects.all()} # Keep track of elo after each game elos = [] # Init elo and number of games for person_name, person in persons.items(): try: person_elos = EloLog.objects.filter(person=person) person.elo = person_elos.latest('date').elo person.ngames = person_elos.count() - 1 # First EloLog is init_elo except: person.elo = person.init_elo person.ngames = 0 elos.append( EloLog(person=person, date=datetime.min, elo=person.init_elo)) for game in Game.objects.filter( date__gte=date).order_by('date').prefetch_related( 'team1', 'team2').iterator(): # We can't call the queryset directly, otherwise the elo is updated to the latest one # So here we select 'persons' that are in game.team1 and game.team2 team1 = [ persons[name["identity__person__name"]] for name in game.team1.all().values("identity__person__name") if name["identity__person__name"] in persons ] team2 = [ persons[name["identity__person__name"]] for name in game.team2.all().values("identity__person__name") if name["identity__person__name"] in persons ] team1_elo = calc_team_elo(team1) team2_elo = calc_team_elo(team2) # Only update the elo if elo of both team1 and team2 have been calculated if game.ranked and team1_elo and team2_elo: delta_elo = team1_elo - team2_elo # Calculate each player's new elo for person in team1 + team2: if person in team1: person.elo = calculate_new_elo(person.elo, delta_elo, game.winner == "team1") else: person.elo = calculate_new_elo(person.elo, -delta_elo, game.winner == "team2") elos.append( EloLog(person=person, date=game.date, elo=person.elo)) person.ngames += 1 # Commit changes EloLog.objects.bulk_create(elos) for person_name, person in persons.items(): person.save()