<commit_before>from __future__ import unicode_literals, division
import random
import copy
import uuid
import sys
import codecs
import os
import tempfile
from operator import itemgetter

from .base import BaseVotingSystem, BaseTally, BlankVoteException



class PairwiseBeta(BaseVotingSystem):
    '''
    Defines the helper functions that allows agora to manage an pairwise-beta election
    '''

    @staticmethod
    def get_id():
        '''
        Returns the identifier of the voting system, used internally to
        discriminate  the voting system used in an election
        '''
        return 'pairwise-beta'

    @staticmethod
    def get_description():
        return _('Pairwise Beta Binomial model')

    @staticmethod
    def create_tally(election, question_num):
        '''
        Create object that helps to compute the tally
        '''
        return PairwiseBetaTally(election, question_num)

class PairwiseBetaTally(BaseTally):
    '''
    Class used to tally an election
    '''
    ballots_file = None
    ballots_path = ""

    # list containing the current list of ballots.
    # In each iteration this list is modified. For efficiency, ballots with the
    # same ordered choices are grouped. The format of each item in this list is
    # the following:
    #
    #{
        #'votes': 12, # number of ballots with this selection of choices
        #'answers': [2, 1, 4] # list of ids of the choices
    #}
    ballots = []

    num_winners = -1

    # report object
    report = None

    def init(self):
        self.ballots = []

    def parse_vote(self, number, question):
        vote_str = str(number)
        tab_size = len(str(len(question['answers']) + 2))

        # fix add zeros
        if len(vote_str) % tab_size != 0:
            num_zeros = (tab_size - (len(vote_str) % tab_size)) % tab_size
            vote_str = "0" * num_zeros + vote_str

        ret = []
        for i in range(int(len(vote_str) / tab_size)):
            option = int(vote_str[i*tab_size: (i+1)*tab_size]) - 1

            # blank vote
            if option == len(question['answers']) + 1:
                raise BlankVoteException()
            # invalid vote
            elif option < 0 or option >= len(question['answers']):
                raise Exception()
            ret.append(option)

        if len(ret) % 2 != 0:
            raise Exception()

        comparisons = len(ret) / 2

        # detect invalid vote
        if comparisons < question['min']:
            raise Exception()

        if comparisons > question['max']:
            if "truncate-max-overload" in question and question["truncate-max-overload"]:
                ret = ret[:question['max'] * 2]
            else:
                raise Exception()

        return ret

    def pre_tally(self, questions):
        '''
        Function called once before the tally begins
        '''


    def find_ballot(self, answers):
        '''
        Find a ballot with the same answers as the one given in self.ballots.
        Returns the ballot or None if not found.
        '''
        for ballot in self.ballots:
            if ballot['answers'] == answers:
                return ballot

        return None

    def add_vote(self, voter_answers, questions, is_delegated):
        '''
        Add to the count a vote from a voter
        '''
        answers = [choice+1 for choice in voter_answers[self.question_num]['choices']]
        # we got ourselves an invalid vote, don't count it
        if -1 in answers:
            return

        if len(answers) > 0:
            ballot = self.find_ballot(answers)
            # if ballot found, increment the count. Else, create a ballot and add it
            if ballot:
                ballot['votes'] += 1
            else:
                self.ballots.append(dict(votes=1, answers=answers))


    def perform_tally(self, questions):
        '''
        Runs the beta calculation
        '''

        self.report = {}
        report = self.report
        report['valid_votes'] = 0
        report['answers'] = {}

        # first collect wins and losses for each option
        for ballot in self.ballots:
            if len(ballot['answers']) % 2 == 0:<commit_msg>Fix for off by one in 0-based answers index<commit_after>from __future__ import unicode_literals, division
import random
import copy
import uuid
import sys
import codecs
import os
import tempfile
from operator import itemgetter

from .base import BaseVotingSystem, BaseTally, BlankVoteException



class PairwiseBeta(BaseVotingSystem):
    '''
    Defines the helper functions that allows agora to manage an pairwise-beta election
    '''

    @staticmethod
    def get_id():
        '''
        Returns the identifier of the voting system, used internally to
        discriminate  the voting system used in an election
        '''
        return 'pairwise-beta'

    @staticmethod
    def get_description():
        return _('Pairwise Beta Binomial model')

    @staticmethod
    def create_tally(election, question_num):
        '''
        Create object that helps to compute the tally
        '''
        return PairwiseBetaTally(election, question_num)

class PairwiseBetaTally(BaseTally):
    '''
    Class used to tally an election
    '''
    ballots_file = None
    ballots_path = ""

    # list containing the current list of ballots.
    # In each iteration this list is modified. For efficiency, ballots with the
    # same ordered choices are grouped. The format of each item in this list is
    # the following:
    #
    #{
        #'votes': 12, # number of ballots with this selection of choices
        #'answers': [2, 1, 4] # list of ids of the choices
    #}
    ballots = []

    num_winners = -1

    # report object
    report = None

    def init(self):
        self.ballots = []

    def parse_vote(self, number, question):
        vote_str = str(number)
        tab_size = len(str(len(question['answers']) + 2))

        # fix add zeros
        if len(vote_str) % tab_size != 0:
            num_zeros = (tab_size - (len(vote_str) % tab_size)) % tab_size
            vote_str = "0" * num_zeros + vote_str

        ret = []
        for i in range(int(len(vote_str) / tab_size)):
            option = int(vote_str[i*tab_size: (i+1)*tab_size]) - 1

            # blank vote
            if option == len(question['answers']) + 1:
                raise BlankVoteException()
            # invalid vote
            elif option < 0 or option >= len(question['answers']):
                raise Exception()
            ret.append(option)

        if len(ret) % 2 != 0:
            raise Exception()

        comparisons = len(ret) / 2

        # detect invalid vote
        if comparisons < question['min']:
            raise Exception()

        if comparisons > question['max']:
            if "truncate-max-overload" in question and question["truncate-max-overload"]:
                ret = ret[:question['max'] * 2]
            else:
                raise Exception()

        return ret

    def pre_tally(self, questions):
        '''
        Function called once before the tally begins
        '''


    def find_ballot(self, answers):
        '''
        Find a ballot with the same answers as the one given in self.ballots.
        Returns the ballot or None if not found.
        '''
        for ballot in self.ballots:
            if ballot['answers'] == answers:
                return ballot

        return None

    def add_vote(self, voter_answers, questions, is_delegated):
        '''
        Add to the count a vote from a voter
        '''
        answers = [choice for choice in voter_answers[self.question_num]['choices']]
        # we got ourselves an invalid vote, don't count it
        if -1 in answers:
            return

        if len(answers) > 0:
            ballot = self.find_ballot(answers)
            # if ballot found, increment the count. Else, create a ballot and add it
            if ballot:
                ballot['votes'] += 1
            else:
                self.ballots.append(dict(votes=1, answers=answers))


    def perform_tally(self, questions):
        '''
        Runs the beta calculation
        '''

        self.report = {}
        report = self.report
        report['valid_votes'] = 0
        report['answers'] = {}

        # first collect wins and losses for each option
        for ballot in self.ballots:
            if len(ballot['answers']) % 2 == 0:
{'fraction_non_alphanumeric': 0.09082285985297604, 'fraction_numerical': 0.005928385107896609, 'mean_word_length': 2.0125, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '122151', 'n_tokens_mistral': 2468, 'n_tokens_neox': 2272, 'n_words': 779}