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


Reply via email to