This is an automated email from the ASF dual-hosted git repository.
sebb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/whimsy.git
The following commit(s) were added to refs/heads/master by this push:
new 09f6f2dc Hack to work-round #257
09f6f2dc is described below
commit 09f6f2dc58bf49a222b9efdf116ab88417073341
Author: Sebb <[email protected]>
AuthorDate: Wed Feb 26 15:42:03 2025 +0000
Hack to work-round #257
Need revisiting
---
tools/whatif.rb | 185 +++++++++++++++++++++++++++++++++++++++++++++++++
www/members/whatif.cgi | 10 ++-
2 files changed, 194 insertions(+), 1 deletion(-)
diff --git a/tools/whatif.rb b/tools/whatif.rb
new file mode 100755
index 00000000..00c8d6de
--- /dev/null
+++ b/tools/whatif.rb
@@ -0,0 +1,185 @@
+# STV Explorer using Historical data from ASF Board Votes
+
+#####
+# 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.
+#####
+
+# N.B. This is a copy of the file
+# https://raw.githubusercontent.com/apache/steve/refs/heads/trunk/whatif.rb
+# adjusted to remove untaint calls (and fix the jquery reference)
+# It's not currently possible to fix the code in Git and use that;
+# see members/whatif.cgi for explanation
+
+#
+# Prereqs:
+#
+# * svn checkout of foundation:voter and foundation:Meetings
+# * Web server with the ability to run cgi (Apache httpd recommended)
+# * Python 2.6.x
+# * Ruby 1.9.x
+# * wunderbar gem ([sudo] gem install wunderbar)
+# * (optional) jQuery http://code.jquery.com/jquery-min.js
+#
+# Installation instructions:
+#
+# ruby whatif.rb --install=/var/www
+#
+# 1) Specify a path that supports cgi, like public-html or Sites.
+# 2) (optional, but highly recommended) download jquery-min.js into
+# your installation directory.
+#
+# Execution instructions:
+#
+# Point your web browser at your cgi script. For best results, use
+# Firefox 4 or a WebKit based browser, like Google Chrome.
+
+
+
+MEETINGS = File.expand_path('../Meetings') unless defined? MEETINGS
+WHATIF = './whatif.py' unless defined? WHATIF
+
+require 'wunderbar'
+require 'tempfile'
+
+def raw_votes(date)
+ all_votes = Dir["#{MEETINGS}/*/raw_board_votes.txt"]
+ if date
+ result = "#{MEETINGS}/#{date}/raw_board_votes.txt"
+ else
+ result = all_votes.sort.last
+ end
+ result
+end
+
+def ini(vote)
+ vote.sub('/raw_','/').sub('votes.','nominations.').sub('.txt','.ini')
+end
+
+def filtered_election(votes, seats, candidates)
+ list = candidates.join(' ')
+
+ output = `#{WHATIF} #{votes} #{seats} #{list}`
+ output.scan(/.*elected$/).inject(Hash.new('none')) do |results, line|
+ name, status = line.scan(/^(.*?)\s+(n?o?t?\s?elected)$/).flatten
+ results.merge({name.gsub(/[^[[:alnum:]]]/,'') => status.gsub(/\s/, '-')})
+ end
+end
+
+# XMLHttpRequest (AJAX)
+_json do
+ nominees = File.read(ini(raw_votes(@date))).scan(/^\w:\s*(.*)/).flatten
+ candidates = params.keys & nominees.map {|name|
name.gsub(/[^[[:alnum:]]]/,'')}
+ _! filtered_election(raw_votes(@date), @seats, candidates)
+end
+
+# main output
+_html do
+ _head_ do
+ _title 'STV Explorer'
+ _style! %{
+ h1 {font-family: sans-serif; font-weight: normal}
+ select {display: block; margin: 0 0 1em 1em; font-size: 140%}
+ label div {display: inline-block; min-width: 12em; font-size: x-large}
+ label div {-webkit-transition: background-color 1s}
+ label div {-moz-transition: background-color 1s}
+ label {float: left; clear: both}
+ label[for=seats] {display: inline; line-height: 500%}
+ p, input[type=checkbox] {margin-left: 1em}
+ p, input[type=submit] {display: block; clear: both}
+ .elected {background: #0F0}
+ .not-elected {background: #F00}
+ .none {background: yellow}
+ }
+ _script src: '../jquery-min.js'
+ end
+
+ _body? do
+ _h1_ 'STV Explorer'
+
+ nominees = Hash[File.read(ini(raw_votes(@date))).scan(/^\w:\s*(.*)/).
+ flatten.map {|name| [name.gsub(/[^[[:alnum:]]]/,''), name]}]
+ candidates = params.keys & nominees.keys
+ candidates = nominees.keys if candidates.empty? or @reset
+
+ @seats ||= '9'
+ results = filtered_election(raw_votes(@date), @seats, candidates)
+
+ # form of nominees and seats
+ _form method: 'post', id: 'vote' do
+ _select name: 'date' do
+ Dir["#{MEETINGS}/*/raw_board_votes.txt"].sort.reverse.each do |votes|
+ next unless File.exist? ini(votes)
+ date = votes[/(\d+)\/raw_board_votes.txt$/,1]
+ display = date.sub(/(\d{4})(\d\d)(\d\d)/,'\1-\2-\3')
+ _option display, value: date, selected: (votes == raw_votes(@date))
+ end
+ end
+
+ nominees.sort.each do |id, name|
+ _label_ id: id do
+ _input type: 'checkbox', name: id, checked: candidates.include?(id)
+ _div name, class: results[id]
+ end
+ end
+
+ _label_ for: 'seats' do
+ _span 'seats:'
+ _input name: 'seats', id: 'seats', value: @seats, size: 2,
+ type: 'number', min: 1, max: nominees.length-1
+ end
+
+ _input type: 'submit', value: 'submit', name: 'submit'
+ end
+
+ _p_ do
+ _a "Member's Meeting Information",
+ href: 'https://whimsy.apache.org/members/meeting'
+ end
+
+ _script %{
+ // submit form using XHR; update class for labels based on results
+ function refresh() {
+ $.post('', $('#vote').serialize(), function(results) {
+ for (var name in results) {
+ $('#'+name+' div').attr('class', results[name]);
+ }
+ }, 'json');
+ return false;
+ }
+
+ // On checkbox click, remove class from associated label & refresh
+ $(':checkbox').click(function() {
+ $('div', $(this).parent()).attr('class', 'none');
+ refresh();
+ });
+
+ // reset whenever the date changes
+ $('select').change(function() {
+ $('input[value=submit]').attr('name', 'reset');
+ $('input[value=submit]').click();
+ });
+
+ // If JS is enabled, we don't need a submit button
+ $('input[type=submit]').hide();
+
+ // Refresh on change in number of seats
+ $('#seats').on('input', function() {return refresh()});
+ }
+ end
+end
+
+__END__
+MEETINGS = '../Meetings'
diff --git a/www/members/whatif.cgi b/www/members/whatif.cgi
index c8e6fc99..b40a23e2 100755
--- a/www/members/whatif.cgi
+++ b/www/members/whatif.cgi
@@ -3,8 +3,16 @@ $LOAD_PATH.unshift '/srv/whimsy/lib'
require 'whimsy/asf/config'
require 'whimsy/asf/svn'
+require 'wunderbar'
MEETINGS = ASF::SVN['Meetings']
+# This is a hack:
+# STeVe has moved to Git, however whatif.py no longer works in that
environment due to changes in stv_tool.py
+# So for the time being, continue to use the old code in SVN
Dir.chdir ASF::SVN['steve']
-require "./whatif"
+# However, whatif.rb no longer works with the current version of Ruby
+# See: https://github.com/apache/whimsy/issues/257
+# The file below is a corrected copy
+#
+require '/srv/whimsy/tools/whatif'