from candidates import *
from voters import *
from plurality import *
from borda import *
from copeland import *
from approval import *
from stv import *
from election import *
from voter_permutations import *
from voter_distr import * 
from aux import *

NUM_EXPS    = 100
NUM_ELECS   = 10
NUM_CANDS   = 3
NUM_VOTES   = 50

def generate_elections(no,c,nv,path):
    elections = []
    for i in range(0,no):
        e = generate_election(i,c,nv,path)
        elections.append(e)
    return elections        

def generate_election(no,c,nv,path):
    vs = voters(c, nv, None)
    name = path+"/blt%i.blt" % no
    vs.output_ballots(name)
    v = voters.parser(name)
    return v

if __name__ == "__main__":
    cws = []
    cls = []
    plw = []
    bow = []
    apw = []
    evw = []
    stw = []
    pll = []
    bol = []
    apl = []
    evl = []
    stl = []

    for i in range(0,NUM_EXPS):
        c = candidates(None, NUM_CANDS)
        elections = generate_elections(NUM_ELECS,c,NUM_VOTES,"random")

        #check for number of condorcet winners existing
        #print "Calculating the condorcet winners and losers"
        condorcet_winners = 0
        condorcet_losers = 0
        conw_exists_elec = []
        conl_exists_elec = []
        #print "Number of elections %i" % len(elections)
        for e in elections:
            co = copeland(e)
            co.score()
            for cand in c.candidates:
                if co.scores[cand] == NUM_CANDS-1 and len(co.winner()) == 1: #num of remaining cands
                    condorcet_winners += 1
                    conw_exists_elec.append((e, cand))
                if co.scores[cand] == 0: #condorcet loser
                    condorcet_losers += 1
                    conl_exists_elec.append((e, cand))
        #print condorcet_winners
        #print condorcet_losers
        cws.append(float(condorcet_winners)/NUM_ELECS)
        cls.append(float(condorcet_losers)/NUM_ELECS)

        
        #How often do the rules elect the condorcet winner?
        #print "How often do rules elect the Condorcet Winner?"
        wp = 0
        wb = 0
        wa = 0
        we = 0
        ws = 0
        for e,cand in conw_exists_elec:
            pl = plurality(e)
            bo = borda(e)
            ap = approval(e)
            ev = approval(e, 'even_and_equal')
            st = stv(e)
            if [cand] == pl.winner():
                wp += 1
            if [cand] == bo.winner():
                wb += 1
            if [cand] == ap.winner():
                wa += 1
            if [cand] == ev.winner():
                we += 1
            if [cand] == st.winner():
                ws += 1
        plw.append(float(wp)/condorcet_winners)
        bow.append(float(wb)/condorcet_winners)
        apw.append(float(wa)/condorcet_winners)
        evw.append(float(we)/condorcet_winners)
        stw.append(float(ws)/condorcet_winners)
        #print wp, wb, wa, we, ws

        # How often do the rules elect the condorcet loser?
        #print "How often do rules elect the Condorcet Loser?"
        lp = 0
        lb = 0
        la = 0
        le = 0
        ls = 0
        for e,cand in conl_exists_elec:
            pl = plurality(e)
            bo = borda(e)
            ap = approval(e)
            ev = approval(e, 'even_and_equal')
            st = stv(e)
            if [cand] == pl.winner():
                lp += 1
            if [cand] == bo.winner():
                lb += 1
            if [cand] == ap.winner():
                la += 1
            if [cand] == ev.winner():
                le += 1
            if [cand] == st.winner():
                ls += 1
        pll.append(float(lp)/condorcet_losers)
        bol.append(float(lb)/condorcet_losers)
        apl.append(float(la)/condorcet_losers)
        evl.append(float(le)/condorcet_losers)
        stl.append(float(ls)/condorcet_losers)
        #print lp, lb, la, le, ls

    avg_cws = 0
    avg_cls = 0
    avgplw = 0
    avgbow = 0
    avgapw = 0
    avgevw = 0
    avgstw = 0
    avgpll = 0
    avgbol = 0
    avgapl = 0
    avgevl = 0
    avgstl = 0

    for i in range(0,NUM_EXPS):
        avg_cws += cws[i]
        avg_cls += cls[i]
        avgplw += plw[i]
        avgbow += bow[i]
        avgapw += apw[i]
        avgevw += evw[i]
        avgstw += stw[i]

        avgpll += pll[i]
        avgbol += bol[i]
        avgapl += apl[i]
        avgevl += evl[i]
        avgstl += stl[i]

    avg_cws = float(avg_cws)/(NUM_EXPS)
    sig_cws = sigma(avg_cws,cws)

    avg_cls = float(avg_cls)/(NUM_EXPS)
    sig_cls = sigma(avg_cls,cls)
    
    avgplw = float(avgplw)/NUM_EXPS
    sigplw = sigma(avgplw,plw)
    avgbow = float(avgbow)/NUM_EXPS
    sigbow = sigma(avgbow,bow)
    avgapw = float(avgapw)/NUM_EXPS
    sigapw = sigma(avgapw,apw)
    avgevw = float(avgevw)/NUM_EXPS
    sigevw = sigma(avgevw,evw)
    avgstw = float(avgstw)/NUM_EXPS
    sigstw = sigma(avgstw,stw)

    avgpll = float(avgpll)/NUM_EXPS
    sigpll = sigma(avgpll,pll)
    avgbol = float(avgbol)/NUM_EXPS
    sigbol = sigma(avgbol,bol)
    avgapl = float(avgapl)/NUM_EXPS
    sigapl = sigma(avgapl,apl)
    avgevl = float(avgevl)/NUM_EXPS
    sigevl = sigma(avgevl,evl)
    avgstl = float(avgstl)/NUM_EXPS
    sigstl = sigma(avgstl,stl)

    print "Number of candidates: %i" % NUM_CANDS
    print "Number of voters: %i" % NUM_VOTES
    print "Number of elections: %i" % (NUM_EXPS*NUM_ELECS)
    print
    print "Existence of Condorcet Winner: %f, %f" % (avg_cws*100, sig_cws*100)
    print "Existence of Condorcet Loser: %f, %f" % (avg_cls*100, sig_cls*100)
    print
    print "How often does a procedure elect the Condorcet winner:"
    print "Plurality: %f, %f" % (avgplw*100, sigplw*100)
    print "Borda Count: %f, %f" % (avgbow*100, sigbow*100)
    print "Approval: %f, %f" % (avgapw*100, sigapw*100)
    print "Even and equal: %f, %f" % (avgevw*100, sigevw*100)    
    print "STV: %f, %f" % (avgstw*100, sigstw*100)
    print
    print "How often does a procedure elect the Condorcet loser:"
    print "Plurality: %f, %f" % (avgpll*100, sigpll*100)
    print "Borda Count: %f, %f" % (avgbol*100, sigbol*100)
    print "Approval: %f, %f" % (avgapl*100, sigapl*100)
    print "Even and equal: %f, %f" % (avgevl*100, sigevl*100)    
    print "STV: %f, %f" % (avgstl*100, sigstl*100)
    print

