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
+}
+