ballots = new WebResource("http://www.lively-web.org/core/media/cdg-logos/votes/").getSubElements(1).subDocuments.select(function (ea) {
return ea.getURL().filename().endsWith(".json")
&& !(ea.getURL().filename().startsWith("unknown_user"));
}).collect(function (ea) {return JSON.parse(ea.forceUncached().get().content)})
candidates = ballots.inject([], function(acc, ea) {return acc.concat(ea)}).uniq()
// See https://en.wikipedia.org/wiki/Schulze_method
d = candidates.collect(function(firstCandidate){
return candidates.collect(function(secondCandidate){
return ballots.select(function(ballot){
var firstRank = ballot.indexOf(firstCandidate),
secondRank = ballot.indexOf(secondCandidate);
if (firstRank < 0) firstRank = candidates.length;
if (secondRank < 0) secondRank = candidates.length;
return firstRank < secondRank;
}).length
})
})
p = []
for (var i = 0; i < candidates.length; i++) {
p[i] = [];
for (var j = 0; j < candidates.length; j++) {
p[i][j] = i == j ? null : d[i][j] > d[j][i] ? d[i][j] : 0
}
}
for (var i = 0; i < candidates.length; i++)
for (var j = 0; j < candidates.length; j++)
if (i != j)
for (var k = 0; k < candidates.length; k++)
if (i != k && j != k)
p[j][k] = Math.max( p[j][k], Math.min( p[j][i], p[i][k] ) )
// p[i][j] now contains the strength of the strongest beat path for each candidate
data = candidates.collect(function(candidate) {
var c = candidates.indexOf(candidate),
wins = 0;
for (var i = 0; i < candidates.length; i++)
if (i != c && p[c][i] > p[i][c]) wins++;
return {url: candidate, wins: wins};
})
var offset = 0;
$morph("Canvas").removeAllMorphs();
data.sortBy(function (ea) {
return ea.wins
}).reverse().map(function (ea, idx) {
var m = lively.morphic.Image.fromURL(ea.url);
var nE = m.getNativeExtent();
var fact = 200 / nE.y;
var scale = (ea.wins+10) / 100 * fact;
m.setScale(scale);
m.setPosition(pt(offset, 0));
offset += nE.x * scale + 15;
m.setToolTip(ea.wins);
return m
}).each(function (m) {
$morph("Canvas").addMorph(m);
})