Improve performances with form Condorcet methods
This commit is contained in:
parent
8547219d35
commit
d2854bad0c
2 changed files with 122 additions and 131 deletions
|
@ -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,11 +149,11 @@ define([], function () {
|
|||
});
|
||||
var rankedResults = {};
|
||||
Object.keys(winningMatches).forEach(function(option) {
|
||||
if (Object.keys(rankedResults).includes(winningMatches[option].toString())) {
|
||||
rankedResults[winningMatches[option]].push(option);
|
||||
} else {
|
||||
rankedResults[winningMatches[option]] = [option];
|
||||
}
|
||||
if (rankedResults[winningMatches[option]]) {
|
||||
rankedResults[winningMatches[option]].push(option);
|
||||
} else {
|
||||
rankedResults[winningMatches[option]] = [option];
|
||||
}
|
||||
});
|
||||
|
||||
var losing = [];
|
||||
|
@ -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,11 +261,11 @@ define([], function () {
|
|||
|
||||
var rankedResults = {};
|
||||
Object.keys(rankingDict).forEach(function(option) {
|
||||
if (Object.keys(rankedResults).includes(rankingDict[option].toString())) {
|
||||
rankedResults[rankingDict[option]].push(option);
|
||||
} else {
|
||||
rankedResults[rankingDict[option]] = [option];
|
||||
}
|
||||
if (rankedResults[rankingDict[option]]) {
|
||||
rankedResults[rankingDict[option]].push(option);
|
||||
} else {
|
||||
rankedResults[rankingDict[option]] = [option];
|
||||
}
|
||||
});
|
||||
|
||||
var rankedKeys = Object.keys(rankedResults).map(function(key) {
|
||||
|
@ -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;
|
||||
|
|
|
@ -2889,7 +2889,7 @@ define([
|
|||
});
|
||||
|
||||
|
||||
var showCondorcetWinner = function(answers, opts, uid, form) {
|
||||
var showCondorcetWinner = function(answers, opts, condorcetMethod, uid) {
|
||||
|
||||
var _answers = parseAnswers(answers);
|
||||
|
||||
|
@ -2905,110 +2905,116 @@ 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]) {
|
||||
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];
|
||||
if (condorcetWinner.length > 1) {
|
||||
condorcetResults.append(h('span', condorcetWinner.join(', ')));
|
||||
} else if (condorcetWinner.length === 1 ) {
|
||||
condorcetResults.append(h('span', condorcetWinner));
|
||||
if (type === "sort" && summary) {
|
||||
var calculateCondorcet = function() {
|
||||
var condorcetResults = h('span');
|
||||
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 ) {
|
||||
condorcetResults.append(h('span', condorcetWinner));
|
||||
} else {
|
||||
condorcetResults.append(h('span', Messages.form_noCondorcetWinner));
|
||||
}
|
||||
var detailedResults = rankedResults.reverse().map(function(result) {
|
||||
if (result.length > 1) {
|
||||
return result[1].join(', ') + ' : ' + result[0];
|
||||
} else {
|
||||
condorcetResults.append(h('span', Messages.form_noCondorcetWinner));
|
||||
}
|
||||
var detailedResults = rankedResults.reverse().map(function(result) {
|
||||
if (result.length > 1) {
|
||||
return result[1].join(', ') + ' : ' + result[0];
|
||||
} else {
|
||||
return result[1] + ' : ' + result[0];
|
||||
}
|
||||
});
|
||||
return [condorcetResults, detailedResults];
|
||||
};
|
||||
|
||||
var dropdownOpts = [Messages.form_condorcetSchulze, Messages.form_condorcetRanked];
|
||||
|
||||
var options = dropdownOpts.map(function (t) {
|
||||
return {
|
||||
tag: 'a',
|
||||
attributes: {
|
||||
'class': 'cp-form-type-value',
|
||||
'data-value': t,
|
||||
'href': '#',
|
||||
},
|
||||
content: t
|
||||
};
|
||||
});
|
||||
var dropdownConfig = {
|
||||
text: '', // Button initial text
|
||||
options: options,
|
||||
isSelect: true,
|
||||
caretDown: true,
|
||||
buttonCls: 'btn btn-secondary'
|
||||
};
|
||||
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];
|
||||
|
||||
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 detailsDiv = h('details', h('summary', Messages.form_showDetails), {id: 'dD'}, Messages.form_condorcetExtendedDisplay, h('div', calculateCondorcet()[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);
|
||||
return result[1] + ' : ' + result[0];
|
||||
}
|
||||
});
|
||||
return [condorcetResults, detailedResults];
|
||||
};
|
||||
|
||||
condorcetWinnerDiv.append(h('div.cp-form-result-details', [
|
||||
h('span', Messages.form_showCondorcetMethod),
|
||||
method,
|
||||
h('span', Messages.form_showCondorcetWinner, condorcetWinner),
|
||||
detailsDiv
|
||||
]));
|
||||
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.key,
|
||||
'href': '#',
|
||||
},
|
||||
content: t.str
|
||||
};
|
||||
});
|
||||
var dropdownConfig = {
|
||||
text: '', // Button initial text
|
||||
options: options,
|
||||
isSelect: true,
|
||||
caretDown: true,
|
||||
buttonCls: 'btn btn-secondary'
|
||||
};
|
||||
var typeSelect = UIElements.createDropdown(dropdownConfig);
|
||||
|
||||
typeSelect.setValue(condorcetMethod);
|
||||
|
||||
var method = h('div.cp-dropdown-container', typeSelect[0]);
|
||||
|
||||
var $typeSelect = $(typeSelect);
|
||||
var $selector = $typeSelect.find('a');
|
||||
|
||||
condorcetWinnerDiv = h('div.cp-form-edit-type');
|
||||
var detailsContainer, condorcetWinner;
|
||||
|
||||
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 () {
|
||||
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),
|
||||
detailsContainer
|
||||
]));
|
||||
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue