import random


def generate_vote(candidate_chances):
    """
    returns a list of vote choices, votes are picked based on each candidate's chances of being voted for.
    [(1, 'candidate_id'), (2, 'candidate_id'), (2, 'candidate_id'), ...]
    Votes are generated by determining how many candidates a voter wants to pick.
    At least one pass is made through the candidate_chance list (possibly picking more candidates than chosen but never
    more than are available)
    for each candidate, it is randomly determined if they will be picked that round. Every candidate picked in
    each round will have the same rank number.

    For example; candidate chances are:
    [(0.3103760707038792, 1), (0.3368433989455909, 0), (0.40308497270067967, 4), (0.6070980766930767, 2), (0.7710239099894114, 3)]
    Voter is determined to pick 3 candidates.
    In the first round each candidate is checked
    0.3103760707038792 rolls 0.1 and is picked at rank 1 (first round) - 2 remaining picks
    0.3368433989455909 rolls 0.9 and is not picked
    0.40308497270067967 rolls 0.3 and is picked at rank 1 - 1 remaining pick
    0.6070980766930767 rolls a 0.5 and is picked at rank 1 - 0 remaining picks but not all candidates have been checked
    0.7710239099894114 rolls a 0.6 and is picked at rank 1
    Vote returned is [(1, 1), (1, 4), (1, 2), (1,3)]
    """
    # vote for at least 1
    nr_to_vote_for = random.randint(1, len(candidate_chances))
    votes = []

    rank = 1
    while nr_to_vote_for > 0:
        for c in candidate_chances:
            if random.random() < c[0]:
                votes.append((rank, c[1]))
                nr_to_vote_for -= 1
            if rank > 1 and nr_to_vote_for == 0:
                break
        rank += 1
    return votes