User:Pathoschild/2009 steward election statistics

This page statistically summarizes the 2009 steward elections. See also a summary of the 2009 confirmations, and the collected statistics page.

Table edit

Unique participants: 1116.
Last update: 2009-02-22 01:02 (UTC)

candidate support ratio oppose reasons result
Meno25 0.963,  96.3% (157/163) elected
Erwin 0.96,  96% (192/200) elected
Kylu 0.954,  95.4% (207/217) elected
Laaknor 0.944,  94.4% (119/126) elected
Mike.lifeguard 0.884,  88.4% (258/292) elected
Leinad 0.868,  86.8% (138/159) inexperience. elected
Dorgan 0.844,  84.4% (141/167) inexperience. elected
Alexanderps 0.817,  81.7% (125/153) too much access, allegations of canvassing and misuse of checkuser tool. elected
Mardetanha 0.813,  81.3% (217/267) disputes on fawiki, fear that Iranian government will gain his access under torture. elected
putnik 0.792,  79.2% (152/192) inexperience, unanswered questions, dispute on ruwiki. failed
Avraham 0.785,  78.5% (150/191) inexperience, limited language skills. failed
Fabexplosive 0.781,  78.1% (114/146) dispute on lmowiki, allegedly executes tasks without understanding them, unanswered questions (later answered). failed
Jredmond 0.759,  75.9% (66/87) inexperience, too much access, unanswered questions (later answered). failed
PhiLiP 0.71,  71% (66/93) inexperience, copyright issues with uploads, fear that Chinese government will gain his access under torture. failed
SpeedyGonsales 0.696,  69.6% (87/125) inexperience, misunderstanding of steward role, disputes on hrwiki. failed
Mywood 0.671,  67.1% (55/82) inexperience, copyright issues with uploads. failed
EVula 0.546,  54.6% (77/141) inexperience, too much access, limited language skills, appearance of incivility. failed
avjoska 0.4,  40% (38/95) inexperience, intent of inactivity as a steward. failed
Fadesga 0.3,  30% (21/70) inexperience, no steward goals, unanswered questions. failed
Al Lemos 0.255,  25.5% (35/137) inexperience, misunderstanding of steward role. failed
Pasquale 0.19,  19% (12/63) inexperience, misunderstanding of steward role, unanswered questions, little activity. failed
Apteva 0.016,  1.6% (2/124) inexperience, prior block, lack of steward goals, misunderstanding of steward role, little activity. failed
Loco085 0.646,  64.6% (42/65) inexperience, unanswered questions. withdrawn
Cometstyles 0.598,  59.8% (76/127) alleged abuse of OTRS access, checkuser requests with insufficient reason. withdrawn
Orderinchaos 0.265,  26.5% (13/49) inexperience, limited language skills. withdrawn
Gutza 0.193,  19.3% (11/57) intent of inactivity as a steward, misunderstanding of steward role, unanswered questions. withdrawn
Chase me ladies, I'm the Cavalry 0.000,   disqualified; not identified. disqualified
Drakesketchit 0.000,   disqualified; not identified. disqualified
Fipplet 0.000,   disqualified; not identified. disqualified
Jagwar 0.000,   disqualified; not identified. disqualified
Wykypydya 0.000,   disqualified; not identified, not linked to an account meeting account requirements. disqualified

Update script edit

This table can be updated using the following quick-and-dirty script while editing this page; this might take several seconds, depending on your connection speed, due to the size of the page. (Anyone wishing to update it automatically with another language is free to do so.)

/*********************
** 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_2009/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();