1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/macros/VotingStars.py Sat Mar 01 21:45:56 2008 +0100
1.3 @@ -0,0 +1,144 @@
1.4 +#format python
1.5 +# -*- coding: iso-8859-1 -*-
1.6 +'''
1.7 + MoinMoin - VotingStars Macro
1.8 + Author: Travis Bailey
1.9 + Date: February 2006
1.10 +
1.11 + Purpose:
1.12 + This macro allows ratings of items using stars (based on Vote macro)
1.13 + Usage:
1.14 + [[VotingStars(UniqueName)]]
1.15 + e.g. 1. NiceShop [[VotingStars(shop1)]]
1.16 + 1. EvenNicerShop [[VotingStars(shop2)]]
1.17 + Tested:
1.18 + Firefox 1.5 MoinMoin 1.5.1 Python 2.3
1.19 +
1.20 + I basically just slapped this together from the Vote1_3.py script and the
1.21 + RatingStars.py script. I wanted to get the benefits of both. I wanted a
1.22 + Utility to only allow Registered users to submit, allow them to change
1.23 + their vote, and to average the results.
1.24 +
1.25 + So basically it uses the Vote1_3.py code to track one vote per user.
1.26 + It averages the total stars given and then displays the number of average
1.27 + number of rated stars.
1.28 +
1.29 + You can have multiple VotingStars on one page (so long as the UniqueNames are unique)
1.30 + Changing the UniqueName creates a new vote.
1.31 + Make sure not to conflict with any Vote names you are using
1.32 +
1.33 + VotingStars data is stored in data_dir/pages/pagename/votes
1.34 + (i.e. alongside the attachments directory for a page).
1.35 +
1.36 + You can customise the appearance by defining the following CSS styles:
1.37 + table.votestars
1.38 +
1.39 +'''
1.40 +import os, pickle
1.41 +from MoinMoin import wikiutil
1.42 +from MoinMoin.util import filesys
1.43 +
1.44 +def makeFilename(thisPage, voteName):
1.45 + votesDir = thisPage.getPagePath("votes")
1.46 + if not os.path.exists(votesDir):
1.47 + filesys.makeDirs(votesDir)
1.48 + voteName = wikiutil.quoteWikinameFS(voteName) + '.pik'
1.49 + return os.path.join(votesDir, voteName)
1.50 +
1.51 +def loadVotes(thisPage, voteName):
1.52 + votesFile = makeFilename(thisPage, voteName)
1.53 + try:
1.54 + f = open(votesFile, 'r')
1.55 + return pickle.load(f)
1.56 + except: # XXX
1.57 + return {}
1.58 +
1.59 +def saveVotes(thisPage, voteName, votes):
1.60 + votesFile = makeFilename(thisPage, voteName)
1.61 + f = open(votesFile, 'w')
1.62 + pickle.dump(votes, f)
1.63 +
1.64 +def countVotes(votes):
1.65 + results = {}
1.66 + for v in votes.values():
1.67 + results.setdefault(v, 0)
1.68 + results[v] += 1
1.69 + return results
1.70 +
1.71 +def execute(macro, args):
1.72 + args = args.split(",")
1.73 + args = map(unicode.strip, args)
1.74 +
1.75 + if len(args) < 1:
1.76 + return macro.formatter.rawHTML('<pre>[[Vote: Insufficient macro arguments]]</pre>')
1.77 +
1.78 + pageName = args[0]
1.79 + voteName = pageName
1.80 + candidates = ['1','2','3','4','5']
1.81 + src_litstar = '/wiki/modern/img/star_on.png'
1.82 + src_unlitstar = '/wiki/modern/img/star_off.png'
1.83 +
1.84 + form = macro.form
1.85 + request = macro.request
1.86 + if request.user.valid:
1.87 + voter = request.user.name
1.88 + else:
1.89 + voter = ''
1.90 + thisPage = macro.formatter.page
1.91 + votes = loadVotes(thisPage, voteName)
1.92 +
1.93 + # votes are stored in a dictionary as {user: candidate} to avoid duplicate votes
1.94 + # (a voter could switch their vote but this UI doesn't expose that facility)
1.95 + if form.has_key('vote') and form.has_key('voteName') and voter:
1.96 + if form['voteName'][0] == voteName:
1.97 + votes[voter] = form['vote'][0]
1.98 + try:
1.99 + saveVotes(thisPage, voteName, votes)
1.100 + except: # XXX
1.101 + return macro.formatter.rawHTML('<a id="voteform"><pre>[[Vote: failed to store vote]]</pre>')
1.102 +
1.103 + # generate dictionary {candidate: numvotes}
1.104 + results = countVotes(votes)
1.105 + onestar = results.setdefault(candidates[0],0)
1.106 + twostar = results.setdefault(candidates[1],0)
1.107 + threestar = results.setdefault(candidates[2],0)
1.108 + fourstar = results.setdefault(candidates[3],0)
1.109 + fivestar = results.setdefault(candidates[4],0)
1.110 + counts = (onestar+twostar+threestar+fourstar+fivestar)
1.111 +
1.112 + if counts == 0:
1.113 + average = 0
1.114 + else:
1.115 + average = (onestar*1+twostar*2+threestar*3+fourstar*4+fivestar*5)/counts
1.116 +
1.117 + hasVoted = voter in votes
1.118 +
1.119 + # spit out votes table (as part of a form if the user hasn't voted yet)
1.120 + html = '<a id="voteform"><table class="votestars"><tr><td>'
1.121 +
1.122 + if voter:
1.123 + html += '''
1.124 + <form method="get" name="%(formname)s" action="%(url)s#voteform">\n
1.125 + <input type="hidden" name="voteName" value="%(voteName)s">\n
1.126 + <input type="hidden" name="vote" value="0">
1.127 + ''' % {
1.128 + 'formname': voteName,
1.129 + 'url': thisPage.url(request),
1.130 + 'voteName': voteName,
1.131 + }
1.132 + btnstar = '<input type="image" src="%(isrc)s" OnClick="document.%(form)s.vote.value=%(value)s">\n'
1.133 + for i in range(1,6):
1.134 + if i <= average:
1.135 + html += btnstar % {'isrc':src_litstar, 'form':voteName, 'value': i}
1.136 + if i > average:
1.137 + html += btnstar % {'isrc':src_unlitstar, 'form':voteName, 'value': i}
1.138 + if average == 0:
1.139 + html += ' No Rating'
1.140 + #else:
1.141 + # html += ' %(avg)s ' % { 'avg': average }
1.142 + html += '</form></td></tr></table></a>'
1.143 + else:
1.144 + html += 'You must be logged in to Rate.</td></tr></table></a>'
1.145 +
1.146 + return macro.formatter.rawHTML(html)
1.147 +