User:Jamesofur/2010SEstatupdate.js
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
- Opera: Press Ctrl-F5.
<source lang="javascript">
/*********************
** Functions
*********************/
// report to box
function ses_report(text) {
$('stewiestats').adopt(document.createTextNode(text));
}
/*********************
** Initialize
*********************/
function ses_initialize() {
// display status box
if(!document.getElementById('stewiestats')) {
// create box
var box = document.createElement('pre');
box.setAttribute('id', 'stewiestats');
box.setAttribute('style', 'margin:1em; padding:0.5em; border:1px solid #C00;');
box.appendChild(document.createTextNode('Loading required framework...\n'));
editbox.parentNode.insertBefore(box, editbox.parentNode.firstChild);
// jump to box
window.location.hash = "#stewiestats";
}
// wait until WikiMooTools loaded
if(!window.$chk) {
setTimeout('init_update()', 500);
return;
}
// reset box
$('stewiestats').set({'text':'Loading required framework...\n'});
// start script
ses_fetch_page();
}
/*********************
** Fetch page text
*********************/
function ses_fetch_page() {
/* update status box */
ses_report('Fetching elections page...\n');
/* grab page text */
var request = new Request({
url:'http://meta.wikimedia.org/wiki/Stewards/elections_2010/votes?action=render',
method: 'GET',
onSuccess:ses_parse_page,
onFailure: function(xhr) {
ses_report('AJAX error while fetching elections page: ' + xhr.status + ' (' + xhr.statusText + ')\n');
}
}).send();
}
/*********************
** Count unique participants
*********************/
function ses_count_participants(text) {
ses_report('Counting unique participants... ');
var links = text.match(/title="User:[^\/"]+/ig);
var names = {};
var count = 0;
if(links) {
for(var i=0, len=links.length; i<len; i++) {
var name = links[i].match(/User:(.+)/)[1];
if(!names[name]) {
names[name] = 1;
count++;
}
}
}
ses_report(count + '\n');
editbox.value = editbox.value.replace(/(<span id="ses_count">).*?(<\/span>)/, '$1' + count + '$2');
}
/*********************
** Extract data from page
*********************/
function ses_parse_page(text, xml) {
/* update status box */
ses_report('Extracting data...\n');
// strip out cruft
text = text.replace(/^[\s\S]+?<table id="toc"[\s\S]+?<\/table>/, ''); // introduction, TOC, etc
text = text.replace(/^(<h2.+?<\/h2>)[\s\S]+?<h3[\s\S]+?(<h3)/mg, '$1\n$2'); // statements, 'questions' header
text = text.replace(/<ul>[\s\S]+?<\/ul>/g, ''); // threaded bullets
text = text.replace(/^(<(?:h2|h3|li).+\n*)|^.+\n*/mg, '$1'); // everything else except headers and list items
text = text.replace(/^<h(\d)>.*<span class="mw-headline">.*?>\s*([^<>]+?)\s*<.+<\/h\1>/mg, '<h$1>$2</h$1>'); // simplify headers
// count participants
ses_count_participants(text);
// data
var names = []; // all candidate names
var votes = []; // all section titles
var counts = {}; // vote counts per section per candidate
var name = ''; // current candidate name
var vote = ''; // current section ('Yes', 'No', 'Neutral')
// parse text
text = text.split('\n');
var len = text.length;
var line;
for(var i=0; i<len; i++) {
line = text[i];
// li: new vote
if(line.match('<li')) {
counts[name][vote]++;
}
// h3: new vote section
else if(line.match('<h3')) {
vote = line.match(/<h3>(.+)<\/h3>/)[1];
votes.push(vote);
counts[name][vote] = 0;
}
// h2: new candidate
else if(line.match('<h2')) {
name = line.match(/<h2>(.+)<\/h2>/)[1];
names.push(name);
counts[name] = {};
}
}
// update table
ses_gen_table(names, votes, counts);
}
/*********************
** Return formatted date
*********************/
function ses_get_date() {
// zero pad
function zero_pad(num) {
if(num<10)
num = '0' + num;
return num;
}
// generate string
var d = new Date();
var str = d.getUTCFullYear() + '-' + zero_pad(d.getUTCMonth()+1) + '-' + zero_pad(d.getUTCDate()) + ' '
+ zero_pad(d.getUTCHours()) + ':' + zero_pad(d.getUTCMinutes()) + ' (UTC)';
return str;
}
/*********************
** Update table
*********************/
function ses_gen_table(names, votes, counts) {
/* update status box */
ses_report('Generating updated table...\n');
/***************
** Variables
***************/
// constants
var len = names.length; // number of candidates
var yes = votes[0]; // title of support headers
var no = votes[1]; // title of oppose headers
// data
var rows = {}; // all template texts
var ratios = {}; // all support ratios
var sorted = []; // candidate names, sorted by ratio
// other
var text = editbox.value;
/***************
** Regex to match candidate row template
***************/
function reg_candidate_template(name) {
return new RegExp('{{user[^}]+name *= *' + name + '[^}]+}}', 'mi');
}
/***************
** Fetch & update rows
***************/
for(var i=0; i<len; i++) {
// grab text
var name = names[i];
var row = text.match(reg_candidate_template(name)).toString();
// update
row = row.replace(/(support *=).*/, '$1 ' + counts[name][yes]);
row = row.replace(/(oppose *=).*/, '$1 ' + counts[name][no]);
// store
rows[name] = row;
ratios[name] = counts[name][yes]/(counts[name][yes]+counts[name][no]);
}
/***************
** Sort rows
***************/
for(var i=0; i<len; i++) {
var name = names[i];
var ratio = counts[name][yes]/(counts[name][yes]+counts[name][no]);
// insert into sorted position
for(var x=0; x<=sorted.length; x++) {
// end of array, just stick it in
if(x==sorted.length) {
sorted.push(name);
break;
}
else if(ratios[name]>ratios[sorted[x]]) {
sorted.splice(x, 0, name);
break;
}
}
}
/***************
** Update text
***************/
// date
text = text.replace(/(<span id="ses_date">).*?(<\/span>)/, '$1' + ses_get_date() + '$2');
// rows
var str = '';
for(var i=0; i<len; i++)
str += rows[sorted[i]] + '\n';
text = text.replace(/(<!--ses-start-->)[\s\S]+?(<!--ses-end-->)/i, '$1\n' + str + '$2');
// text
editbox.value = text;
/* update status box */
ses_report('Done.');
}
ses_initialize();
</source>