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