From 39eff376898723d78dfbc1f1bdcc407c6e5e4a0b Mon Sep 17 00:00:00 2001 From: Beatriz Llamas Date: Thu, 9 Dec 2021 10:58:26 +0100 Subject: [PATCH 1/4] =?UTF-8?q?A=C3=B1adido=20m=C3=A9todo=20D=C2=B4Hont?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- decide/postproc/views.py | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/decide/postproc/views.py b/decide/postproc/views.py index 73024fae72..b651a141ab 100644 --- a/decide/postproc/views.py +++ b/decide/postproc/views.py @@ -19,6 +19,7 @@ def identity(self, options): out.sort(key=lambda x: -x['postproc']) return Response(out) + def HuntingtonHill(self,numEscanos,options): votosTotales = 0 @@ -85,9 +86,31 @@ def HuntingtonHill(self,numEscanos,options): return Response(options) + def dHont(self, options, numEscanos): + + #Añadimos un campo para el contador de escaños asignados a cada opción + for op in options: + op['postproc'] = 0 + + #Para cada escaño recorremos todas las opciones usando la fórmula de d'Hont: número de votos de esa opción/(número de escaños asignados a esa opción + 1) + for escano in range(0, numEscanos): + #Lista de tamaño igual al número de opciones. Recuento al aplicar la fórmula a cada opción (ordenados en la misma forma) + recuento = [] + for op in options: + r = op['votes'] / (op['postproc']+1) + recuento.append(r) + + #Obtenemos el índice del máximo valor en la lista de recuento de votos (del ganador del escaño) + ganador = recuento.index(max(recuento)) + #En la posicion del ganador le sumamos 1 escaño + options[ganador]['postproc'] += 1 + + return Response(options) + + def post(self, request): """ - * type: IDENTITY | EQUALITY | WEIGHT + * type: IDENTITY | HUNTINGTONHILL | DHONT * options: [ { option: str, @@ -100,8 +123,15 @@ def post(self, request): t = request.data.get('type', 'IDENTITY') opts = request.data.get('options', []) + numEscanos = request.data.get('numEscanos', 0) if t == 'IDENTITY': return self.identity(opts) + elif t == 'HUNTINGTONHILL': + return self.HuntingtonHill(options=opts, numEscanos=numEscanos) + + elif t == 'DHONT': + return self.dHont(options=opts, numEscanos=numEscanos) + return Response({}) From 47cf00b5c900db4bc023128ea0a24f82a9826e9a Mon Sep 17 00:00:00 2001 From: Beatriz Llamas Date: Thu, 9 Dec 2021 11:09:49 +0100 Subject: [PATCH 2/4] =?UTF-8?q?A=C3=B1adido=20m=C3=A9todo=20D'Hont=20al=20?= =?UTF-8?q?m=C3=B3dulo=20voting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- decide/voting/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/decide/voting/models.py b/decide/voting/models.py index b11f983f69..a34112db97 100644 --- a/decide/voting/models.py +++ b/decide/voting/models.py @@ -36,7 +36,7 @@ class Voting(models.Model): start_date = models.DateTimeField(blank=True, null=True) end_date = models.DateTimeField(blank=True, null=True) - tipo_votacion = [("IDENTITY", "IDENTITY"),("HUNTINGTONHILL", "HUNTINGTONHILL")] + tipo_votacion = [("IDENTITY", "IDENTITY"),("HUNTINGTONHILL", "HUNTINGTONHILL"),("DHONT","DHONT")] tipo = models.CharField(choices=tipo_votacion, max_length=20, default="IDENTITY", verbose_name='Count method') From 483d32d2add17285878130716da534027a081471 Mon Sep 17 00:00:00 2001 From: Beatriz Llamas Date: Sun, 19 Dec 2021 21:16:35 +0100 Subject: [PATCH 3/4] =?UTF-8?q?test=20(dhont):=20a=C3=B1adido=20test=20del?= =?UTF-8?q?=20metodo=20D'Hont?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- decide/postproc/tests.py | 164 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) diff --git a/decide/postproc/tests.py b/decide/postproc/tests.py index 1a6a27e86c..92034bda21 100644 --- a/decide/postproc/tests.py +++ b/decide/postproc/tests.py @@ -42,3 +42,167 @@ def test_identity(self): values = response.json() self.assertEqual(values, expected_result) + + + def testDHont1(self): #Fácil de comprobar manualmente + data = { + 'type': 'DHONT', + 'options': [ + {'option':'Option 1','number':1,'votes': 12000}, + {'option':'Option 2','number':2,'votes': 140000}, + {'option':'Option 3','number':3,'votes': 110000}, + {'option':'Option 4','number':4,'votes': 205000}, + {'option':'Option 5','number':5,'votes': 150000}, + {'option':'Option 6','number':6,'votes': 16000} + ], + 'numEscanos': 10 + } + + expected_result = [ + {'option':'Option 1','number':1,'votes': 12000, 'postproc': 0}, + {'option':'Option 2','number':2,'votes': 140000, 'postproc': 2}, + {'option':'Option 3','number':3,'votes': 110000, 'postproc': 2}, + {'option':'Option 4','number':4,'votes': 205000, 'postproc': 4}, + {'option':'Option 5','number':5,'votes': 150000, 'postproc': 2}, + {'option':'Option 6','number':6,'votes': 16000, 'postproc': 0} + ] + + response = self.client.post('/postproc/', data, format='json') + self.assertEqual(response.status_code, 200) + + values = response.json() + self.assertEqual(values, expected_result) + + + def testDHont2(self): #Votos muy igualados + data = { + 'type': 'DHONT', + 'options': [ + {'option':'Option 1','number':1,'votes': 65000}, + {'option':'Option 2','number':2,'votes': 60000}, + {'option':'Option 3','number':3,'votes': 50000}, + {'option':'Option 4','number':4,'votes': 55000}, + {'option':'Option 5','number':5,'votes': 62000}, + {'option':'Option 6','number':6,'votes': 57000}, + ], + 'numEscanos': 10 + } + + expected_result = [ + {'option':'Option 1','number':1,'votes': 65000,'postproc': 2}, + {'option':'Option 2','number':2,'votes': 60000,'postproc': 2}, + {'option':'Option 3','number':3,'votes': 50000,'postproc': 1}, + {'option':'Option 4','number':4,'votes': 55000,'postproc': 1}, + {'option':'Option 5','number':5,'votes': 62000,'postproc': 2}, + {'option':'Option 6','number':6,'votes': 57000,'postproc': 2}, + ] + + response = self.client.post('/postproc/', data, format='json') + self.assertEqual(response.status_code, 200) + + values = response.json() + self.assertEqual(values, expected_result) + + + def testDHont3(self): #Votos muy desiguales + data = { + 'type': 'DHONT', + 'options': [ + {'option':'Option 1','number':1,'votes': 65000}, + {'option':'Option 2','number':2,'votes': 30000}, + {'option':'Option 3','number':3,'votes': 1500}, + {'option':'Option 4','number':4,'votes': 4500}, + {'option':'Option 5','number':5,'votes': 2000}, + ], + 'numEscanos': 100 + } + + expected_result = [ + {'option':'Option 1','number':1,'votes': 65000,'postproc': 32}, + {'option':'Option 2','number':2,'votes': 30000,'postproc': 15}, + {'option':'Option 3','number':3,'votes': 1500,'postproc': 0}, + {'option':'Option 4','number':4,'votes': 4500,'postproc': 2}, + {'option':'Option 5','number':5,'votes': 2000,'postproc': 1}, + ] + + response = self.client.post('/postproc/', data, format='json') + self.assertEqual(response.status_code, 200) + + values = response.json() + self.assertEqual(values, expected_result) + + + def testDHont4(self): #Votos iguales + data = { + 'type': 'DHONT', + 'options': [ + {'option':'Option 1','number':1,'votes': 50000}, + {'option':'Option 2','number':2,'votes': 50000}, + {'option':'Option 3','number':3,'votes': 50000} + ], + 'numEscanos': 300 + } + + expected_result = [ + {'option':'Option 1','number':1,'votes': 50000,'postproc': 100}, + {'option':'Option 2','number':2,'votes': 50000,'postproc': 100}, + {'option':'Option 3','number':3,'votes': 50000,'postproc': 100} + ] + + response = self.client.post('/postproc/', data, format='json') + self.assertEqual(response.status_code, 200) + + values = response.json() + self.assertEqual(values, expected_result) + + + def testDHont5(self): #Votos muy elevados + data = { + 'type': 'DHONT', + 'options': [ + {'option':'Option 1','number':1,'votes': 150150150150150}, + {'option':'Option 2','number':2,'votes': 300300300300300}, + {'option':'Option 3','number':3,'votes': 200200200200200} + ], + 'numEscanos': 100 + } + + expected_result = [ + {'option':'Option 1','number':1,'votes': 150150150150150,'postproc': 23}, + {'option':'Option 2','number':2,'votes': 300300300300300,'postproc': 46}, + {'option':'Option 3','number':3,'votes': 200200200200200,'postproc': 31} + ] + + response = self.client.post('/postproc/', data, format='json') + self.assertEqual(response.status_code, 200) + + values = response.json() + self.assertEqual(values, expected_result) + + + def testDHont5(self): #Escaños elevados + data = { + 'type': 'DHONT', + 'options': [ + {'option':'Option 1','number':1,'votes': 15000}, + {'option':'Option 2','number':2,'votes': 75000}, + {'option':'Option 3','number':3,'votes': 10000}, + {'option':'Option 4','number':4,'votes': 5000}, + {'option':'Option 5','number':5,'votes': 2500}, + ], + 'numEscanos': 900 + } + + expected_result = [ + {'option':'Option 1','number':1,'votes': 15000,'postproc': 338}, + {'option':'Option 2','number':2,'votes': 7500,'postproc': 169}, + {'option':'Option 3','number':3,'votes': 10000,'postproc': 225}, + {'option':'Option 4','number':4,'votes': 5000,'postproc': 112}, + {'option':'Option 5','number':5,'votes': 2500,'postproc': 56} + ] + + response = self.client.post('/postproc/', data, format='json') + self.assertEqual(response.status_code, 200) + + values = response.json() + self.assertEqual(values, expected_result) \ No newline at end of file From fdff4c8ea7024ca08d03d20a9cce44ed51f88aa1 Mon Sep 17 00:00:00 2001 From: romflorod Date: Mon, 20 Dec 2021 18:50:05 +0100 Subject: [PATCH 4/4] Arreglo tests DHONT --- decide/postproc/tests.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/decide/postproc/tests.py b/decide/postproc/tests.py index 92034bda21..cb534f246c 100644 --- a/decide/postproc/tests.py +++ b/decide/postproc/tests.py @@ -118,10 +118,10 @@ def testDHont3(self): #Votos muy desiguales } expected_result = [ - {'option':'Option 1','number':1,'votes': 65000,'postproc': 32}, - {'option':'Option 2','number':2,'votes': 30000,'postproc': 15}, - {'option':'Option 3','number':3,'votes': 1500,'postproc': 0}, - {'option':'Option 4','number':4,'votes': 4500,'postproc': 2}, + {'option':'Option 1','number':1,'votes': 65000,'postproc': 65}, + {'option':'Option 2','number':2,'votes': 30000,'postproc': 29}, + {'option':'Option 3','number':3,'votes': 1500,'postproc': 1}, + {'option':'Option 4','number':4,'votes': 4500,'postproc': 4}, {'option':'Option 5','number':5,'votes': 2000,'postproc': 1}, ] @@ -180,7 +180,7 @@ def testDHont5(self): #Votos muy elevados self.assertEqual(values, expected_result) - def testDHont5(self): #Escaños elevados + def testDHont6(self): #Escaños elevados data = { 'type': 'DHONT', 'options': [ @@ -194,11 +194,11 @@ def testDHont5(self): #Escaños elevados } expected_result = [ - {'option':'Option 1','number':1,'votes': 15000,'postproc': 338}, - {'option':'Option 2','number':2,'votes': 7500,'postproc': 169}, - {'option':'Option 3','number':3,'votes': 10000,'postproc': 225}, - {'option':'Option 4','number':4,'votes': 5000,'postproc': 112}, - {'option':'Option 5','number':5,'votes': 2500,'postproc': 56} + {'option':'Option 1','number':1,'votes': 15000,'postproc': 126}, + {'option':'Option 2','number':2,'votes': 75000,'postproc': 630}, + {'option':'Option 3','number':3,'votes': 10000,'postproc': 83}, + {'option':'Option 4','number':4,'votes': 5000,'postproc': 41}, + {'option':'Option 5','number':5,'votes': 2500,'postproc': 20} ] response = self.client.post('/postproc/', data, format='json')