Skip to content

Commit

Permalink
Merge 8a981ab into 1dbd380
Browse files Browse the repository at this point in the history
  • Loading branch information
lfalvarez committed Sep 6, 2018
2 parents 1dbd380 + 8a981ab commit f41c3e2
Show file tree
Hide file tree
Showing 10 changed files with 443 additions and 6 deletions.
19 changes: 19 additions & 0 deletions agenda/migrations/0005_auto_20180905_1922.py
@@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.9 on 2018-09-05 19:22
from __future__ import unicode_literals

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('agenda', '0004_auto_20180525_1552'),
]

operations = [
migrations.AlterModelOptions(
name='activity',
options={'ordering': ['date']},
),
]
20 changes: 20 additions & 0 deletions elections/migrations/0034_auto_20180903_1614.py
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.9 on 2018-09-03 16:14
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('elections', '0033_auto_20180717_2345'),
]

operations = [
migrations.AlterField(
model_name='election',
name='extra_info_content',
field=models.TextField(blank=True, help_text='Voc\xea pode usar Markdown. <br/> <a href="http://daringfireball.net/projects/markdown/syntax" target="_blank">Markdown syntax</a> allowed, but no raw HTML. Examples: **bold**, *italic*, indent 4 spaces for a code block.', max_length=3000, null=True),
),
]
Empty file added merepresenta/match/__init__.py
Empty file.
97 changes: 97 additions & 0 deletions merepresenta/match/matrix_builder.py
@@ -0,0 +1,97 @@
import numpy as np
from candidator.models import Position
from elections.models import QuestionCategory
from merepresenta.models import Candidate


class MatrixBuilder(object):
def __init__(self, *args, **kwargs):
self.positions = Position.objects.all().order_by('id')
self.candidates = Candidate.objects.filter(candidatequestioncategory__isnull=False).order_by('id')
self.categories = QuestionCategory.objects.all().order_by('id')
self.positions_id = self.set_index_of(self.positions)
self.categories_id = self.set_index_of(self.categories)
self.candidates_id = self.set_index_of(self.candidates)
self.electors_categories = np.ones(self.categories.count())
self.coalicagaos_nota = self.get_coaligacao_marks()

def set_index_of(self, variable):
index = 0
result = {}
for v in variable:
result[v.id] = index
index +=1
return result

def get_coaligacao_marks(self):
coalicagaos_nota = np.ones(len(self.candidates_id))
for c in self.candidates:
index = self.candidates_id[c.id]
try:
mark = c.partido.coaligacao.mark
coalicagaos_nota[index] = mark
except:
pass
return coalicagaos_nota

def get_positions_vector_for_category(self, cat):
result = np.zeros(self.positions.count())
for topic in cat.topics.all():
i = self.positions_id[topic.right_answer.position.id]
result[i] = 1
return result

def get_matrix_positions_and_categories(self):
r = []
for c in self.categories:
r.append(self.get_positions_vector_for_category(c))
return np.vstack(r).T

def get_positions_vector_for_candidate(self, cand):
r = np.zeros(self.positions.count())
for p in self.positions:
if cand.candidatequestioncategory_set.filter(category=p.topic.category).exists():
multiplier = 2
else:
multiplier = 1
if cand.taken_positions.filter(position=p).exists():
index = self.positions_id[p.id]
r[index] = 1 * multiplier
return r.T

def get_matrix_positions_and_candidates(self):
r = []
for c in self.candidates:
r.append(self.get_positions_vector_for_candidate(c))
return np.vstack(r)

def get_candidates_right_positions_matrix(self):
C = self.get_matrix_positions_and_candidates()
P = self.get_matrix_positions_and_categories()
return np.dot(C ,P)

def set_electors_categories(self, categories):
for c in categories:
index = self.categories_id[c.id]
self.electors_categories[index] = 3

def get_candidates_result(self):
# Candidates right answers multiplied by 2 if she chooses
# the given TEMA
CPR = self.get_candidates_right_positions_matrix()
return np.dot(CPR, self.electors_categories)

def get_result(self):
C = self.get_candidates_result()
notas = self.coalicagaos_nota.T
return C * notas

def get_result_as_array(self):
r = self.get_result()
as_array = []
index = 0
for c in self.candidates:
i = self.candidates_id[c.id]
mark = r[i]
as_array.append({'candidato': c, 'nota': mark})
return as_array
207 changes: 207 additions & 0 deletions merepresenta/match/tests/match_tests.py
@@ -0,0 +1,207 @@
# coding=utf-8
from django.test import TestCase
from elections.tests import VotaInteligenteTestCase
from popular_proposal.models import PopularProposal, Commitment
from merepresenta.models import (MeRepresentaPopularProposal,
MeRepresentaCommitment,
Candidate,
Coaligacao,
Partido,
VolunteerInCandidate,
CandidateQuestionCategory,
LGBTQDescription,
RightAnswer,
QuestionCategory)
from django.contrib.auth.models import User
from elections.models import Election, Topic
from candidator.models import Position, TakenPosition
from django.utils import timezone
import datetime
from django.core.urlresolvers import reverse
from merepresenta.voluntarios.models import VolunteerProfile
from backend_candidate.models import Candidacy
from django.test import override_settings
import numpy as np
from merepresenta.match.matrix_builder import MatrixBuilder
from numpy.testing import assert_equal


