Rev 77 | Blame | Compare with Previous | Last modification | View Log | RSS feed
#!/usr/bin/env pythonimport optparseimport cgiimport stringimport sysimport parseinputimport tallyfHTML = 1formaction = string.split(sys.argv[0],"/")[-1]def emitPreHTML(formaction):emitHTML("""Content-type: text/html\n<html><body><title>Hare Ballot Calculation</title><h1>Hare Ballot Calculation</h1><form enctype="multipart/form-data" method=POST action=%s><table><tr><td>CSV file of ballots:<td><input type=file size=70 name=name></table><p><input type=submit name="run1" value="Run 1 Time"><!-- <input type=submit name="run500" value="Run 500 Times"> --><input type=submit name="runparallel" value="Run All Ways"></form><p>Input is a CSV/spreadsheet file with the number of winners to beselected 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<a href="http://www.bikmort.com/dokuwiki/hare_voting_procedure">here</a>.Little error checking is done, so be sure to review the trace output.The source code is available <a href="%s?fetch=yes">here</a>.<p><small>%s</small><hr><pre>""" % (formaction, formaction, "$Id: vote.py 78 2016-05-11 19:18:03Z jtkorb $"))returndef emitPostHTML():emitHTML("""</pre></body></html>""")returndef emitHTML(s):global fHTMLif fHTML: print sreturndef doone(nWinners, ballots):tally.traceLevel = 1tally.fParallel = 0results = tally.dotally(nWinners, ballots)def domany(nTimes, nWinners, ballots):tally.traceLevel = 0tally.fParallel = 0summary = {}for i in range(nTimes):results = str(tally.dotally(nWinners, ballots))if not summary.has_key(results):summary[results] = 0summary[results] = summary[results] + 1tally.trace(0, "\nSUMMARY AFTER %d TIMES" % nTimes)l = summary.items()l.sort(lambda x,y: cmp(y[1], x[1]))for pair in l:tally.trace(0, "%3d %s" % (pair[1], pair[0]))def doparallel(nWinners, ballots):tally.traceLevel = 0tally.fParallel = 1results = tally.dotally(nWinners, ballots)def doweb():emitPreHTML(formaction)form = cgi.FieldStorage()if not form:emitHTML("Enter file name and press a button to see results.")elif form.has_key("fetch"):filename = string.replace(formaction, "vote.py", "tally.py")source = open(filename).read()print cgi.escape(source)elif not form.has_key("name"):emitHTML("Error: no file received")elif not form["name"].filename:emitHTML("Error: file name missing")else:name = form["name"].filenamecontents = form["name"].valuetally.trace(0, "INPUT FILE")tally.trace(0, contents)nWinners, ballots = parseinput.parsestring(contents)if form.has_key("run1"):doone(nWinners, ballots)elif form.has_key("run1000"):domany(1000, nWinners, ballots)elif form.has_key("runparallel"):doparallel(nWinners, ballots)else:print "UNEXPECTED SUBMIT BUTTON: %s" % formemitPostHTML()returndef main():usage = "usage: %prog [options] filename.csv"parser = optparse.OptionParser(usage)parser.add_option("-m", "--multiple", dest="multi", action="store_true",help="run process multiple (1000) times")parser.add_option("-p", "--parallel", dest="para", action="store_true",help="run process in parallel universes")(options, args) = parser.parse_args()if len(args) == 0:doweb()else:nWinners, ballots = parseinput.parsefile(args[0])if options.multi:domany(1000, nWinners, ballots)elif options.para:doparallel(nWinners, ballots)else:doone(nWinners, ballots)if __name__=='__main__':main()