Subversion Repositories Remote Hare Voting

Rev

Rev 45 | Rev 77 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 45 Rev 75
Line 1... Line 1...
1
#!/p/python-2.5.1/bin/python
1
#!/usr/bin/env python
2
 
2
 
3
import optparse
3
import optparse
4
import cgi
4
import cgi
5
import string
5
import string
6
import sys
6
import sys
7
 
7
 
8
import revision
-
 
9
import parseinput
8
import parseinput
10
import tally
9
import tally
11
 
10
 
12
fHTML = 1
11
fHTML = 1
13
formaction = string.split(sys.argv[0],"/")[-1]
12
formaction = string.split(sys.argv[0],"/")[-1]
Line 23... Line 22...
23
        <tr><td>CSV file of ballots:
22
        <tr><td>CSV file of ballots:
24
                <td><input type=file size=70 name=name>
23
                <td><input type=file size=70 name=name>
25
        </table>
24
        </table>
26
        <p>
25
        <p>
27
        <input type=submit name="run1" value="Run 1 Time">
26
        <input type=submit name="run1" value="Run 1 Time">
28
        <input type=submit name="run1000" value="Run 1000 Times">
27
        <!-- <input type=submit name="run500" value="Run 500 Times"> -->
-
 
28
	<input type=submit name="runparallel" value="Run All Ways">
29
    </form>
29
    </form>
30
    <p>
30
    <p>
31
Input file format is given
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 
32
<a href="http://www.bikmort.com/wiki/index.php?title=Hare_Voting_Procedure">here</a>.
33
<a href="http://www.bikmort.com/dokuwiki/doku.php/hare_voting_procedure">here</a>.
33
Almost no error checking is done, so be sure to review the trace output.
34
Little error checking is done, so be sure to review the trace output.
34
The source code is available <a href="%s?fetch=yes">here</a>.
35
The source code is available <a href="%s?fetch=yes">here</a>.
35
<p>
36
<p>
36
<small>%s</small>
37
<small>%s</small>
37
<hr>
38
<hr>
38
<pre>
39
<pre>
39
""" % (formaction, formaction, revision.revision))
40
""" % (formaction, formaction, "$Id: vote.py 75 2009-01-08 23:29:13Z jtkorb $"))
40
    return
41
    return
41
 
42
 
