mirror of
https://github.com/ae-utbm/sith.git
synced 2025-04-01 09:20:24 +00:00
refactor election result computing
This commit is contained in:
parent
e222ac6762
commit
a74037a7f3
@ -1,4 +1,5 @@
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.db.models import Count
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
@ -110,23 +111,24 @@ class Role(OrderedModel):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.title} - {self.election.title}"
|
return f"{self.title} - {self.election.title}"
|
||||||
|
|
||||||
def results(self, total_vote):
|
def results(self, total_vote: int) -> dict[str, dict[str, int | float]]:
|
||||||
results = {}
|
if total_vote == 0:
|
||||||
|
candidates = self.candidatures.values_list("user__username")
|
||||||
|
return {
|
||||||
|
key: {"vote": 0, "percent": 0} for key in ["blank_votes", *candidates]
|
||||||
|
}
|
||||||
total_vote *= self.max_choice
|
total_vote *= self.max_choice
|
||||||
|
results = {"total vote": total_vote}
|
||||||
non_blank = 0
|
non_blank = 0
|
||||||
for candidature in self.candidatures.all():
|
candidatures = self.candidatures.annotate(nb_votes=Count("votes")).values(
|
||||||
cand_results = {}
|
"nb_votes", "user__username"
|
||||||
cand_results["vote"] = self.votes.filter(candidature=candidature).count()
|
)
|
||||||
if total_vote == 0:
|
for candidature in candidatures:
|
||||||
cand_results["percent"] = 0
|
non_blank += candidature["nb_votes"]
|
||||||
else:
|
results[candidature["user__username"]] = {
|
||||||
cand_results["percent"] = cand_results["vote"] * 100 / total_vote
|
"vote": candidature["nb_votes"],
|
||||||
non_blank += cand_results["vote"]
|
"percent": candidature["nb_votes"] * 100 / total_vote,
|
||||||
results[candidature.user.username] = cand_results
|
}
|
||||||
results["total vote"] = total_vote
|
|
||||||
if total_vote == 0:
|
|
||||||
results["blank vote"] = {"vote": 0, "percent": 0}
|
|
||||||
else:
|
|
||||||
results["blank vote"] = {
|
results["blank vote"] = {
|
||||||
"vote": total_vote - non_blank,
|
"vote": total_vote - non_blank,
|
||||||
"percent": (total_vote - non_blank) * 100 / total_vote,
|
"percent": (total_vote - non_blank) * 100 / total_vote,
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
|
import pytest
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
from model_bakery import baker
|
||||||
|
|
||||||
|
from core.baker_recipes import subscriber_user
|
||||||
from core.models import Group, User
|
from core.models import Group, User
|
||||||
from election.models import Election
|
from election.models import Candidature, Election, ElectionList, Role, Vote
|
||||||
|
|
||||||
|
|
||||||
class TestElection(TestCase):
|
class TestElection(TestCase):
|
||||||
@ -12,8 +15,7 @@ class TestElection(TestCase):
|
|||||||
cls.election = Election.objects.first()
|
cls.election = Election.objects.first()
|
||||||
cls.public_group = Group.objects.get(id=settings.SITH_GROUP_PUBLIC_ID)
|
cls.public_group = Group.objects.get(id=settings.SITH_GROUP_PUBLIC_ID)
|
||||||
cls.sli = User.objects.get(username="sli")
|
cls.sli = User.objects.get(username="sli")
|
||||||
cls.subscriber = User.objects.get(username="subscriber")
|
cls.public = baker.make(User)
|
||||||
cls.public = User.objects.get(username="public")
|
|
||||||
|
|
||||||
|
|
||||||
class TestElectionDetail(TestElection):
|
class TestElectionDetail(TestElection):
|
||||||
@ -36,7 +38,7 @@ class TestElectionDetail(TestElection):
|
|||||||
|
|
||||||
class TestElectionUpdateView(TestElection):
|
class TestElectionUpdateView(TestElection):
|
||||||
def test_permission_denied(self):
|
def test_permission_denied(self):
|
||||||
self.client.force_login(self.subscriber)
|
self.client.force_login(subscriber_user.make())
|
||||||
response = self.client.get(
|
response = self.client.get(
|
||||||
reverse("election:update", args=str(self.election.id))
|
reverse("election:update", args=str(self.election.id))
|
||||||
)
|
)
|
||||||
@ -45,3 +47,47 @@ class TestElectionUpdateView(TestElection):
|
|||||||
reverse("election:update", args=str(self.election.id))
|
reverse("election:update", args=str(self.election.id))
|
||||||
)
|
)
|
||||||
assert response.status_code == 403
|
assert response.status_code == 403
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_election_results():
|
||||||
|
election = baker.make(
|
||||||
|
Election, voters=baker.make(User, _quantity=50, _bulk_create=True)
|
||||||
|
)
|
||||||
|
lists = baker.make(ElectionList, election=election, _quantity=2, _bulk_create=True)
|
||||||
|
roles = baker.make(
|
||||||
|
Role, election=election, max_choice=iter([1, 2]), _quantity=2, _bulk_create=True
|
||||||
|
)
|
||||||
|
users = baker.make(User, _quantity=4, _bulk_create=True)
|
||||||
|
cand = [
|
||||||
|
baker.make(Candidature, role=roles[0], user=users[0], election_list=lists[0]),
|
||||||
|
baker.make(Candidature, role=roles[0], user=users[1], election_list=lists[1]),
|
||||||
|
baker.make(Candidature, role=roles[1], user=users[2], election_list=lists[0]),
|
||||||
|
baker.make(Candidature, role=roles[1], user=users[3], election_list=lists[1]),
|
||||||
|
]
|
||||||
|
votes = [
|
||||||
|
baker.make(Vote, role=roles[0], _quantity=20, _bulk_create=True),
|
||||||
|
baker.make(Vote, role=roles[0], _quantity=25, _bulk_create=True),
|
||||||
|
baker.make(Vote, role=roles[1], _quantity=20, _bulk_create=True),
|
||||||
|
baker.make(Vote, role=roles[1], _quantity=35, _bulk_create=True),
|
||||||
|
baker.make(Vote, role=roles[1], _quantity=10, _bulk_create=True),
|
||||||
|
]
|
||||||
|
cand[0].votes.set(votes[0])
|
||||||
|
cand[1].votes.set(votes[1])
|
||||||
|
cand[2].votes.set([*votes[2], *votes[4]])
|
||||||
|
cand[3].votes.set([*votes[3], *votes[4]])
|
||||||
|
|
||||||
|
assert election.results == {
|
||||||
|
roles[0].title: {
|
||||||
|
cand[0].user.username: {"percent": 40.0, "vote": 20},
|
||||||
|
cand[1].user.username: {"percent": 50.0, "vote": 25},
|
||||||
|
"blank vote": {"percent": 10.0, "vote": 5},
|
||||||
|
"total vote": 50,
|
||||||
|
},
|
||||||
|
roles[1].title: {
|
||||||
|
cand[2].user.username: {"percent": 30.0, "vote": 30},
|
||||||
|
cand[3].user.username: {"percent": 45.0, "vote": 45},
|
||||||
|
"blank vote": {"percent": 25.0, "vote": 25},
|
||||||
|
"total vote": 100,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user