Attachment 'VotingStars.py'
Download 1 #format python
2 # -*- coding: iso-8859-1 -*-
3 '''
4 MoinMoin - VotingStars Macro
5 Author: Travis Bailey
6 Date: February 2006
7
8 Purpose:
9 This macro allows ratings of items using stars (based on Vote macro)
10 Usage:
11 [[VotingStars(UniqueName)]]
12 e.g. 1. NiceShop [[VotingStars(shop1)]]
13 1. EvenNicerShop [[VotingStars(shop2)]]
14 Tested:
15 Firefox 1.5 MoinMoin 1.5.1 Python 2.3
16
17 I basically just slapped this together from the Vote1_3.py script and the
18 RatingStars.py script. I wanted to get the benefits of both. I wanted a
19 Utility to only allow Registered users to submit, allow them to change
20 their vote, and to average the results.
21
22 So basically it uses the Vote1_3.py code to track one vote per user.
23 It averages the total stars given and then displays the number of average
24 number of rated stars.
25
26 You can have multiple VotingStars on one page (so long as the UniqueNames are unique)
27 Changing the UniqueName creates a new vote.
28 Make sure not to conflict with any Vote names you are using
29
30 VotingStars data is stored in data_dir/pages/pagename/votes
31 (i.e. alongside the attachments directory for a page).
32
33 You can customise the appearance by defining the following CSS styles:
34 table.votestars
35
36 '''
37 import os, pickle
38 from MoinMoin import wikiutil
39 from MoinMoin.util import filesys
40
41 def makeFilename(thisPage, voteName):
42 votesDir = thisPage.getPagePath("votes")
43 if not os.path.exists(votesDir):
44 filesys.makeDirs(votesDir)
45 voteName = wikiutil.quoteWikinameFS(voteName) + '.pik'
46 return os.path.join(votesDir, voteName)
47
48 def loadVotes(thisPage, voteName):
49 votesFile = makeFilename(thisPage, voteName)
50 try:
51 f = open(votesFile, 'r')
52 return pickle.load(f)
53 except: # XXX
54 return {}
55
56 def saveVotes(thisPage, voteName, votes):
57 votesFile = makeFilename(thisPage, voteName)
58 f = open(votesFile, 'w')
59 pickle.dump(votes, f)
60
61 def countVotes(votes):
62 results = {}
63 for v in votes.values():
64 results.setdefault(v, 0)
65 results[v] += 1
66 return results
67
68 def execute(macro, args):
69 args = args.split(",")
70 args = map(unicode.strip, args)
71
72 if len(args) < 1:
73 return macro.formatter.rawHTML('<pre>[[Vote: Insufficient macro arguments]]</pre>')
74
75 pageName = args[0]
76 voteName = pageName
77 candidates = ['1','2','3','4','5']
78 src_litstar = '/wiki/modern/img/star_on.png'
79 src_unlitstar = '/wiki/modern/img/star_off.png'
80
81 form = macro.form
82 request = macro.request
83 if request.user.valid:
84 voter = request.user.name
85 else:
86 voter = ''
87 thisPage = macro.formatter.page
88 votes = loadVotes(thisPage, voteName)
89
90 # votes are stored in a dictionary as {user: candidate} to avoid duplicate votes
91 # (a voter could switch their vote but this UI doesn't expose that facility)
92 if form.has_key('vote') and form.has_key('voteName') and voter:
93 if form['voteName'][0] == voteName:
94 votes[voter] = form['vote'][0]
95 try:
96 saveVotes(thisPage, voteName, votes)
97 except: # XXX
98 return macro.formatter.rawHTML('<a id="voteform"><pre>[[Vote: failed to store vote]]</pre>')
99
100 # generate dictionary {candidate: numvotes}
101 results = countVotes(votes)
102 onestar = results.setdefault(candidates[0],0)
103 twostar = results.setdefault(candidates[1],0)
104 threestar = results.setdefault(candidates[2],0)
105 fourstar = results.setdefault(candidates[3],0)
106 fivestar = results.setdefault(candidates[4],0)
107 counts = (onestar+twostar+threestar+fourstar+fivestar)
108
109 if counts == 0:
110 average = 0
111 else:
112 average = (onestar*1+twostar*2+threestar*3+fourstar*4+fivestar*5)/counts
113
114 hasVoted = voter in votes
115
116 # spit out votes table (as part of a form if the user hasn't voted yet)
117 html = '<a id="voteform"><table class="votestars"><tr><td>'
118
119 if voter:
120 html += '''
121 <form method="get" name="%(formname)s" action="%(url)s#voteform">\n
122 <input type="hidden" name="voteName" value="%(voteName)s">\n
123 <input type="hidden" name="vote" value="0">
124 ''' % {
125 'formname': voteName,
126 'url': thisPage.url(request),
127 'voteName': voteName,
128 }
129 btnstar = '<input type="image" src="%(isrc)s" OnClick="document.%(form)s.vote.value=%(value)s">\n'
130 for i in range(1,6):
131 if i <= average:
132 html += btnstar % {'isrc':src_litstar, 'form':voteName, 'value': i}
133 if i > average:
134 html += btnstar % {'isrc':src_unlitstar, 'form':voteName, 'value': i}
135 if average == 0:
136 html += ' No Rating'
137 #else:
138 # html += ' %(avg)s ' % { 'avg': average }
139 html += '</form></td></tr></table></a>'
140 else:
141 html += 'You must be logged in to Rate.</td></tr></table></a>'
142
143 return macro.formatter.rawHTML(html)
144
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.