Test instant runoff algorithm
This commit is contained in:
parent
65a19eb756
commit
049a8d0d70
|
@ -0,0 +1,82 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
import argparse
|
||||
|
||||
import psycopg
|
||||
import psycopg.rows
|
||||
|
||||
def get_args():
|
||||
ap = argparse.ArgumentParser()
|
||||
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
|
||||
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(ballots):
|
||||
count = {}
|
||||
candidates = {}
|
||||
for ballot in ballots:
|
||||
for r in ballot:
|
||||
count[r.id] = 0
|
||||
candidates[r.id] = r
|
||||
for ballot in ballots:
|
||||
# The votes are sorted by position, so the first entry is the favourite
|
||||
count[ballot[0].id] += 1
|
||||
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
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = get_args()
|
||||
|
||||
ballots = get_ballots()
|
||||
|
||||
result = []
|
||||
while max(len(b) for b in ballots):
|
||||
dump_ballots(ballots)
|
||||
loser, ballots = runoff(ballots)
|
||||
result.append(loser)
|
||||
result = reversed(result)
|
||||
print("final result")
|
||||
for r in result:
|
||||
print(r)
|
Loading…
Reference in New Issue