from voters import *
from copeland import *
from aux import *
from copy import deepcopy

class dodgson():
    voters = None
    candidates = None
    num_cands = None
    num_voters = None
    cond_compare = None #pairwise comparison matrix
    flip_vec = None
    scores = None
    

    def __init__(self, voters):
        """
        Calculates the Dodgson winner of a set of voters
        """
        self.voters = voters
        self.num_voters = len(voters.votes)
        self.candidates = voters.cands
        self.num_cands = self.candidates.num_cands
        self.flip_vec = []
        self.scores = {}

    def __str__(self):
        w = self.winner()
        return "Dodgson winner: %s" % w
        

    def score(self):
        for c in self.candidates.candidates:
            self.scores[c] = 1
        cope = copeland(self.voters)
        cope.score()
        #print "copeland scores:"
        #print cope.scores
        for cd,sc in cope.scores.iteritems():
            if sc == self.num_cands-1:
                self.scores[cd] = 0
                return self.scores
        
        combs = all_combs(self.num_cands, self.num_voters)
        vecs = order_combs(combs)
        #maniwins = []

        for c in self.candidates.candidates:
            manips = self.manip_voter(c,vecs)
            self.scores[c] = manips
            #maniwins.append((manips,c))
        print "manipulations:"
        print self.scores


    def manip_voter(self,c,vecs):
        for vec in vecs:
            v = deepcopy(self.voters)
            i = 0
            for voter in v.votes:
                ind = voter.ballot.index(c)
                if ind >= vec[i]:
                    nind = ind - vec[i]
                    i += 1
                    voter.ballot.remove(c)
                    voter.ballot.insert(nind,c)
                    co = copeland(v)
                    co.score()
                    if co.scores[c] == self.num_cands-1:
                        manips = 0
                        for j in vec:
                            manips += j
                        return manips


    def condorcet_tally(self):
        for c1 in self.candidates:
            self.cond_comp[c1] = {}
            for c2 in self.candidates:
                self.cond_comp[c1][c2] = 0 #a matrix of candidates x candidates
                for voter in self.voters.votes:
                    s1 = 0
                    s2 = 0
                    for i in range(0, self.num_cands):
                        #check if the candidate is a pairwise winner
                        if voter.ballot[i] == c1:
                            s1 = i
                        if voter.ballot[i] == c2:
                            s2 = i
                    if s1 < s2: #if the index is lower, the score is higher
                        self.cond_comp[c1][c2] += 1

    def condorcet_winner(self):
        co = copeland(self.voters)
        co.score()
        for c,v in co.scores:
            if v == len(self.candidates)-1:
                return c
        return None
    

    def winner(self):
        self.score()
        #print "Dodgson:"
        #print self.scores
        bot = []
        val = self.num_cands*self.num_voters
        for v in self.scores.itervalues():
            if v < val:
                val = v
        for k,v in self.scores.iteritems():
            if v == val:
                bot.append(k)
        return bot


