On affiche le nombre de personnes préférant A à B pour les duels

This commit is contained in:
Tom Hubrecht 2021-04-07 23:56:39 +02:00
parent 7460785e53
commit 3d6a538ebe
2 changed files with 23 additions and 17 deletions

View file

@ -32,7 +32,7 @@
</th>
{% for cell in line %}
<td class="has-text-centered has-tooltip-primary" {% if cell %}data-tooltip="{% blocktrans with winner=forloop.counter %}L'option {{ winner }} gagne le duel contre l'option {{ loser }} par {{ cell }} voix {% endblocktrans %}{% endif %}">{{ cell }}</td>
<td class="has-text-centered has-tooltip-primary" {% if cell %}data-tooltip="{% blocktrans with winner=forloop.counter %}L'option {{ winner }} est préférée à l'option {{ loser }} par {{ cell }} personnes.{% endblocktrans %}{% endif %}">{{ cell }}</td>
{% endfor %}
</tr>
{% endwith %}

View file

@ -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():