linted and refactored

This commit is contained in:
zuzanna-maria 2023-03-22 19:12:34 +01:00
parent 005eed7d38
commit fcb49c3666
2 changed files with 170 additions and 155 deletions

View file

@ -1,14 +1,16 @@
define([], function () {
var Condorcet = {}
var Condorcet = {};
// Creates every possible combination pair of given options
var getPermutations = function(array, size) {
var result = [];
function p(t, i) {
if (t.length === size) {
result.push(t);
result.push(t.slice().reverse())
result.push(t.slice().reverse());
return;
}
if (i >= array.length) {
@ -18,118 +20,120 @@ define([], function () {
p(t, i + 1);
}
var result = [];
p([], 0);
return result;
}
};
Condorcet.showCondorcetWinner = function(_answers, opts, uid, form) {
Condorcet.showCondorcetWinner = function(_answers, opts, uid, form, optionArray, listOfLists) {
var comparePairs = function() {
var pairs = getPermutations(optionArray, 2)
var pairs = getPermutations(optionArray, 2);
var pairDict = {}
var pairDict = {};
pairs.forEach(function (pair) {
pairDict[pair] = 0
pairDict[pair] = 0;
listOfLists.forEach(function(optionList) {
if (optionList.indexOf(pair[0]) < optionList.indexOf(pair[1])) {
pairDict[pair] ++
pairDict[pair] ++;
}
})
})
});
});
pathDictionary = {}
var pathDictionary = {};
//Adds winner of each pairwise comparison to path
optionArray.forEach(function(option1) {
optionArray.forEach(function(option2){
if (option1 != option2) {
var key1 = [option1, option2].join()
var key2 = [option2, option1].join()
if (option1 !== option2) {
var key1 = [option1, option2].join();
var key2 = [option2, option1].join();
if (pairDict[key1] > pairDict[key2]) {
pathDictionary[key1] = pairDict[key1]
pathDictionary[key1] = pairDict[key1];
} else if (pairDict[key2] > pairDict[key1]) {
pathDictionary[key2] = pairDict[key2]
pathDictionary[key2] = pairDict[key2];
}
}
})
})
return pathDictionary
}
});
});
return pathDictionary;
};
var schulzeMethod = function(optionArray, listOfLists, _answers, uid) {
var schulzeMethod = function(optionArray) {
var findWeakestPath = function(optionArray) {
var pathDictionary = comparePairs(optionArray)
var pathDictionary = comparePairs(optionArray);
//Iterates through paths between two options comparing the weakest edge to current score
optionArray.forEach(function(option1) {
optionArray.forEach(function(option2) {
if (option1 != option2) {
if (option1 !== option2) {
optionArray.forEach(function(option3){
if (option1 != option3 && option2 != option3) {
var key1 = [option2, option3].join()
var key2 = [option2, option1].join()
var key3 = [option1, option3].join()
if (option1 !== option3 && option2 !== option3) {
var key1 = [option2, option3].join();
var key2 = [option2, option1].join();
var key3 = [option1, option3].join();
var score;
if (pathDictionary[key1] === undefined) {
var score = 0
score = 0;
} else {
var score = pathDictionary[key1]
score = pathDictionary[key1];
}
var path1;
if (pathDictionary[key2] !== undefined) {
var path1 = pathDictionary[key2]
path1 = pathDictionary[key2];
} else {
var path1 = 0
path1 = 0;
}
var path2;
if (pathDictionary[key3]) {
var path2 = pathDictionary[key3]
path2 = pathDictionary[key3];
} else {
var path2 = 0
path2 = 0;
}
var weakestPath = Math.min(path1, path2)
var weakestPath = Math.min(path1, path2);
if (weakestPath > score) {
pathDictionary[key1] = weakestPath
pathDictionary[key1] = weakestPath;
}
}
})
});
}
})
})
return pathDictionary
}
});
});
return pathDictionary;
};
var calculateWinner = function(_answers, uid) {
var calculateWinner = function() {
var pathDictionary = findWeakestPath(optionArray)
var pathDictionary = findWeakestPath(optionArray);
//Calculate scores for each option and select winner
winningMatches = {}
var winningMatches = {};
optionArray.forEach(function(option){
winningMatches[option] = 0
})
winningMatches[option] = 0;
});
Object.keys(pathDictionary).forEach(function(pair) {
option1 = pair.split(',')[0]
winningMatches[option1] ++
})
var option1 = pair.split(',')[0];
winningMatches[option1] ++;
});
rankedResults = {}
var rankedResults = {};
Object.keys(winningMatches).forEach(function(option) {
if (Object.keys(rankedResults).includes(winningMatches[option].toString())) {
rankedResults[winningMatches[option]].push(option)
rankedResults[winningMatches[option]].push(option);
} else {
rankedResults[winningMatches[option]] = [option]
rankedResults[winningMatches[option]] = [option];
}
})
return [rankedResults, winningMatches]
}
return(calculateWinner(_answers, uid))
}
});
return [rankedResults, winningMatches];
};
return(calculateWinner());
};
var rankedPairsMethod = function (optionArray, listOfLists, _answers) {
var pairs = getPermutations(optionArray, 2)
var pairs = getPermutations(optionArray, 2);
var lockPairs = function() {
//'Locks' pairwise comparisons which do not create a beatpath cycle
var pathDictionary = comparePairs(listOfLists, pairs)
var pathDictionary = comparePairs(listOfLists, pairs);
var items = Object.keys(pathDictionary).map(function(key) {
return [key, pathDictionary[key]];
@ -139,37 +143,37 @@ define([], function () {
return second[1] - first[1];
});
list = [items[0][0]]
list2 = []
var list = [items[0][0]];
var list2 = [];
items.forEach(function(item){
opts = item[0].split(',')
opts = item[0].split(',');
if (!list2.includes(opts[0])) {
list2.push(opts[1])
list2.push(opts[1]);
if (!list.includes(item[0])) {
list.push(item[0])
list.push(item[0]);
}
}
})
});
return list
return list;
}
};
var rankPairs = function(optionArray, listOfLists, _answers) {
//Ranks locked pairs
var list = lockPairs(optionArray, listOfLists, _answers)
var list = lockPairs(optionArray, listOfLists, _answers);
rankDict = {}
var rankDict = {};
optionArray.forEach(function(o){
rankDict[o] = 0
rankDict[o] = 0;
list.forEach(function(pair) {
if (o == pair.split(',')[1]) {
rankDict[o] --
} else if (o == pair.split(',')[0]) {
rankDict[o] ++
if (o === pair.split(',')[1]) {
rankDict[o] --;
} else if (o === pair.split(',')[0]) {
rankDict[o] ++;
}
})
})
});
});
var rankedItems = Object.keys(rankDict).map(function(key) {
return [key, rankDict[key]];
@ -179,39 +183,39 @@ define([], function () {
return second[1] - first[1];
});
finalRank = []
var finalRank = [];
rankedItems.forEach(function(i){
finalRank.push(i[0])
})
sortedRankDict = {}
finalRank.push(i[0]);
});
var sortedRankDict = {};
finalRank.forEach(function(opt){
sortedRankDict[opt] = rankDict[opt]
})
sortedRankDict[opt] = rankDict[opt];
});
return [finalRank, sortedRankDict]
}
return [finalRank, sortedRankDict];
};
var condorcetWinner = rankPairs(optionArray, listOfLists, _answers)
return condorcetWinner
}
var condorcetWinner = rankPairs(optionArray, listOfLists, _answers);
return condorcetWinner;
};
var pickMethod = function(optionArray, listOfLists, _answers, uid){
var condorcetWinner = []
var schulzeWinner = schulzeMethod(optionArray, listOfLists, _answers, uid)
var rankedPairWinner = rankedPairsMethod(optionArray, listOfLists)
var method = form[uid].condorcet["method"]
if (method == "schulze") {
condorcetWinner[0] = schulzeWinner
condorcetWinner[1] = rankedPairWinner
} else if (method == "ranked") {
condorcetWinner[0] = rankedPairWinner
condorcetWinner[1] = schulzeWinner
var condorcetWinner = [];
var schulzeWinner = schulzeMethod(optionArray, listOfLists, _answers, uid);
var rankedPairWinner = rankedPairsMethod(optionArray, listOfLists);
var method = form[uid].condorcet["method"];
if (method === "schulze") {
condorcetWinner[0] = schulzeWinner;
condorcetWinner[1] = rankedPairWinner;
} else if (method === "ranked") {
condorcetWinner[0] = rankedPairWinner;
condorcetWinner[1] = schulzeWinner;
}
return condorcetWinner
}
return pickMethod(optionArray, listOfLists, _answers, uid)
}
return condorcetWinner;
};
return pickMethod(optionArray, listOfLists, _answers, uid);
};
return Condorcet
})
return Condorcet;
});

View file

@ -72,9 +72,20 @@ define([
ChainPad,
Share, Access, Properties,
Flatpickr,
Sortable,
Sortable
)
{
{
Messages.form_chooseCondorcetMethod = "Choose Condorcet winner using: "; //XXX;
Messages.form_chooseCondorcetDisplay = "Condorcet winner display view: ";
Messages.form_schulzeMethod = "Schulze method";
Messages.form_rankedPairs = "Ranked pairs method";
Messages.form_condorcetBasicDisplayButton = "Basic display";
Messages.form_condorcetExtendedDisplayButton = "Extended display";
Messages.form_showCondorcetWinner = "The Condorcet winner is: ";
Messages.form_condorcetExtendedDisplay = "Number of matches won by each candidate: ";
Messages.form_showAlternateWinnerButton = "Show alternate method winner";
Messages.form_showAlternateWinner = "The alternate method Condorcet winner is: ";
var APP = window.APP = {
blocks: {}
};
@ -2435,20 +2446,18 @@ define([
showCondorcetWinner: function(answers, opts, uid, form) {
var showCondorcetWinner = {}
var _answers = parseAnswers(answers);
optionArray = []
var optionArray = [];
opts.values.forEach(function (option) {
optionArray.push(option.v)
})
optionArray.push(option.v);
});
listOfLists = []
var listOfLists = [];
Object.keys(_answers).forEach(function(a) {
listOfLists.push(_answers[a].msg[uid])
})
return Condorcet.showCondorcetWinner(_answers, opts, uid, form)
listOfLists.push(_answers[a].msg[uid]);
});
return Condorcet.showCondorcetWinner(_answers, opts, uid, form, optionArray, listOfLists);
},
icon: h('i.cptools.cptools-form-list-ordered')
@ -2808,48 +2817,50 @@ define([
});
let condorcetWinnerDiv = h('div')
let condorcetWinnerDiv = h('div');
if (type == "sort") {
condorcetWinnerDiv = h('div.cp-form-block', {style: { margin: 100, padding:100 }})
if (form[uid].condorcet["method"] == 'schulze') {
var condorcetResults = model.showCondorcetWinner(answers, block.opts, uid, form)[0][0]
var condorcetWinner = condorcetResults[Object.keys(condorcetResults).length - 1]
if (type === "sort") {
condorcetWinnerDiv = h('div.cp-form-block', {style: { margin: 100, padding:100 }});
var rankedResults = model.showCondorcetWinner(answers, block.opts, uid, form)[0][0];
var condorcetWinner;
if (form[uid].condorcet["method"] === 'schulze') {
condorcetWinner = rankedResults[Object.keys(rankedResults).length - 1];
condorcetWinner.forEach(function(option) {
condorcetWinnerDiv.append(h('div', Messages.form_showCondorcetWinner, option, {style: { margin: '10px'}}))
})
condorcetWinnerDiv.append(h('div', Messages.form_showCondorcetWinner, option, {style: { margin: '10px'}}));
});
} else {
var condorcetResults = model.showCondorcetWinner(answers, block.opts, uid, form)[0][0]
var condorcetWinner = condorcetResults[0]
condorcetWinnerDiv.append(h('div', Messages.form_showCondorcetWinner, condorcetWinner, {style: { margin: '10px'}}))
condorcetWinner = rankedResults[0];
condorcetWinnerDiv.append(h('div', Messages.form_showCondorcetWinner, condorcetWinner, {style: { margin: '10px'}}));
}
if (form[uid].condorcet["display"] == 'extended') {
if (form[uid].condorcet["method"] == 'schulze') {
var results = Object.keys(rankedResults).reverse().map(function(result) {
if (form[uid].condorcet["display"] === 'extended') {
var sortedRankDict = model.showCondorcetWinner(answers, block.opts, uid, form)[0][1];
var alternateWinner;
var results;
if (form[uid].condorcet["method"] === 'schulze') {
results = Object.keys(rankedResults).reverse().map(function(result) {
return rankedResults[result] + ' : ' + result;
});
var alternateWinner = model.showCondorcetWinner(answers, block.opts, uid, form)[1][0][0]
alternateWinner = model.showCondorcetWinner(answers, block.opts, uid, form)[1][0][0];
} else {
var results = Object.keys(sortedRankDict).map(function(result) {
results = Object.keys(sortedRankDict).map(function(result) {
return result + ' : ' + sortedRankDict[result];
});
var alternateWinner = model.showCondorcetWinner(answers, block.opts, uid, form)[1][0][model.showCondorcetWinner(answers, block.opts, uid, form)[0][0].length - 1]
alternateWinner = model.showCondorcetWinner(answers, block.opts, uid, form)[1][0][model.showCondorcetWinner(answers, block.opts, uid, form)[0][0].length - 1];
}
condorcetWinnerDiv.append(h('div', Messages.form_condorcetExtendedDisplay, results.join(', '), {style: { margin: '10px'}}))
condorcetWinnerDiv.append(h('div', Messages.form_condorcetExtendedDisplay, results.join(', '), {style: { margin: '10px'}}));
var showAlternateWinnerButton = h('button.btn.btn-secondary', Messages.form_showAlternateWinnerButton, {style: { margin: '10px'}})
condorcetWinnerDiv.append(h('div', showAlternateWinnerButton))
var showAlternateWinnerButton = h('button.btn.btn-secondary', Messages.form_showAlternateWinnerButton, {style: { margin: '10px'}});
condorcetWinnerDiv.append(h('div', showAlternateWinnerButton));
$(showAlternateWinnerButton).click(function() {
if ($(condorcetWinnerDiv).children().length < 4) {
condorcetWinnerDiv.append(h('div', Messages.form_showAlternateWinner, alternateWinner, {style: { margin: '10px'}}))
condorcetWinnerDiv.append(h('div', Messages.form_showAlternateWinner, alternateWinner, {style: { margin: '10px'}}));
}
})
});
}
}
@ -3734,38 +3745,38 @@ define([
uid: uid,
tmp: temp && temp[uid]
});
var chooseCondorcetDiv = h('div')
if (type == "sort") {
var schulzeButton = h('button.btn.btn-secondary', Messages.form_schulzeMethod)
var rankedPairButton = h('button.btn.btn-secondary', Messages.form_rankedPairs)
var chooseCondorcetDiv = h('div');
if (type === "sort") {
var schulzeButton = h('button.btn.btn-secondary', Messages.form_schulzeMethod);
var rankedPairButton = h('button.btn.btn-secondary', Messages.form_rankedPairs);
var chooseCondorcetMethod = h('div',
Messages.form_chooseCondorcetMethod,
schulzeButton, ' ',
rankedPairButton,
{style: { margin: '10px'}}
)
var basicDisplayButton = h('button.btn.btn-secondary', Messages.form_condorcetBasicDisplayButton)
var extendedDisplayButton = h('button.btn.btn-secondary', Messages.form_condorcetExtendedDisplayButton,)
);
var basicDisplayButton = h('button.btn.btn-secondary', Messages.form_condorcetBasicDisplayButton);
var extendedDisplayButton = h('button.btn.btn-secondary', Messages.form_condorcetExtendedDisplayButton);
var chooseCondorcetDisplay = h('div',
Messages.form_chooseCondorcetDisplay,
basicDisplayButton, ' ',
extendedDisplayButton,
{style: { margin: '10px'}}
)
chooseCondorcetDiv.append(chooseCondorcetMethod, chooseCondorcetDisplay)
form[uid].condorcet = {method: 'schulze', display: 'basic'}
);
chooseCondorcetDiv.append(chooseCondorcetMethod, chooseCondorcetDisplay);
form[uid].condorcet = {method: 'schulze', display: 'basic'};
$(schulzeButton).click(function() {
form[uid].condorcet["method"] = 'schulze'
})
form[uid].condorcet["method"] = 'schulze';
});
$(rankedPairButton).click(function() {
form[uid].condorcet["method"] = 'ranked'
})
form[uid].condorcet["method"] = 'ranked';
});
$(basicDisplayButton).click(function() {
form[uid].condorcet["display"] = 'basic'
})
form[uid].condorcet["display"] = 'basic';
});
$(extendedDisplayButton).click(function() {
form[uid].condorcet["display"] = 'extended'
})
form[uid].condorcet["display"] = 'extended';
});
}
if (!data) { return; }
data.uid = uid;