diff --git a/elections/templates/elections/results/rank.html b/elections/templates/elections/results/rank.html index 073cfda..3e9cfc4 100644 --- a/elections/templates/elections/results/rank.html +++ b/elections/templates/elections/results/rank.html @@ -32,7 +32,7 @@ {% for cell in line %} - {{ cell }} + {{ cell }} {% endfor %} {% endwith %} diff --git a/elections/utils.py b/elections/utils.py index f8ed5db..5b0ec03 100644 --- a/elections/utils.py +++ b/elections/utils.py @@ -99,13 +99,8 @@ class TallyFunctions: """On dépouille un vote par classement et on crée la matrice des duels""" from .models import Duel, Option, Rank - def duel(a, b): - # Renvoie 1 si a est classé avant b, -1 si c'est l'inverse et - # 0 si a et b ont le même rang, ce qui permet d'avoir directement - # le graphe des duels en faisant le max avec la matrice nulle - return (a.rank < b.rank) - (a.rank > b.rank) - options = list(question.options.all()) + nb_options = len(options) ranks = Rank.objects.select_related("vote").filter(vote__option__in=options) ranks_by_user = {} @@ -121,12 +116,19 @@ class TallyFunctions: # Pour chaque votant·e, on regarde son classement for user in ranks_by_user: votes = ranks_by_user[user] - ballots.append(np.array([[duel(x, y) for x in votes] for y in votes])) + ballot = np.zeros((nb_options, nb_options)) + + for i in range(nb_options): + for j in range(i): + ballot[i, j] = int(votes[i].rank < votes[j].rank) + ballot[j, i] = int(votes[j].rank < votes[i].rank) + + ballots.append(ballot) if ballots != []: # On additionne les classements de tout le monde pour avoir la matrice # des duels - duels = np.maximum(sum(ballots), 0) + duels = sum(ballots) # Configuration du graphe graph = nx.DiGraph() @@ -136,21 +138,25 @@ class TallyFunctions: cells = [] # On enregistre la matrice - for i, line in enumerate(duels): - for j, cell in enumerate(line): - if cell > 0: - graph.add_edge(options[j], options[i], weight=cell) + for i in range(nb_options): + for j in range(nb_options): + if duels[i, j] > duels[j, i]: + graph.add_edge( + options[i], options[j], weight=(duels[i, j] - duels[j, i]) + ) + + if duels[i, j] > 0: cells.append( Duel( question=question, - winner=options[j], - loser=options[i], - amount=cell, + winner=options[i], + loser=options[j], + amount=duels[i, j], ) ) Duel.objects.bulk_create(cells) - # On utilise la méthode de schwartz pour trouver les options gagnantes + # On utilise la méthode de Schwartz pour trouver les options gagnantes while graph.edges(): losers = set() # Les options qui se font battre strictement for n in graph.nodes():