class QuestionCategoryVectors(TestCase):
def setUp(self):
super(QuestionCategoryVectors, self).setUp()
self.c1 = Candidate.objects.create(name='c1', cpf='1')
self.c2 = Candidate.objects.create(name='c2', cpf='2')
self.c3 = Candidate.objects.create(name='c3', cpf='3')

self.cat1 = QuestionCategory.objects.create(name="Pautas LGBT")
topic = Topic.objects.create(label=u"Adoção de crianças por famílias LGBTs", category=self.cat1)
yes = Position.objects.create(topic=topic, label=u"Sou a FAVOR da adoção de crianças por famílias LGBTs")
no = Position.objects.create(topic=topic, label=u"Sou CONTRA a adoção de crianças por famílias LGBTs")
RightAnswer.objects.create(topic=topic,position=yes)
TakenPosition.objects.create(topic=topic, person=self.c1, position=yes)
TakenPosition.objects.create(topic=topic, person=self.c2, position=no)
TakenPosition.objects.create(topic=topic, person=self.c3, position=yes)
CandidateQuestionCategory.objects.create(category=self.cat1, candidate=self.c1)

topic2 = Topic.objects.create(label=u"é A favor?", category=self.cat1)
yes2 = Position.objects.create(topic=topic2, label=u"Sou a FAVOR")
no2 = Position.objects.create(topic=topic2, label=u"Sou CONTRA")
RightAnswer.objects.create(topic=topic2, position=yes2)

TakenPosition.objects.create(topic=topic2, person=self.c1, position=no2)
TakenPosition.objects.create(topic=topic2, person=self.c2, position=yes2)
TakenPosition.objects.create(topic=topic2, person=self.c3, position=yes2)

self.cat2 = QuestionCategory.objects.create(name="Genero")
CandidateQuestionCategory.objects.create(category=self.cat2, candidate=self.c2)
topic3 = Topic.objects.create(label=u"Aborto é A favor?", category=self.cat2)
yes3 = Position.objects.create(topic=topic3, label=u"Sou a FAVOR")
no3 = Position.objects.create(topic=topic3, label=u"Sou CONTRA")
RightAnswer.objects.create(topic=topic3, position=yes3)
TakenPosition.objects.create(topic=topic3, person=self.c1, position=yes3)
TakenPosition.objects.create(topic=topic3, person=self.c2, position=no3)
TakenPosition.objects.create(topic=topic3, person=self.c3, position=no3)

topic4 = Topic.objects.create(label=u"Monitoramento da Lei do feminicídio", category=self.cat2)
yes4 = Position.objects.create(topic=topic4, label=u"Sou a FAVOR")
no4 = Position.objects.create(topic=topic4, label=u"Sou CONTRA")
RightAnswer.objects.create(topic=topic4, position=yes4)
TakenPosition.objects.create(topic=topic4, person=self.c1, position=yes4)
TakenPosition.objects.create(topic=topic4, person=self.c2, position=no4)
TakenPosition.objects.create(topic=topic4, person=self.c3, position=yes4)

self.cat3 = QuestionCategory.objects.create(name=u"Corrupção")
CandidateQuestionCategory.objects.create(category=self.cat3, candidate=self.c3)
topic5 = Topic.objects.create(label=u"Políticos serem donos de emissoras de rádio e TV", category=self.cat3)
yes5 = Position.objects.create(topic=topic5, label=u"Sou a FAVOR")
no5 = Position.objects.create(topic=topic5, label=u"Sou CONTRA")
RightAnswer.objects.create(topic=topic5, position=no5)
TakenPosition.objects.create(topic=topic5, person=self.c1, position=yes5)
TakenPosition.objects.create(topic=topic5, person=self.c2, position=yes5)
TakenPosition.objects.create(topic=topic5, person=self.c3, position=yes5)


def test_get_positions_vector_of_categories(self):
'''
Aqui o que eu quero lograr é um vector de dimensiones (Nao sei falar portugues)
Dx1 onde D é a quantidade de possivels respostas, asim:
yes1 | 1 |
no1 | 0 |
yes2 | 1 |
no2 | 0 |
yes3 | 0 |
no3 | 0 |
yes4 | 0 |
no4 | 0 |
yes5 | 0 |
no5 | 0 |
Más que só tem os dados do Tema
'''
builder = MatrixBuilder()
vector = builder.get_positions_vector_for_category(self.cat1)
self.assertEquals(vector.shape, (Position.objects.count(),))
expected_vector = np.array([1,0,1,0,0,0,0,0,0,0])

assert_equal(vector, expected_vector)

