Subversion Repositories Local Hare Voting

Rev

Rev 77 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
75 jtkorb 1
#!/usr/bin/env python
15 jtkorb 2
 
39 jtkorb 3
import optparse
5 jtkorb 4
import cgi
5
import string
6
import sys
7
 
15 jtkorb 8
import parseinput
9
import tally
7 jtkorb 10
 
15 jtkorb 11
fHTML = 1
5 jtkorb 12
formaction = string.split(sys.argv[0],"/")[-1]
13
 
14
def emitPreHTML(formaction):
15
    emitHTML("""Content-type: text/html\n
16
<html>
17
<body>
18
<title>Hare Ballot Calculation</title>
19
    <h1>Hare Ballot Calculation</h1>
20
    <form enctype="multipart/form-data" method=POST action=%s>
21
        <table>
22
        <tr><td>CSV file of ballots:
23
                <td><input type=file size=70 name=name>
24
        </table>
25
        <p>
26
        <input type=submit name="run1" value="Run 1 Time">
75 jtkorb 27
        <!-- <input type=submit name="run500" value="Run 500 Times"> -->
78 jtkorb 28
        <input type=submit name="runparallel" value="Run All Ways">
5 jtkorb 29
    </form>
30
    <p>
75 jtkorb 31
Input is a CSV/spreadsheet file with the number of winners to be
32
selected in the first cell.  On subsequent lines, the first column contains the names of the candidates (no blanks), with each additional column representing a ballot.  Details are given 
77 jtkorb 33
<a href="http://www.bikmort.com/dokuwiki/hare_voting_procedure">here</a>.
75 jtkorb 34
Little error checking is done, so be sure to review the trace output.
5 jtkorb 35
The source code is available <a href="%s?fetch=yes">here</a>.
36
<p>
37
<small>%s</small>
38
<hr>
39
<pre>
75 jtkorb 40
""" % (formaction, formaction, "$Id: vote.py 78 2016-05-11 19:18:03Z jtkorb $"))
5 jtkorb 41
    return
42
 
43
def emitPostHTML():
44
    emitHTML("""</pre>
45
</body>
46
</html>
47
""")
48
    return
49
 
50
def emitHTML(s):
51
    global fHTML
52
    if fHTML: print s
53
    return
54
 
38 jtkorb 55
def doone(nWinners, ballots):
75 jtkorb 56
    tally.traceLevel = 1
57
    tally.fParallel = 0
38 jtkorb 58
    results = tally.dotally(nWinners, ballots)
59
 
39 jtkorb 60
def domany(nTimes, nWinners, ballots):
75 jtkorb 61
    tally.traceLevel = 0
62
    tally.fParallel = 0
39 jtkorb 63
    summary = {}
64
    for i in range(nTimes):
65
        results = str(tally.dotally(nWinners, ballots))
66
        if not summary.has_key(results):
67
            summary[results] = 0
68
        summary[results] = summary[results] + 1
75 jtkorb 69
    tally.trace(0, "\nSUMMARY AFTER %d TIMES" % nTimes)
39 jtkorb 70
    l = summary.items()
71
    l.sort(lambda x,y: cmp(y[1], x[1]))
72
    for pair in l:
75 jtkorb 73
        tally.trace(0, "%3d %s" % (pair[1], pair[0]))
39 jtkorb 74
 
75 jtkorb 75
def doparallel(nWinners, ballots):
76
    tally.traceLevel = 0
77
    tally.fParallel = 1
78
    results = tally.dotally(nWinners, ballots)
79
 
39 jtkorb 80
def doweb():
5 jtkorb 81
    emitPreHTML(formaction)
82
    form = cgi.FieldStorage()
83
 
84
    if not form:
85
        emitHTML("Enter file name and press a button to see results.")
86
    elif form.has_key("fetch"):
21 jtkorb 87
        filename = string.replace(formaction, "vote.py", "tally.py")
88
        source = open(filename).read()
89
        print cgi.escape(source)
5 jtkorb 90
    elif not form.has_key("name"):
91
        emitHTML("Error: no file received")
92
    elif not form["name"].filename:
93
        emitHTML("Error: file name missing")
94
    else:
95
        name = form["name"].filename
96
        contents = form["name"].value
97
 
75 jtkorb 98
        tally.trace(0, "INPUT FILE")
99
        tally.trace(0, contents)
5 jtkorb 100
 
15 jtkorb 101
        nWinners, ballots = parseinput.parsestring(contents)
21 jtkorb 102
        if form.has_key("run1"):
38 jtkorb 103
            doone(nWinners, ballots)
21 jtkorb 104
        elif form.has_key("run1000"):
39 jtkorb 105
            domany(1000, nWinners, ballots)
75 jtkorb 106
        elif form.has_key("runparallel"):
107
            doparallel(nWinners, ballots)
21 jtkorb 108
        else:
109
            print "UNEXPECTED SUBMIT BUTTON: %s" % form
110
 
5 jtkorb 111
    emitPostHTML()
112
    return
113
 
39 jtkorb 114
def main():
115
    usage = "usage: %prog [options] filename.csv"
116
    parser = optparse.OptionParser(usage)
75 jtkorb 117
    parser.add_option("-m", "--multiple", dest="multi", action="store_true",
39 jtkorb 118
                      help="run process multiple (1000) times")
75 jtkorb 119
    parser.add_option("-p", "--parallel", dest="para", action="store_true",
120
                      help="run process in parallel universes")
39 jtkorb 121
    (options, args) = parser.parse_args()
122
 
123
    if len(args) == 0:
124
        doweb()
38 jtkorb 125
    else:
39 jtkorb 126
        nWinners, ballots = parseinput.parsefile(args[0])
127
        if options.multi:
128
            domany(1000, nWinners, ballots)
75 jtkorb 129
        elif options.para:
130
            doparallel(nWinners, ballots)
39 jtkorb 131
        else:
132
            doone(nWinners, ballots)
38 jtkorb 133
 
15 jtkorb 134
if __name__=='__main__':
39 jtkorb 135
    main()