42
def emitPostHTML():
43
def emitPostHTML():
43
    emitHTML("""</pre>
44
    emitHTML("""</pre>
44
</body>
45
</body>
Line 50... Line 51...
50
    global fHTML
51
    global fHTML
51
    if fHTML: print s
52
    if fHTML: print s
52
    return
53
    return
53
 
54
 
54
def doone(nWinners, ballots):
55
def doone(nWinners, ballots):
-
 
56
    tally.traceLevel = 1
-
 
57
    tally.fParallel = 0
55
    results = tally.dotally(nWinners, ballots)
58
    results = tally.dotally(nWinners, ballots)
56
    tally.fTrace = 1
-
 
57
    tally.trace("\nFINAL RESULTS")
-
 
58
    for winner in results:
-
 
59
        tally.trace("\t%s" % winner)
-
 
60
 
59
 
61
def domany(nTimes, nWinners, ballots):
60
def domany(nTimes, nWinners, ballots):
-
 
61
    tally.traceLevel = 0
62
    tally.fTrace = 0
62
    tally.fParallel = 0
63
    summary = {}
63
    summary = {}
64
    for i in range(nTimes):
64
    for i in range(nTimes):
65
        results = str(tally.dotally(nWinners, ballots))
65
        results = str(tally.dotally(nWinners, ballots))
66
        if not summary.has_key(results):
66
        if not summary.has_key(results):
67
            summary[results] = 0
67
            summary[results] = 0
68
        summary[results] = summary[results] + 1
68
        summary[results] = summary[results] + 1
69
    tally.fTrace = 1
-
 
70
    tally.trace("SUMMARY AFTER %d TIMES" % nTimes)
69
    tally.trace(0, "\nSUMMARY AFTER %d TIMES" % nTimes)
71
    l = summary.items()
70
    l = summary.items()
72
    l.sort(lambda x,y: cmp(y[1], x[1]))
71
    l.sort(lambda x,y: cmp(y[1], x[1]))
73
    for pair in l:
72
    for pair in l:
74
        tally.trace("%3d %s" % (pair[1], pair[0]))
73
        tally.trace(0, "%3d %s" % (pair[1], pair[0]))
-
 
74
 
-
 
75
def doparallel(nWinners, ballots):
-
 
76
    tally.traceLevel = 0
-
 
77
    tally.fParallel = 1
-
 
78
    results = tally.dotally(nWinners, ballots)
75
 
79
 
76
def doweb():
80
def doweb():
77
    emitPreHTML(formaction)
81
    emitPreHTML(formaction)
78
    form = cgi.FieldStorage()
82
    form = cgi.FieldStorage()
79
 
83
 
Line 89... Line 93...
89
        emitHTML("Error: file name missing")
93
        emitHTML("Error: file name missing")
90
    else:
94
    else:
91
        name = form["name"].filename
95
        name = form["name"].filename
92
        contents = form["name"].value
96
        contents = form["name"].value
93
 
97
 
94
        tally.trace("INPUT FILE")
98
        tally.trace(0, "INPUT FILE")
95
        tally.trace(contents)
99
        tally.trace(0, contents)
96
 
100
 
97
        nWinners, ballots = parseinput.parsestring(contents)
101
        nWinners, ballots = parseinput.parsestring(contents)
98
        if form.has_key("run1"):
102
        if form.has_key("run1"):
99
            doone(nWinners, ballots)
103
            doone(nWinners, ballots)
100
        elif form.has_key("run1000"):
104
        elif form.has_key("run1000"):
101
            domany(1000, nWinners, ballots)
105
            domany(1000, nWinners, ballots)
-
 
106
        elif form.has_key("runparallel"):
-
 
107
            doparallel(nWinners, ballots)
102
        else:
108
        else:
103
            print "UNEXPECTED SUBMIT BUTTON: %s" % form
109
            print "UNEXPECTED SUBMIT BUTTON: %s" % form
104
                
110
                
105
    emitPostHTML()
111
    emitPostHTML()
106
    return
112
    return
107
 
113
 
108
def main():
114
def main():
109
    usage = "usage: %prog [options] filename.csv"
115
    usage = "usage: %prog [options] filename.csv"
110
    parser = optparse.OptionParser(usage)
116
    parser = optparse.OptionParser(usage)
111
    parser.add_option("-m", "--multi", dest="multi", action="store_true",
117
    parser.add_option("-m", "--multiple", dest="multi", action="store_true",
112
                      help="run process multiple (1000) times")
118
                      help="run process multiple (1000) times")
-
 
119
    parser.add_option("-p", "--parallel", dest="para", action="store_true",
-
 
120
                      help="run process in parallel universes")
113
    (options, args) = parser.parse_args()
121
    (options, args) = parser.parse_args()
114
 
122
 
115
    if len(args) == 0:
123
    if len(args) == 0:
116
        doweb()
124
        doweb()
117
    else:
125
    else:
118
        nWinners, ballots = parseinput.parsefile(args[0])
126
        nWinners, ballots = parseinput.parsefile(args[0])
119
        if options.multi:
127
        if options.multi:
120
            domany(1000, nWinners, ballots)
128
            domany(1000, nWinners, ballots)
-
 
129
        elif options.para:
-
 
130
            doparallel(nWinners, ballots)
121
        else:
131
        else:
122
            doone(nWinners, ballots)
132
            doone(nWinners, ballots)
123
 
133
 
124
if __name__=='__main__':
134
if __name__=='__main__':
125
    main()
135
    main()