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 import os, pickle 34 from MoinMoin import wikiutil 35 from MoinMoin.util import filesys 36 37 def makeFilename(thisPage, voteName): 38 votesDir = thisPage.getPagePath("votes") 39 if not os.path.exists(votesDir): 40 filesys.makeDirs(votesDir) 41 voteName = wikiutil.quoteWikinameFS(voteName) + '.pik' 42 return os.path.join(votesDir, voteName) 43 44 def loadVotes(thisPage, voteName): 45 votesFile = makeFilename(thisPage, voteName) 46 try: 47 f = open(votesFile, 'r') 48 return pickle.load(f) 49 except: # XXX 50 return {} 51 52 def saveVotes(thisPage, voteName, votes): 53 votesFile = makeFilename(thisPage, voteName) 54 f = open(votesFile, 'w') 55 pickle.dump(votes, f) 56 57 def countVotes(votes): 58 results = {} 59 for v in votes.values(): 60 results.setdefault(v, 0) 61 results[v] += 1 62 return results 63 64 def execute(macro, args): 65 fmt = macro.formatter 66 67 args = args.split(",") 68 args = map(unicode.strip, args) 69 70 if len(args) < 1: 71 return fmt.rawHTML('<pre>[[Vote: Insufficient macro arguments]]</pre>') 72 73 pageName = args[0] 74 voteName = pageName 75 candidates = ['1','2','3','4','5'] 76 src_litstar = '/wiki/modern/img/star_on.png' 77 src_unlitstar = '/wiki/modern/img/star_off.png' 78 79 form = macro.form 80 request = macro.request 81 if request.user.valid: 82 voter = request.user.name 83 else: 84 voter = '' 85 thisPage = fmt.page 86 votes = loadVotes(thisPage, voteName) 87 88 # votes are stored in a dictionary as {user: candidate} to avoid duplicate votes 89 # (a voter could switch their vote but this UI doesn't expose that facility) 90 if form.has_key('vote') and form.has_key('voteName') and voter: 91 if form['voteName'][0] == voteName: 92 votes[voter] = form['vote'][0] 93 try: 94 saveVotes(thisPage, voteName, votes) 95 except: # XXX 96 return fmt.rawHTML('<pre>[[Vote: failed to store vote]]</pre>') 97 98 # generate dictionary {candidate: numvotes} 99 results = countVotes(votes) 100 onestar = results.setdefault(candidates[0],0) 101 twostar = results.setdefault(candidates[1],0) 102 threestar = results.setdefault(candidates[2],0) 103 fourstar = results.setdefault(candidates[3],0) 104 fivestar = results.setdefault(candidates[4],0) 105 counts = (onestar+twostar+threestar+fourstar+fivestar) 106 107 if counts == 0: 108 average = 0 109 else: 110 average = (onestar*1+twostar*2+threestar*3+fourstar*4+fivestar*5)/counts 111 112 hasVoted = voter in votes 113 114 # spit out votes table (as part of a form if the user hasn't voted yet) 115 html = [] 116 117 if voter: 118 html.append(''' 119 <form method="get" name="%(formname)s" action="%(url)s#%(formname)s">\n 120 <input type="hidden" name="voteName" value="%(voteName)s">\n 121 <input type="hidden" name="vote" value="0"> 122 ''' % { 123 'formname': voteName, 124 'url': thisPage.url(request), 125 'voteName': voteName, 126 } 127 ) 128 btnstar = '<input type="image" src="%(isrc)s" OnClick="document.%(form)s.vote.value=%(value)s">\n' 129 for i in range(1,6): 130 if i <= average: 131 html.append(btnstar % {'isrc':src_litstar, 'form':voteName, 'value': i}) 132 if i > average: 133 html.append(btnstar % {'isrc':src_unlitstar, 'form':voteName, 'value': i}) 134 if average == 0: 135 html.append(' No Rating') 136 #else: 137 # html.append(' %(avg)s ' % { 'avg': average }) 138 html.append('</form>') 139 else: 140 html.append('Please log in to vote.') 141 142 return fmt.rawHTML(''.join(html)) 143 144 # vim: tabstop=4 expandtab shiftwidth=4