Hi! Here is the new (and as far as I am concerned now, ready) version of my little voting program. It is designed to be used in a village meeting where there is only one computer, and too much people to cast votes one by one. In the rows of the "vote" tab you give the candidates, and the number of voters who prefer the candidate above the one corresponding to the column. You click on the result tab and see the result. On the config tab you can configure the number of candidates and the font size for the other two tabs.
On some places it talks Hungarian, but you will understand it :) It depends on python, and its gtk and pango package. Copyright GNU GPL, any comments or criticism are welcome.
#!/usr/bin/python # -*- coding: utf-8 -*- # Copyright [email protected] GNU GPL import pygtk pygtk.require('2.0') import gtk import pango class Configuration: def __init__(self): self.rownum=5 self.fontsize=20 self.fd=pango.FontDescription("Sans %d"%self.fontsize) class MainWin: def delete_event(self,widget,event,data=None): return False def destroy(self,widget,data=None): gtk.main_quit() def __init__(self,children): self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) self.window.connect("delete_event", self.delete_event) self.window.connect("destroy", self.destroy) self.window.set_border_width(10) self.notebook = gtk.Notebook() self.window.add(self.notebook) self.notebook.show() self.window.show() self.children=children for w,n in children: self.add(w.widget,n) def main(self): gtk.main() def add(self,widget,name): self.notebook.add(widget) self.notebook.set_tab_label_text(widget,name) widget.show() class Config: def __init__(self,config=None): self.config=config self.widget=gtk.Table(rows=3,columns=2) label=gtk.Label("# of candidates") self.widget.attach(label,0,1,0,1) self.rownumentry=gtk.Entry() self.rownumentry.insert_text('5') self.widget.attach(self.rownumentry,1,2,0,1) label2=gtk.Label("Font size") self.widget.attach(label2,0,1,1,2) self.fontsizentry=gtk.Entry() self.fontsizentry.insert_text('20') self.widget.attach(self.fontsizentry,1,2,1,2) self.button=gtk.Button("Legyen") self.button.connect('clicked',self.configure,None) self.widget.attach(self.button,2,3,0,2) label.show() label2.show() self.rownumentry.show() self.fontsizentry.show() self.button.show() def configure(self,widget,data=None): ns=self.rownumentry.get_chars(0,-1) if ns == '': ns = '0' n=int(ns) print ns,n self.config.rownum=n ns=self.fontsizentry.get_chars(0,-1) if ns == '': ns = '0' n=int(ns) print ns,n self.config.fontsize=n self.config.fd=pango.FontDescription("Sans %d"%n) class Entries: def __init__(self, config=None): self.config=config self.widget=gtk.Table(rows=self.config.rownum,columns=self.config.rownum+1) self.widget.connect('map',self.configure,None) self.populate() self.widget.show() def populate(self,fr=0): fd=self.config.fd for e in self.widget.get_children(): e.destroy() self.children=[] for i in range(fr,self.config.rownum): cs=[] e=gtk.Entry() e.modify_font(fd) cs.append(e) e.set_property("width-chars",30) e.show() self.widget.attach(e,0,1,i,i+1) for j in range(fr,self.config.rownum): if i == j: e=gtk.Label(' - ') else: e=gtk.Entry() e.set_property("width-chars",3) cs.append(e) e.modify_font(fd) e.show() self.widget.attach(e,1+j,2+j,i,i+1,xoptions=0) self.children.append(cs) def harvest(self): l=[] for i in self.children: ll=[] for j in i: if j.__class__ == gtk.Label: ll.append("0") else: ll.append(j.get_chars(0,-1)) l.append(ll) return l def configure(self,widget=None,data=None): l=self.harvest() self.widget.resize(rows=self.config.rownum,columns=self.config.rownum+1) self.populate() x=0 for i in l[:self.config.rownum]: y=0 for j in i[:self.config.rownum+1]: k=self.children[x][y] if k.__class__ != gtk.Label: k.insert_text(j) y += 1 x += 1 class Result: def __init__(self,entries,config=None): self.config=config self.widget=gtk.Label("ide jon\n az eredmeny") self.widget.connect('map',self.compute,None) self.entries=entries def printmat(self,m): l=[] for i in range(len(self.candidates)): ll=[] for j in range(len(self.candidates)): if i == j: ll.append('-') else: ll.append('%s'%m[i,j]) l.append(','.join(ll)) print '\n'.join(l) def compute_old(self,widget,data=None): self.widget.set_text('computing result') self.getdata() self.floyd_warshall() print self.candidates self.printmat(self.d) self.printmat(self.p) C = len(self.candidates) winners=[] hasnew = True while hasnew: hasnew = False for i in range(C): if i not in winners: isnew = True for j in range(C): if j not in winners: if i != j: if self.p[i,j] < self.p[j,i]: isnew = False if isnew: winners.append(i) hasnew = True print winners s="" for i in range(len(winners)): s += self.candidates[winners[i]] if i > 0: s += ",by %s:%s"%(self.p[winners[i],winners[i-1]],self.p[winners[i-1],winners[i]]) s += "\n" print s self.widget.set_text(s) def getdata(self): l=self.entries.harvest() candidates=[] d={} x=0 for line in l: candidates.append(line[0]) y=0 for pr in line[1:]: if pr == '': pr = '0' d[x,y]=int(pr) y+=1 x+=1 self.candidates=candidates self.d=d def floyd_warshall(self): candidates=self.candidates C=len(candidates) d=self.d p={} for i in range(C): for j in range(C): if i != j: if d[i,j] > d[j,i]: p[i,j] = d[i,j] else: p[i,j] = 0 for i in range(C): for j in range(C): if i != j: for k in range(C): if i != k: if j != k: p[j,k] = max(p[j,k],min(p[j,i],p[i,k])) self.p = p def winners(self,ignore): n=len(self.candidates) winner=[] for i in range(n): if not ignore.has_key(i): won = True for j in range(n): if not (ignore.has_key(j) or (i == j)): if self.p[i,j] < self.p[j,i]: won = False break if won: winner.append(i) return winner def rank_candidates(self): n=len(self.candidates) ignore={} num_ranked=0 result=[] while (num_ranked < n): winner_list=self.winners(ignore) result.append(winner_list) for j in winner_list: ignore[j] = 1 num_ranked += 1 return result def _losenum(self,i,j): s=" %s: %d "%(self.candidates[j],self.p[j,i]) #print i,j,s return s def loosedata(self,ranking,now,n): l = [] if n > 0: l +=ranking[n-1] if n > 1: l +=ranking[n-2] s='' print l for c in l: if c != now: s += self._losenum(now,c) return s def compute(self,widget,data=None): fd=self.config.fd self.widget.modify_font(fd) self.widget.set_text('computing result') self.getdata() self.floyd_warshall() print self.candidates self.printmat(self.d) self.printmat(self.p) ranking=self.rank_candidates() print ranking s="Sorrend:\n" n=0 for r in ranking: s += " %d. hely:"%(n+1) if len(r) > 1: s += " holtverseny:\n" for i in r: s+= " %s (%s)\n"%(self.candidates[i],self.loosedata(ranking,i,n)) n+=1 print s self.widget.set_text(s) def main(go=False): conf=Configuration() e=Entries(config=conf) c=Config(config=conf) r=Result(e,config=conf) mainwin = MainWin([(c,'config'),(r,"result"),(e,'vote')]) if go: mainwin.main() if __name__ == "__main__": main(True)
---- Election-Methods mailing list - see http://electorama.com/em for list info