def test_get_matrix_of_positions_and_categories(self):
builder = MatrixBuilder()
matrix = builder.get_matrix_positions_and_categories()
expected_mat = np.array([[1,0,1,0,0,0,0,0,0,0],
[0,0,0,0,1,0,1,0,0,0],
[0,0,0,0,0,0,0,0,0,1]
]).T
assert_equal(matrix, expected_mat)

def test_get_zeros_if_not_right_answers_selected(self):
builder = MatrixBuilder()
vector = builder.get_positions_vector_for_category(self.cat1)
RightAnswer.objects.all().delete()
expected_vector = np.array([0,0,0,0,0,0,0,0,0,0])

def test_get_position_vector_respect_with_candidate(self):
builder = MatrixBuilder()
vector = builder.get_positions_vector_for_candidate(self.c1)
expected_vector = np.array([2,0,0,2,1,0,1,0,1,0])
assert_equal(vector, expected_vector)

def test_get_matrix_of_candidates_with_positions(self):
builder = MatrixBuilder()
matrix = builder.get_matrix_positions_and_candidates()
expected_mat = np.array([[2,0,0,2,1,0,1,0,1,0],
[0,1,1,0,0,2,0,2,1,0],
[1,0,1,0,0,1,1,0,2,0]
])
assert_equal(matrix, expected_mat)

def test_get_matrix_of_candidates_and_positions_and_right_positions(self):
builder = MatrixBuilder()
matrix = builder.get_candidates_right_positions_matrix()
self.assertEquals(matrix.shape, (3 ,3))
self.assertEquals(matrix[0][0], 2)
self.assertEquals(matrix[0][1], 2)
self.assertEquals(matrix[0][2], 0)

def test_set_electors_categories(self):
builder = MatrixBuilder()
builder.set_electors_categories([self.cat1, self.cat2])
electors_choices = builder.electors_categories
self.assertEquals(electors_choices.shape, (3,))
self.assertEquals(electors_choices[0], 3)
self.assertEquals(electors_choices[1], 3)
self.assertEquals(electors_choices[2], 1)

def test_get_candidates_right_answers_vs_electors(self):
builder = MatrixBuilder()
builder.set_electors_categories([self.cat1, self.cat2])
r = builder.get_candidates_result()
self.assertEquals(r.shape, (Candidate.objects.count(), ))

def test_get_candidates_full_answer_including_partido(self):
coaligacao = Coaligacao.objects.create(name=u"Coaligacao a", initials='CA', number='1234')
Partido.objects.create(name=u"Partido de los trabalhadores",
initials='PT',
number='12345',
mark=3.5,
coaligacao=coaligacao)
peta = Partido.objects.create(name=u"Petronila",
initials='PeTa',
number='1232',
mark=4.5,
coaligacao=coaligacao)
self.c1.partido = peta
self.c1.save()
builder = MatrixBuilder()
builder.set_electors_categories([self.cat1, self.cat2])
r = builder.get_result()
self.assertEquals(r.shape, (Candidate.objects.count(), ))
self.assertEquals(r[0], 48)
self.assertEquals(r[1], 3)
self.assertEquals(r[2], 9)

def test_get_result_as_dict(self):
coaligacao = Coaligacao.objects.create(name=u"Coaligacao a", initials='CA', number='1234')
Partido.objects.create(name=u"Partido de los trabalhadores",
initials='PT',
number='12345',
mark=3.5,
coaligacao=coaligacao)
peta = Partido.objects.create(name=u"Petronila",
initials='PeTa',
number='1232',
mark=4.5,
coaligacao=coaligacao)

self.c1.partido = peta
self.c1.save()
builder = MatrixBuilder()
builder.set_electors_categories([self.cat1, self.cat2])
r = builder.get_result_as_array()
self.assertEquals(r[0]['candidato'], self.c1)
self.assertEquals(r[0]['nota'], 48)
self.assertEquals(r[1]['candidato'], self.c2)
self.assertEquals(r[1]['nota'], 3)
self.assertEquals(r[2]['candidato'], self.c3)
self.assertEquals(r[2]['nota'], 9)
25 changes: 25 additions & 0 deletions merepresenta/migrations/0019_rightanswer.py
@@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.9 on 2018-09-03 16:14
from __future__ import unicode_literals

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('elections', '0034_auto_20180903_1614'),
('merepresenta', '0018_auto_20180830_1923'),
]

operations = [
migrations.CreateModel(
name='RightAnswer',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('position', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='candidator.Position')),
('topic', models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='right_answer', to='elections.Topic')),
],
),
]
20 changes: 20 additions & 0 deletions merepresenta/migrations/0020_auto_20180905_1922.py
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.9 on 2018-09-05 19:22
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('merepresenta', '0019_rightanswer'),
]

operations = [
migrations.AlterField(
model_name='partido',
name='mark',
field=models.FloatField(null=True),
),
]

0 comments on commit f41c3e2

Please sign in to comment.