Revision 79948f90

b/stv.py
61 61
    decreasing order of preference) and an ordered list of weights
62 62
    (new weights are added to the front of the list). The index of the
63 63
    current preference (for the first count and subsequent rounds)
64
    is kept in an index.
64
    is also kept.
65 65

  
66 66
    """
67 67

  
68 68
    candidates = []
69 69
    weights = [1.0]
70
    index = 0
70
    current_preference = 0
71 71
    _value = 1.0
72 72

  
73 73
    def __init__(self, candidates=[]):
......
135 135

  
136 136
    logger = logging.getLogger(SVT_LOGGER)
137 137
    transferred = []
138
    # Keep a hash of ballot moves for logging purposes.
139
    # The hash comprises 
138 140
    moves = {}
139 141

  
140 142
    for ballot in allocated[selected]:
141 143
        reallocated = False
142
        i = ballot.index + 1
144
        i = ballot.current_preference + 1
143 145
        while not reallocated and i < len(ballot.candidates):
144 146
            recipient = ballot.candidates[i]
145 147
            if recipient in hopefuls:
146
                ballot.index = i
148
                ballot.current_preference = i
147 149
                ballot.add_weight(weight)
150
                current_value = ballot.get_value()
148 151
                if recipient in allocated:
149 152
                    allocated[recipient].append(ballot)
150 153
                else:
151 154
                    allocated[recipient] = [ballot]
152 155
                if recipient in vote_count:
153
                    vote_count[recipient] += (1 * weight)
156
                    vote_count[recipient] += current_value
154 157
                else:
155
                    vote_count[recipient] = 1 * weight
158
                    vote_count[recipient] = current_value
159
                vote_count[selected] -= current_value
156 160
                reallocated = True
157
                if (selected, recipient) in moves:
158
                    moves[(selected, recipient)] += 1
161
                if (selected, recipient, current_value) in moves:
162
                    moves[(selected, recipient, current_value)] += 1
159 163
                else:
160
                    moves[(selected, recipient)] = 1
164
                    moves[(selected, recipient, current_value)] = 1
161 165
                transferred.append(ballot)
162 166
            else:
163 167
                i += 1
164 168
    for move, times in moves.iteritems():
165
        description =  "from {0} to {1} {2}*{3}={4}".format(move[0], move[1],
169
        description =  "from {0} to {1} {2}*{3}={4}".format(move[0],
170
                                                            move[1],
166 171
                                                            times,
167
                                                            weight,
168
                                                            times*weight)
172
                                                            move[2],
173
                                                            times*move[2])
169 174
        logger.info(LOG_MESSAGE.format(action=Action.TRANSFER,
170 175
                                       desc=description))
171 176
    allocated[selected][:] = [x for x in allocated[selected]
172 177
                              if x not in transferred ]
173
    vote_count[selected] -= (len(transferred) * weight)
174 178
    
175 179
def count_stv(ballots, seats, rnd_gen=None):
176 180
    """Performs a SVT vote for the given ballots and number of seats.
......
185 189

  
186 190
    seed()
187 191

  
188
    threshold = int(math.ceil(1 + len(ballots) / (seats + 1)))
192
    threshold = (1 + len(ballots) / (seats + 1))
189 193

  
190 194
    logger = logging.getLogger(SVT_LOGGER)
191 195
    logger.info(LOG_MESSAGE.format(action=Action.THRESHOLD,
......
267 271
    parser = argparse.ArgumentParser(description='Perform STV')
268 272
    parser.add_argument('--ballots', nargs='?', default='sys.stdin',
269 273
                        dest='ballots_file', help='input ballots file')
274
    parser.add_argument('--seats', nargs='?', default=0,
275
                        dest='seats', help='number of seats')
270 276
    args = parser.parse_args()
271 277
    ballots = []
272 278
    ballots_file = sys.stdin
......
278 284
    for ballot in ballots_reader:
279 285
        ballots.append(Ballot(ballot))
280 286

  
281
    (elected, vote_count) = count_stv(ballots, 5)
287
    if args.seats == 0:
288
        args.seats = len(ballots) / 2
289
    (elected, vote_count) = count_stv(ballots, int(args.seats))
282 290

  
283 291
    print "Results:"
284 292
    for candidate in elected:

Also available in: Unified diff