#!/usr/bin/python3 import argparse import psycopg import psycopg.rows def get_args(): ap = argparse.ArgumentParser() ap.add_argument("--reverse", action="store_true") ap.add_argument("meet", type=int) ap.add_argument("kind") args = ap.parse_args() return args def get_ballots(): db = psycopg.connect(dbname="meeat", user="www-meeat") csr = db.cursor(row_factory=psycopg.rows.namedtuple_row) kind = args.kind q = f""" select {kind}.*, bod, position, min(w) over(partition by bod order by position) as vote_w from {kind} join {kind}_vote on {kind}.id = {kind}_vote.{kind} where meet = %s order by bod, position """ csr.execute(q, (args.meet,)) last_bod = None ballots = [] for r in csr: if r.bod != last_bod: ballot = [] ballots.append(ballot) last_bod = r.bod ballot.append(r) return ballots def dump_ballots(ballots): for ballot in ballots: print ("---") for r in ballot: print(r) def runoff_forward(ballots): count = {} candidates = {} for ballot in ballots: for r in ballot: if r.id not in count or len(count[r.id]) < len(ballot): log.debug("count[%d] <- %d elements", r.id, len(ballot)) count[r.id] = [0] * len(ballot) candidates[r.id] = r for ballot in ballots: weight = max(r.vote_w for r in ballot) for pos, r in enumerate(ballot): count[r.id][pos] += weight if args.reverse: result = sorted(count.keys(), key=lambda i: list(reversed(count[i])), reverse=True) else: result = sorted(count.keys(), key=lambda i: count[i]) print("result of this round:") for r in result: print(r, count[r]) print("striking", result[0]) loser = candidates[result[0]] new_ballots = [ [ r for r in ballot if r.id != loser.id ] for ballot in ballots ] return loser, new_ballots der runoff_backward(ballot): for ballot in ballots: for r in ballot: if r.id not in count or len(count[r.id]) < len(ballot): log.debug("count[%d] <- %d elements", r.id, len(ballot)) count[r.id] = [0] * len(ballot) candidates[r.id] = r pprint(candidates) for ballot in ballots: for pos, r in enumerate(ballot): count[r.id][pos] += 1 pprint(count) return loser, new_ballots if __name__ == "__main__": args = get_args() ballots = get_ballots() result = [] while max(len(b) for b in ballots): dump_ballots(ballots) loser, ballots = runoff_forward(ballots) result.append(loser) result = reversed(result) print("final result") for r in result: print(r)