diff --git a/www/form/condorcet.js b/www/form/condorcet.js index 69c5209a0..c32491045 100644 --- a/www/form/condorcet.js +++ b/www/form/condorcet.js @@ -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; diff --git a/www/form/inner.js b/www/form/inner.js index 1474b742d..eadfc68ce 100644 --- a/www/form/inner.js +++ b/www/form/inner.js @@ -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; }