def tallyCOP()

in pysteve/lib/plugins/cop.py [0:0]


def tallyCOP(votes, issue):
    m = re.match(r"cop(\d+)", issue['type'])
    if not m:
        raise Exception("Not a COP vote!")
    
    numseats = int(m.group(1))
    parties = {}

    for c in issue['candidates']:
        if not c['pletter'] in parties:
            parties[c['pletter']] = {
                'name': c['pname'],
                'letter': c['pletter'],
                'surplus': 0,
                'candidates': []
            }
        parties[c['pletter']]['candidates'].append({
            'letter': c['letter'],
            'name': c['name'],
            'votes': 0,
            'elected': False
            })
    

    debug = []
    winners = []
    
        
    # Tally up all scores and surplus
    for key in votes:
        vote = votes[key]
        
        for party in parties:
            if parties[party]['letter'] == vote:
                parties[party]['surplus'] += 1
            else:
                for candidate in parties[party]['candidates']:
                    if candidate['letter'] == vote:
                        candidate['votes'] += 1
                
        
    numvotes = len(votes)
    
    if numseats < len(issue['candidates']):
        
        # Start by assigning all surplus (party votes) to the first listed candidate
        iterations = 0
        
        while numseats > len(winners) and iterations < 9999: # Catch forever-looping counts (in case of bug)
            quota = (numvotes / numseats * 1.0) # Make it a float to prevent from rounding down for now
            for party in parties:
                surplus = 0
                movedOn = False
                for candidate in parties[party]['candidates']:
                    # If a candidate has not yet been elected, and has >= votes than the required quota, elect her/him
                    if not candidate['elected'] and numseats > len(winners):
                        if candidate['votes'] >= quota:
                            candidate['elected'] = True
                            winners.append("%s (%s) %u" % ( candidate['name'], parties[party]['name'], candidate['votes']))
                            
                            # Did X receive more votes than needed? if so, add back to the party surplus
                            surplus += candidate['votes'] - quota
                    
                # If surplus of votes, add it to the next candidate in the same party
                if surplus > 0:
                    for candidate in parties[party]['candidates']:
                        if not candidate['elected']:
                            candidate['votes'] += surplus
                            movedOn = True
                            break
                        
                # If surplus but no candidates left, decrease the number of votes required by the surplus
                if not movedOn:
                    numvotes -= surplus
            
    # Everyone's a winner!!
    else:
        for party in parties:
            for candidate in parties[party]['candidates']:
                winners.append("%s (%s) %u" % ( candidate['name'], parties[party]['name'], candidate['votes']))
        

   
    # Return the data
    return {
        'votes': len(votes),
        'winners': winners,
        'winnernames': winners,
        'debug': debug
    }, """
Winners:
 - %s
""" % "\n - ".join(winners)