-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtally.py
More file actions
98 lines (83 loc) · 2.56 KB
/
Copy pathtally.py
File metadata and controls
98 lines (83 loc) · 2.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import argparse
import fractions
from collections import defaultdict, Counter
from itertools import chain
from tabulate import tabulate
def format_pos(position: int, primary_count: int) -> str:
if primary_count:
if position <= primary_count:
return f"#{position}"
return f"(#{position - primary_count})"
return f"#{position}"
def format_fraction(frac: fractions.Fraction) -> str:
return f"{frac.numerator}/{frac.denominator}"
def format_table_row(
pos: int,
name: str,
name_votes: list[fractions.Fraction],
extant_fractions: list[fractions.Fraction],
*,
primary_count: int,
):
score = sum(name_votes)
vote_ctr = Counter(name_votes)
return (
format_pos(pos, primary_count),
name,
float(score),
str(score),
*(vote_ctr[v] for v in extant_fractions),
)
def format_table(
votes: dict[str, list[fractions.Fraction]], primary_count: int
) -> None:
extant_fractions = sorted(set(chain(*votes.values())), reverse=True)
table = [
format_table_row(
pos,
name,
name_votes,
primary_count=primary_count,
extant_fractions=extant_fractions,
)
for pos, (name, name_votes) in enumerate(
sorted(votes.items(), key=lambda p: sum(p[1]), reverse=True),
1,
)
]
headers = (
"Position",
"Name",
"Total",
"Fraction",
*(f"Σ {format_fraction(f)}" for f in extant_fractions),
)
print(tabulate(table, headers=headers))
def main():
ap = argparse.ArgumentParser()
ap.add_argument("file")
ap.add_argument("-c", "--count", type=int, required=True)
ap.add_argument("-r", "--reverse", action="store_true", default=False)
args = ap.parse_args()
primary_count = args.count
if primary_count < 1:
raise ValueError("primary count must be >= 1")
votes = defaultdict(list)
with open(args.file) as infp:
for line in infp:
line = line.strip()
if not line:
continue
if line.startswith("#"):
continue
name, num = line.split(None, 1)
if args.reverse:
name, num = num, name
num = int(num)
if not (1 <= num <= primary_count):
raise ValueError(f"invalid line: {line}")
frac = fractions.Fraction(1, num)
votes[name.title()].append(frac)
format_table(votes, primary_count=primary_count)
if __name__ == "__main__":
main()