Merge branch 'master' of git.hjp.at:hjp/meeat
This commit is contained in:
commit
a147032c61
47
app.py
47
app.py
|
@ -173,7 +173,7 @@ def vote_date():
|
||||||
(session["user"]["id"], meet_id,))
|
(session["user"]["id"], meet_id,))
|
||||||
dates = csr.fetchall()
|
dates = csr.fetchall()
|
||||||
|
|
||||||
result = instantrunoff_forward(meet_id, "date")
|
result = instantrunoff_backward(meet_id, "date")
|
||||||
log.debug("result = %s", result)
|
log.debug("result = %s", result)
|
||||||
|
|
||||||
csr.execute(
|
csr.execute(
|
||||||
|
@ -194,7 +194,7 @@ def vote_date():
|
||||||
|
|
||||||
@app.get("/result/<int:meet_id>/date")
|
@app.get("/result/<int:meet_id>/date")
|
||||||
def result_date(meet_id):
|
def result_date(meet_id):
|
||||||
result = instantrunoff_forward(meet_id, "date")
|
result = instantrunoff_backward(meet_id, "date")
|
||||||
log.debug("result = %s", result)
|
log.debug("result = %s", result)
|
||||||
|
|
||||||
csr = get_cursor()
|
csr = get_cursor()
|
||||||
|
@ -251,7 +251,7 @@ def vote_time():
|
||||||
(session["user"]["id"], meet_id,))
|
(session["user"]["id"], meet_id,))
|
||||||
times = csr.fetchall()
|
times = csr.fetchall()
|
||||||
|
|
||||||
result = instantrunoff_forward(meet_id, "time")
|
result = instantrunoff_backward(meet_id, "time")
|
||||||
log.debug("result = %s", result)
|
log.debug("result = %s", result)
|
||||||
|
|
||||||
csr.execute(
|
csr.execute(
|
||||||
|
@ -272,7 +272,7 @@ def vote_time():
|
||||||
|
|
||||||
@app.get("/result/<int:meet_id>/time")
|
@app.get("/result/<int:meet_id>/time")
|
||||||
def result_time(meet_id):
|
def result_time(meet_id):
|
||||||
result = instantrunoff_forward(meet_id, "time")
|
result = instantrunoff_backward(meet_id, "time")
|
||||||
log.debug("result = %s", result)
|
log.debug("result = %s", result)
|
||||||
|
|
||||||
csr = get_cursor()
|
csr = get_cursor()
|
||||||
|
@ -327,7 +327,7 @@ def vote_place():
|
||||||
(session["user"]["id"], meet_id,))
|
(session["user"]["id"], meet_id,))
|
||||||
places = csr.fetchall()
|
places = csr.fetchall()
|
||||||
|
|
||||||
result = instantrunoff_forward(meet_id, "place")
|
result = instantrunoff_backward(meet_id, "place")
|
||||||
log.debug("result = %s", result)
|
log.debug("result = %s", result)
|
||||||
|
|
||||||
csr.execute(
|
csr.execute(
|
||||||
|
@ -349,7 +349,7 @@ def vote_place():
|
||||||
|
|
||||||
@app.get("/result/<int:meet_id>/place")
|
@app.get("/result/<int:meet_id>/place")
|
||||||
def result_place(meet_id):
|
def result_place(meet_id):
|
||||||
result = instantrunoff_forward(meet_id, "place")
|
result = instantrunoff_backward(meet_id, "place")
|
||||||
log.debug("result = %s", result)
|
log.debug("result = %s", result)
|
||||||
|
|
||||||
csr = get_cursor()
|
csr = get_cursor()
|
||||||
|
@ -373,7 +373,7 @@ def result_place(meet_id):
|
||||||
@app.get("/result/<int:meet_id>/date/ballot")
|
@app.get("/result/<int:meet_id>/date/ballot")
|
||||||
def result_ballots_date(meet_id):
|
def result_ballots_date(meet_id):
|
||||||
ballots = get_ballots(meet_id, "date")
|
ballots = get_ballots(meet_id, "date")
|
||||||
result = instantrunoff_forward(meet_id, "date")
|
result = instantrunoff_backward(meet_id, "date")
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
"date_result_ballots.html",
|
"date_result_ballots.html",
|
||||||
|
@ -382,7 +382,7 @@ def result_ballots_date(meet_id):
|
||||||
@app.get("/result/<int:meet_id>/time/ballot")
|
@app.get("/result/<int:meet_id>/time/ballot")
|
||||||
def result_ballots_time(meet_id):
|
def result_ballots_time(meet_id):
|
||||||
ballots = get_ballots(meet_id, "time")
|
ballots = get_ballots(meet_id, "time")
|
||||||
result = instantrunoff_forward(meet_id, "time")
|
result = instantrunoff_backward(meet_id, "time")
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
"time_result_ballots.html",
|
"time_result_ballots.html",
|
||||||
|
@ -391,7 +391,7 @@ def result_ballots_time(meet_id):
|
||||||
@app.get("/result/<int:meet_id>/place/ballot")
|
@app.get("/result/<int:meet_id>/place/ballot")
|
||||||
def result_ballots_place(meet_id):
|
def result_ballots_place(meet_id):
|
||||||
ballots = get_ballots(meet_id, "place")
|
ballots = get_ballots(meet_id, "place")
|
||||||
result = instantrunoff_forward(meet_id, "place")
|
result = instantrunoff_backward(meet_id, "place")
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
"place_result_ballots.html",
|
"place_result_ballots.html",
|
||||||
|
@ -412,7 +412,8 @@ def get_ballots(meet_id, kind):
|
||||||
csr = get_cursor()
|
csr = get_cursor()
|
||||||
|
|
||||||
q = f"""
|
q = f"""
|
||||||
select {kind}.*, bod, position, email
|
select {kind}.*, bod, position, email,
|
||||||
|
min(w) over(partition by bod order by position) as vote_w
|
||||||
from {kind}
|
from {kind}
|
||||||
join {kind}_vote on {kind}.id = {kind}_vote.{kind}
|
join {kind}_vote on {kind}.id = {kind}_vote.{kind}
|
||||||
join bod on bod = bod.id
|
join bod on bod = bod.id
|
||||||
|
@ -437,7 +438,7 @@ def dump_ballots(ballots):
|
||||||
for r in ballot:
|
for r in ballot:
|
||||||
log.debug(r)
|
log.debug(r)
|
||||||
|
|
||||||
def runoff(ballots):
|
def runoff(ballots, direction):
|
||||||
count = {}
|
count = {}
|
||||||
candidates = {}
|
candidates = {}
|
||||||
for ballot in ballots:
|
for ballot in ballots:
|
||||||
|
@ -447,13 +448,17 @@ def runoff(ballots):
|
||||||
count[r.id] = [0] * len(ballot)
|
count[r.id] = [0] * len(ballot)
|
||||||
candidates[r.id] = r
|
candidates[r.id] = r
|
||||||
for ballot in ballots:
|
for ballot in ballots:
|
||||||
|
weight = max(r.vote_w for r in ballot)
|
||||||
for pos, r in enumerate(ballot):
|
for pos, r in enumerate(ballot):
|
||||||
log.debug("count = %s", count)
|
log.debug("count = %s", count)
|
||||||
log.debug("r.id = %s", r.id)
|
log.debug("r.id = %s", r.id)
|
||||||
log.debug("pos = %s", pos)
|
log.debug("pos = %s", pos)
|
||||||
count[r.id][pos] += 1
|
count[r.id][pos] += weight
|
||||||
log.debug("count[%d][%d]) = %d", r.id, pos, count[r.id][pos])
|
log.debug("count[%d][%d]) = %d", r.id, pos, count[r.id][pos])
|
||||||
result = sorted(count.keys(), key=lambda i: count[i])
|
if direction == "backward":
|
||||||
|
result = sorted(count.keys(), key=lambda i: list(reversed(count[i])), reverse=True)
|
||||||
|
else:
|
||||||
|
result = sorted(count.keys(), key=lambda i: count[i])
|
||||||
log.debug("result of this round:")
|
log.debug("result of this round:")
|
||||||
for r in result:
|
for r in result:
|
||||||
log.debug("%s %s", r, count[r])
|
log.debug("%s %s", r, count[r])
|
||||||
|
@ -472,7 +477,21 @@ def instantrunoff_forward(meet_id, kind):
|
||||||
result = []
|
result = []
|
||||||
while max(len(b) for b in ballots):
|
while max(len(b) for b in ballots):
|
||||||
dump_ballots(ballots)
|
dump_ballots(ballots)
|
||||||
loser, ballots = runoff(ballots)
|
loser, ballots = runoff(ballots, "forward")
|
||||||
|
result.append(loser)
|
||||||
|
result = list(reversed(result))
|
||||||
|
log.debug("final result")
|
||||||
|
for r in result:
|
||||||
|
log.debug(r)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def instantrunoff_backward(meet_id, kind):
|
||||||
|
ballots = get_ballots(meet_id, kind)
|
||||||
|
|
||||||
|
result = []
|
||||||
|
while max(len(b) for b in ballots):
|
||||||
|
dump_ballots(ballots)
|
||||||
|
loser, ballots = runoff(ballots, "backward")
|
||||||
result.append(loser)
|
result.append(loser)
|
||||||
result = list(reversed(result))
|
result = list(reversed(result))
|
||||||
log.debug("final result")
|
log.debug("final result")
|
||||||
|
|
|
@ -7,6 +7,7 @@ import psycopg.rows
|
||||||
|
|
||||||
def get_args():
|
def get_args():
|
||||||
ap = argparse.ArgumentParser()
|
ap = argparse.ArgumentParser()
|
||||||
|
ap.add_argument("--reverse", action="store_true")
|
||||||
ap.add_argument("meet", type=int)
|
ap.add_argument("meet", type=int)
|
||||||
ap.add_argument("kind")
|
ap.add_argument("kind")
|
||||||
|
|
||||||
|
@ -20,7 +21,8 @@ def get_ballots():
|
||||||
|
|
||||||
kind = args.kind
|
kind = args.kind
|
||||||
q = f"""
|
q = f"""
|
||||||
select {kind}.*, bod, position
|
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}
|
from {kind} join {kind}_vote on {kind}.id = {kind}_vote.{kind}
|
||||||
where meet = %s
|
where meet = %s
|
||||||
order by bod, position
|
order by bod, position
|
||||||
|
@ -53,9 +55,13 @@ def runoff_forward(ballots):
|
||||||
count[r.id] = [0] * len(ballot)
|
count[r.id] = [0] * len(ballot)
|
||||||
candidates[r.id] = r
|
candidates[r.id] = r
|
||||||
for ballot in ballots:
|
for ballot in ballots:
|
||||||
|
weight = max(r.vote_w for r in ballot)
|
||||||
for pos, r in enumerate(ballot):
|
for pos, r in enumerate(ballot):
|
||||||
count[r.id][pos] += 1
|
count[r.id][pos] += weight
|
||||||
result = sorted(count.keys(), key=lambda i: count[i])
|
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:")
|
print("result of this round:")
|
||||||
for r in result:
|
for r in result:
|
||||||
print(r, count[r])
|
print(r, count[r])
|
||||||
|
|
Loading…
Reference in New Issue