Author: humbedooh
Date: Wed Mar 25 17:50:32 2015
New Revision: 1669184
URL: http://svn.apache.org/r1669184
Log:
Add FiC voting style, as requested by covener.
Added:
steve/trunk/pysteve/lib/plugins/fic.py
steve/trunk/pysteve/www/htdocs/ballot_fic.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=1669184&r1=1669183&r2=1669184&view=diff
==============================================================================
--- steve/trunk/pysteve/lib/plugins/__init__.py (original)
+++ steve/trunk/pysteve/lib/plugins/__init__.py Wed Mar 25 17:50:32 2015
@@ -23,6 +23,7 @@ CORE VOTE PLUGINS:
fpp: First Past the Post (Presidential elections)
mntv: Multiple Non-Transferable Votes
cop: Candidate or Party Voting
+ fic: First in Class Voting
"""
-__all__ = ['yna','stv','dh','fpp','mntv','cop']
\ No newline at end of file
+__all__ = ['yna','stv','dh','fpp','mntv','cop','fic']
\ No newline at end of file
Added: steve/trunk/pysteve/lib/plugins/fic.py
URL:
http://svn.apache.org/viewvc/steve/trunk/pysteve/lib/plugins/fic.py?rev=1669184&view=auto
==============================================================================
--- steve/trunk/pysteve/lib/plugins/fic.py (added)
+++ steve/trunk/pysteve/lib/plugins/fic.py Wed Mar 25 17:50:32 2015
@@ -0,0 +1,109 @@
+#
+# 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.
+#
+""" First in Class (FiC) Based Voting Plugin """
+import re, heapq
+
+from lib import constants
+
+def validateFIC(vote, issue):
+ "Tries to invalidate a vote, returns why if succeeded, None otherwise"
+ m = re.match(r"fic(\d+)", issue['type'])
+ if not m:
+ return "Not an FiC 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 tallyFIC(votes, issue):
+ m = re.match(r"fic(\d+)", issue['type'])
+ if not m:
+ raise Exception("Not an FiC 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]
+ i = 0
+ for letter in vote:
+ if not letter in matrix:
+ matrix[letter] = 0
+ matrix[letter] += numseats - i
+ i += 1
+
+ # Start counting
+ winners = [l for l in matrix if matrix[l] in heapq.nlargest(numseats,
matrix.values())]
+
+ # Compile list of winner names
+ winnernames = []
+ x = 0
+ for c in winners:
+ i = ord(c) - ord('a')
+ winnernames.append("%s ( %u)" % ( candidates[i],
heapq.nlargest(numseats, matrix.values())[x]))
+ x+=1
+
+ # Return the data
+ return {
+ 'votes': len(votes),
+ 'winners': winners,
+ 'winnernames': winnernames,
+ }
+
+
+constants.VOTE_TYPES += (
+ {
+ 'key': "fic1",
+ 'description': "First in Class Votes with 1 point max",
+ 'category': 'fic',
+ 'validate_func': validateFIC,
+ 'vote_func': None,
+ 'tally_func': tallyFIC
+ },
+)
+
+# Add ad nauseam
+for i in range(2,constants.MAX_NUM+1):
+ constants.VOTE_TYPES += (
+ {
+ 'key': "fic%u" % i,
+ 'description': "First in Class Votes with %u points max" % i,
+ 'category': 'fic',
+ 'validate_func': validateFIC,
+ 'vote_func': None,
+ 'tally_func': tallyFIC
+ },
+ )
\ No newline at end of file
Added: steve/trunk/pysteve/www/htdocs/ballot_fic.html
URL:
http://svn.apache.org/viewvc/steve/trunk/pysteve/www/htdocs/ballot_fic.html?rev=1669184&view=auto
==============================================================================
--- steve/trunk/pysteve/www/htdocs/ballot_fic.html (added)
+++ steve/trunk/pysteve/www/htdocs/ballot_fic.html Wed Mar 25 17:50:32 2015
@@ -0,0 +1,51 @@
+ <!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: FiC 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 First in Class Vote ballot with <span id="cnum">N</span>
candidates and
+ <span id="snum">N</span> points 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. Place the person you wish to give the highest score at the top,
+ then the person with the second highest score and so on.
+ 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 points to give out. 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=1669184&r1=1669183&r2=1669184&view=diff
==============================================================================
--- steve/trunk/pysteve/www/htdocs/js/steve_rest.js (original)
+++ steve/trunk/pysteve/www/htdocs/js/steve_rest.js Wed Mar 25 17:50:32 2015
@@ -494,6 +494,32 @@ function renderEditIssue(code, response,
obj.appendChild(div)
renderEditCandidates()
}
+ else if (edit_i.type.match(/^fic/)) {
+
+ // base data
+ obj.innerHTML = "<h3>Editing a First in Class Vote (" +
edit_i.type.toUpperCase() + ") 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 if (edit_i.type.match(/^cop/)) {
// base data
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=1669184&r1=1669183&r2=1669184&view=diff
==============================================================================
--- steve/trunk/pysteve/www/htdocs/js/steve_stv.js (original)
+++ steve/trunk/pysteve/www/htdocs/js/steve_stv.js Wed Mar 25 17:50:32 2015
@@ -520,7 +520,7 @@ function displayIssueSTV(code, response,
var m = response.issue.type.match(/(\d+)/);
if (m) {
seats = parseInt(m[1])
- if (response.issue.type.match(/mntv/)) {
+ if (response.issue.type.match(/mntv/) ||
response.issue.type.match(/fic/)) {
maxnum = seats
}
}