Author: humbedooh
Date: Wed Mar 25 01:55:21 2015
New Revision: 1669042

URL: http://svn.apache.org/r1669042
Log:
Add Multiple Non-Transferable Votes (MNTV) system to it as well, we're on a 
roll here!

Added:
    steve/trunk/pysteve/lib/plugins/mntv.py
    steve/trunk/pysteve/www/htdocs/ballot_mntv.html
Modified:
    steve/trunk/pysteve/lib/plugins/__init__.py
    steve/trunk/pysteve/www/htdocs/js/steve_rest.js
    steve/trunk/pysteve/www/htdocs/js/steve_stv.js

Modified: steve/trunk/pysteve/lib/plugins/__init__.py
URL: 
http://svn.apache.org/viewvc/steve/trunk/pysteve/lib/plugins/__init__.py?rev=1669042&r1=1669041&r2=1669042&view=diff
==============================================================================
--- steve/trunk/pysteve/lib/plugins/__init__.py (original)
+++ steve/trunk/pysteve/lib/plugins/__init__.py Wed Mar 25 01:55:21 2015
@@ -19,6 +19,7 @@ yna
 stv
 dh
 fpp
+mntv
 """
 
-__all__ = ['yna','stv','dh','fpp']
\ No newline at end of file
+__all__ = ['yna','stv','dh','fpp','mntv']
\ No newline at end of file

Added: steve/trunk/pysteve/lib/plugins/mntv.py
URL: 
http://svn.apache.org/viewvc/steve/trunk/pysteve/lib/plugins/mntv.py?rev=1669042&view=auto
==============================================================================
--- steve/trunk/pysteve/lib/plugins/mntv.py (added)
+++ steve/trunk/pysteve/lib/plugins/mntv.py Wed Mar 25 01:55:21 2015
@@ -0,0 +1,105 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+""" Multiple Non-Transferable Vote (MNTV) Based Voting Plugin """
+import re, heapq
+
+from lib import constants
+
+def validateMNTV(vote, issue):
+    "Tries to invalidate a vote, returns why if succeeded, None otherwise"
+    m = re.match(r"mntv(\d+)", issue['type'])
+    if not m:
+        return "Not an MNTV vote!"
+    numseats = int(m.group(1))
+    letters = [chr(i) for i in range(ord('a'), ord('a') + 
len(issue['candidates']))]
+    if len(vote) > numseats:
+        return "Vote contains too many candidates!"
+    for char in vote:
+        if char not in letters:
+            return "Invalid characters in vote. Accepted are: %s" % ", 
".join(letters)
+    return None
+
+
+def tallyMNTV(votes, issue):
+    m = re.match(r"mntv(\d+)", issue['type'])
+    if not m:
+        raise Exception("Not an MNTV vote!")
+    
+    numseats = int(m.group(1))
+    candidates = []
+    for c in issue['candidates']:
+        candidates.append(c['name'])
+    
+
+    debug = []
+    
+    # Set up letters for mangling
+    letters = [chr(i) for i in range(ord('a'), ord('a') + len(candidates))]
+    cc = "".join(letters)
+    
+    # Set up seats won
+    winners = []
+   
+    # Set up vote matrix 
+    matrix = {}
+    for key in votes:
+        vote = votes[key]
+        for letter in vote:
+            if not letter in matrix:
+                matrix[letter] = 0
+            matrix[letter] += 1
+
+    # Start counting
+    winners = [l for l in matrix if matrix[l] in heapq.nlargest(numseats, 
matrix.values())]
+
+    # Compile list of winner names
+    winnernames = []
+    for c in winners:
+        i = ord(c) - ord('a')
+        winnernames.append(candidates[i])
+
+    # Return the data
+    return {
+        'votes': len(votes),
+        'winners': winners,
+        'winnernames': winnernames,
+    }
+
+
+constants.VOTE_TYPES += (
+    {
+        'key': "mntv1",
+        'description': "Multiple Non-Transferable Votes (MNTV) with 1 seat",
+        'category': 'dh',
+        'validate_func': validateMNTV,
+        'vote_func': None,
+        'tally_func': tallyMNTV
+    },
+)
+
+# Add ad nauseam
+for i in range(2,constants.MAX_NUM+1):
+    constants.VOTE_TYPES += (
+        {
+            'key': "mntv%u" % i,
+            'description': "Multiple Non-Transferable Votes (MNTV) with %u 
seats" % i,
+            'category': 'mntv',
+            'validate_func': validateMNTV,
+            'vote_func': None,
+            'tally_func': tallyMNTV
+        },
+    )
\ No newline at end of file

Added: steve/trunk/pysteve/www/htdocs/ballot_mntv.html
URL: 
http://svn.apache.org/viewvc/steve/trunk/pysteve/www/htdocs/ballot_mntv.html?rev=1669042&view=auto
==============================================================================
--- steve/trunk/pysteve/www/htdocs/ballot_mntv.html (added)
+++ steve/trunk/pysteve/www/htdocs/ballot_mntv.html Wed Mar 25 01:55:21 2015
@@ -0,0 +1,49 @@
+ <!DOCTYPE HTML>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="css/steve_interactive.css">
+<link rel="stylesheet" href="css/jquery-ui.css">
+<script src="js/steve_rest.js" type="text/javascript"></script>
+<script src="js/steve_stv.js" type="text/javascript"></script>
+<title>Apache STeVe: MNTV Voting</title>
+
+</head>
+<body onload="window.setTimeout(loadIssue, 500, null, null, null, 
displayIssueSTV, 'mntv');">
+    <div id="popups"></div>
+    <p style="text-align: center;">
+        <img src="/images/steve_logo.png"/>
+    </p>
+    <a href="javascript:void(location.href='election.html' + 
document.location.search);">Back to election front page</a>
+<div class="formbox" id="votebox">
+    <h2 id="title"></h2>
+<p>
+    This is a Multiple Non-Transferable Vote ballot with <span 
id="cnum">N</span> candidates and
+    <span id="snum">N</span> seats available.
+    All the nominees are placed in random order on the candidate list.
+    If the canidate has prepared a statement, you can view it by clicking on 
the
+    statement link to the right of the candidate's name.
+</p>
+<p>
+    <b>How to vote:</b><br/>
+    Drag a candidate from the candidate list to the ballot box to place them in
+    the vote. You can rearrange your votes as you see fit, by dragging
+    candidates up/down on the ballot box list. You may only votes for as many
+    canidates as there are seats. If you want to
+    remove a single candidate from your ballot box, simply drag the
+    canidate back to the list of remaining candidates to the left.
+</p>
+<div id="preloaderWrapper">
+    <img src="/images/steve_spinner.gif"/>
+    <div id="preloader">
+        Loading issues, please wait...
+    </div>
+</div>
+</div>
+<p style="font-size: 12px; font-style: italic; text-align: center;">
+    Powered by <a href="https://steve.apache.org/";>Apache STeVe</a>.
+    Copyright 2015, the Apache Software Foundation.
+    Licensed under the <a 
href="http://www.apache.org/licenses/LICENSE-2.0";>Apache License 2.0</a>
+</p>
+</body>
+</html>
\ No newline at end of file

Modified: steve/trunk/pysteve/www/htdocs/js/steve_rest.js
URL: 
http://svn.apache.org/viewvc/steve/trunk/pysteve/www/htdocs/js/steve_rest.js?rev=1669042&r1=1669041&r2=1669042&view=diff
==============================================================================
--- steve/trunk/pysteve/www/htdocs/js/steve_rest.js (original)
+++ steve/trunk/pysteve/www/htdocs/js/steve_rest.js Wed Mar 25 01:55:21 2015
@@ -467,6 +467,32 @@ function renderEditIssue(code, response,
                        obj.appendChild(div)
                        renderEditCandidates()
                }
+               else if (edit_i.type.match(/^mntv/)) {
+                       
+                       // base data
+                       obj.innerHTML = "<h3>Editing a Multiple 
Non-Transferable Vote issue</h3>"
+                       obj.appendChild(keyvaluepair("id", "Issue ID:", "text", 
edit_i.id, true))
+                       obj.appendChild(keyvaluepair("ititle", "Issue title:", 
"text", edit_i.title))
+                       obj.appendChild(keyvaluepair("description", 
"Description (optinal):", "textarea", edit_i.description))
+                       obj.appendChild(document.createElement('hr'))
+                       
+                       // candidates
+                       var cobj = document.createElement('div')
+                       cobj.setAttribute("id", "candidateList")
+                       cobj.setAttribute("class", "candidateEditList")
+                       obj.appendChild(cobj)
+                       
+                       var div = document.createElement('div')
+                       div.setAttribute("class", "keyvaluepair")
+                       var btn = document.createElement('input')
+                       btn.setAttribute("type", "button")
+                       btn.setAttribute("class", "btn-green")
+                       btn.setAttribute("value", "Save changes")
+                       btn.setAttribute("onclick", "saveSTV();")
+                       div.appendChild(btn)
+                       obj.appendChild(div)
+                       renderEditCandidates()
+               }
        } else {
                alert(response.message)
        }

Modified: steve/trunk/pysteve/www/htdocs/js/steve_stv.js
URL: 
http://svn.apache.org/viewvc/steve/trunk/pysteve/www/htdocs/js/steve_stv.js?rev=1669042&r1=1669041&r2=1669042&view=diff
==============================================================================
--- steve/trunk/pysteve/www/htdocs/js/steve_stv.js (original)
+++ steve/trunk/pysteve/www/htdocs/js/steve_stv.js Wed Mar 25 01:55:21 2015
@@ -25,6 +25,7 @@ var ballotChars = []
 var chars;
 var fading = false
 var seats = 0;
+var maxnum = 9999
 
 // Make copies for reset
 var candidates_copy = []
@@ -103,7 +104,7 @@ function dropComplete(z) {
         ballotNames.splice(did, 0, ballotNames.splice(sid, 1)[0])
         ballotChars.splice(did, 0, ballotChars.splice(sid, 1)[0])
     } else {
-        alert(source + ":" + dest)
+        //alert(source + ":" + dest)
     }
     //ev.preventDefault();
     // Redraw and carry on
@@ -206,8 +207,10 @@ function drawCandidates() {
 
 // Did we drop a vote on top of another?
 function dropCandidate(ev) {
-    
     ev.preventDefault();
+    if (ballotNames.length >= maxnum) {
+        return; // MNTV lockout
+    }
     source = ev.dataTransfer.getData("Text");
     dest = ev.target.getAttribute("data")
     var z = 0;
@@ -517,6 +520,9 @@ function displayIssueSTV(code, response,
         var m = response.issue.type.match(/(\d+)/);
         if (m) {
             seats = parseInt(m[1])
+            if (response.issue.type.match(/mntv/)) {
+                maxnum = seats
+            }
         }
         for (c in response.issue.candidates) {
             var candidate = response.issue.candidates[c];
@@ -609,4 +615,5 @@ function castVotesCallback(code, respons
     } else {
         document.getElementById('votebox').innerHTML = "<h2>Your vote has been 
registered!</h2><p style='text-align:center;'><big>Should you reconsider, you 
can always reload this page and vote again.<br/><br/><a 
href=\"javascript:void(location.href='election.html'+document.location.search);\">Back
 to election front page</a></big></p>"
     }
-}
\ No newline at end of file
+}
+


Reply via email to