Improve performances with form Condorcet methods

This commit is contained in:
yflory 2023-04-26 12:55:02 +02:00
parent 8547219d35
commit d2854bad0c
2 changed files with 122 additions and 131 deletions

View file

@ -24,12 +24,8 @@ define([], function () {
return result;
};
Condorcet.showCondorcetWinner = function(_answers, uid, form, optionArray, listOfLists) {
// _answers not needed
// uid and form can be replaced by "method"
// listOfLists represents responses
Condorcet.showCondorcetWinner = function (method, optionArray, listOfLists) {
// For each pair, get the stronger direction (A to B or B to A) and its weight
var comparePairs = function () {
var pairs = getPermutations(optionArray, 2);
var pairDict = {};
@ -38,12 +34,15 @@ define([], function () {
listOfLists.forEach(function(optionList) {
var idx1 = optionList.indexOf(pair[0]);
var idx2 = optionList.indexOf(pair[1]);
// Put missing options as last in the array
if (idx1 === -1) { idx1 = Infinity; }
if (idx2 === -1) { idx2 = Infinity; }
if (idx1 < idx2) { pairDict[pair] ++; }
});
});
/*
// XXX to test
var pathDictionary = {};
//Adds winner of each pairwise comparison to path
pairs.forEach(function (pair) {
@ -54,10 +53,9 @@ define([], function () {
} else if (pairDict[key2] > pairDict[key1]) {
pathDictionary[key2] = pairDict[key2] - pairDict[key1];
}
});
*/
/*
var pathDictionary = {};
//Adds winner of each pairwise comparison to path
optionArray.forEach(function(option1) {
@ -75,7 +73,6 @@ define([], function () {
}
});
});
*/
return pathDictionary;
};
@ -152,7 +149,7 @@ define([], function () {
});
var rankedResults = {};
Object.keys(winningMatches).forEach(function(option) {
if (Object.keys(rankedResults).includes(winningMatches[option].toString())) {
if (rankedResults[winningMatches[option]]) {
rankedResults[winningMatches[option]].push(option);
} else {
rankedResults[winningMatches[option]] = [option];
@ -187,9 +184,7 @@ define([], function () {
});
var sortedRankedResults = [];
Object.keys(rankedResults).map(Number).sort(function(a, b) {
return a - b;
}).forEach(function(score) {
Object.keys(rankedResults).map(Number).sort().forEach(function(score) {
sortedRankedResults.push([score, rankedResults[score]]);
});
@ -207,12 +202,12 @@ define([], function () {
return(calculateWinner());
};
var rankedPairsMethod = function (optionArray, listOfLists) {
var rankedPairsMethod = function (optionArray) {
var pairs = getPermutations(optionArray, 2);
//'Locks' pairwise comparisons which do not create a beatpath cycle
var pathDictionary = comparePairs(listOfLists, pairs);
var pathDictionary = comparePairs();
var items = Object.keys(pathDictionary).map(function(key) {
return [key, pathDictionary[key]];
@ -229,9 +224,7 @@ define([], function () {
});
var sortedArray = [];
Object.keys(itemsDict).map(Number).sort(function(a, b) {
return a - b;
}).forEach(function(score) {
Object.keys(itemsDict).map(Number).sort().forEach(function(score) {
sortedArray.push([score, itemsDict[score]]);
});
@ -268,7 +261,7 @@ define([], function () {
var rankedResults = {};
Object.keys(rankingDict).forEach(function(option) {
if (Object.keys(rankedResults).includes(rankingDict[option].toString())) {
if (rankedResults[rankingDict[option]]) {
rankedResults[rankingDict[option]].push(option);
} else {
rankedResults[rankingDict[option]] = [option];
@ -281,11 +274,10 @@ define([], function () {
var finalsortedItems = {};
Object.values(rankedKeys).forEach(function(value){
if (Object.keys(finalsortedItems).includes(value[1].toString())) {
if (finalsortedItems[value[1]]) {
finalsortedItems[value[1]].push(value[0]);
} else {
finalsortedItems[value[1]] = [];
finalsortedItems[value[1]].push(value[0]);
finalsortedItems[value[1]] = [value[0]];
}
});
@ -326,28 +318,21 @@ define([], function () {
}
var sortedRankedResults = [];
Object.keys(rankedResults).map(Number).sort(function(a, b) {
return a - b;
}).forEach(function(score) {
Object.keys(rankedResults).map(Number).sort().forEach(function(score) {
sortedRankedResults.push([score, rankedResults[score]]);
});
return [winner, sortedRankedResults];
};
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].condorcetmethod;
var pickMethod = function (optionArray){
if (method === "schulze") {
condorcetWinner = schulzeWinner;
return schulzeMethod(optionArray);
} else if (method === "ranked") {
condorcetWinner = rankedPairWinner;
return rankedPairsMethod(optionArray);
}
return condorcetWinner;
};
return pickMethod(optionArray, listOfLists, _answers, uid);
return pickMethod(optionArray);
};
return Condorcet;

View file

@ -2889,7 +2889,7 @@ define([
});
var showCondorcetWinner = function(answers, opts, uid, form) {
var showCondorcetWinner = function(answers, opts, condorcetMethod, uid) {
var _answers = parseAnswers(answers);
@ -2905,25 +2905,25 @@ define([
}
});
try {
if (Array.isArray(Object.keys(listOfLists))) {
console.error(_answers, uid, form, optionArray, listOfLists);
return Condorcet.showCondorcetWinner(_answers, uid, form, optionArray, listOfLists);
if (listOfLists.length) {
return Condorcet.showCondorcetWinner(condorcetMethod, optionArray, listOfLists);
}
} catch (e) {
console.error(e);
return;}
return [];
}
};
var condorcetWinnerDiv = h('div.cp-form-block-content');
form[uid].condorcetmethod = 'schulze';
var condorcetMethod = 'schulze';
try {
if (type === "sort" && summary && showCondorcetWinner(answers, block.opts, uid, form)[0] && showCondorcetWinner(answers, block.opts, uid, form)[1]) {
if (type === "sort" && summary) {
var calculateCondorcet = function() {
var condorcetResults = h('span');
var condorcetWinner = showCondorcetWinner(answers, block.opts, uid, form)[0];
var rankedResults = showCondorcetWinner(answers, block.opts, uid, form)[1];
var c = showCondorcetWinner(answers, block.opts, condorcetMethod, uid);
var condorcetWinner = c[0];
var rankedResults = c[1];
if (!condorcetWinner || !condorcetResults) { return; }
if (condorcetWinner.length > 1) {
condorcetResults.append(h('span', condorcetWinner.join(', ')));
} else if (condorcetWinner.length === 1 ) {
@ -2941,17 +2941,23 @@ define([
return [condorcetResults, detailedResults];
};
var dropdownOpts = [Messages.form_condorcetSchulze, Messages.form_condorcetRanked];
var dropdownOpts = [{
key: 'schulze',
str: Messages.form_condorcetSchulze
}, {
key: 'ranked',
str: Messages.form_condorcetRanked
}];
var options = dropdownOpts.map(function (t) {
return {
tag: 'a',
attributes: {
'class': 'cp-form-type-value',
'data-value': t,
'data-value': t.key,
'href': '#',
},
content: t
content: t.str
};
});
var dropdownConfig = {
@ -2963,52 +2969,52 @@ define([
};
var typeSelect = UIElements.createDropdown(dropdownConfig);
typeSelect.setValue(dropdownOpts[0]);
var methodOptions = {0: 'schulze', 1: 'ranked'};
var optionIndex = dropdownOpts.indexOf(typeSelect.getValue());
form[uid].condorcetmethod = methodOptions[optionIndex];
typeSelect.setValue(condorcetMethod);
var method = h('div.cp-dropdown-container', typeSelect[0]);
var evOnSave = Util.mkEvent();
typeSelect.onChange.reg(evOnSave.fire);
var $typeSelect = $(typeSelect);
var $selector = $typeSelect.find('a');
var condorcetWinner = h('span', { id: 'cW'}, calculateCondorcet()[0]);
condorcetWinnerDiv = h('div.cp-form-edit-type');
var detailsContainer, condorcetWinner;
var detailsDiv = h('details', h('summary', Messages.form_showDetails), {id: 'dD'}, Messages.form_condorcetExtendedDisplay, h('div', calculateCondorcet()[1].join(', ')));
var condorcetResult = calculateCondorcet();
if (condorcetResult) {
condorcetWinner = h('span#cp-condorcet-winner', condorcetResult[0]);
detailsContainer = h('details#cp-condorcet-details', [
h('summary', Messages.form_showDetails),
Messages.form_condorcetExtendedDisplay,
h('div', condorcetResult[1].join(', '))
]);
}
$selector.click(function () {
optionIndex = dropdownOpts.indexOf($(this).attr('data-value'));
form[uid].condorcetmethod = methodOptions[optionIndex];
try {
$('#cW').replaceWith(h('span', { id: 'cW'}, calculateCondorcet()[0]));
} catch (err) {
console.error(err);
}
try {
$('#dD').replaceWith(h('details', h('summary', Messages.form_showDetails), {id: 'dD'}, Messages.form_condorcetExtendedDisplay, h('div', calculateCondorcet()[1].join(', '))));
} catch (err) {
console.error(err);
condorcetMethod = typeSelect.getValue();
var condorcetResult = calculateCondorcet();
if (!condorcetResult) {
$('#cp-condorcet-winner').empty();
$('#cp-condorcet-details').empty();
return;
}
$('#cp-condorcet-winner').replaceWith(h('span#cp-condorcet-winner', condorcetResult[0]));
$('#cp-condorcet-details').replaceWith(h('details#cp-condorcet-details', [
h('summary', Messages.form_showDetails),
Messages.form_condorcetExtendedDisplay,
h('div', condorcetResult[1].join(', '))
]));
});
condorcetWinnerDiv.append(h('div.cp-form-result-details', [
h('span', Messages.form_showCondorcetMethod),
method,
h('span', Messages.form_showCondorcetWinner, condorcetWinner),
detailsDiv
detailsContainer
]));
}
} catch (err) {
console.error(err);
return;
}