Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- var ADDON_TITLE = 'SPSV Calculator';
- var NUM_KP_BALLOTS = 5;
- function onOpen(e) {
- FormApp.getUi()
- .createAddonMenu()
- .addItem('Run Election', 'runElection')
- .addToUi();
- }
- function onInstall(e) {
- onOpen(e);
- }
- function runElection() {
- var form = FormApp.getActiveForm();
- var responses = form.getResponses();
- if(responses.length == 0)
- return;
- formItems = form.getItems();
- num_candidates = 0;
- candidate_names = [];
- for(z = 0; z < formItems.length; z++)
- if(formItems[z].getType() == FormApp.ItemType.SCALE)
- {
- num_candidates++;
- candidate_names.push(formItems[z].getTitle());
- }
- rounds = []
- for (var i = 0; i < num_candidates; i++)
- rounds[i] = "Round " + (i + 1);
- var spreadsheet = SpreadsheetApp.create(form.getTitle() + " Results");
- url = spreadsheet.getUrl();
- SpreadsheetApp.openByUrl(url);
- result_sheet = spreadsheet.getActiveSheet();
- result_sheet.setName("Results");
- result_range = result_sheet.getDataRange();
- result_values = result_range.getValues();
- num_ballots = responses.length;
- // create empty score lists
- candidate_scores = [];
- for(c = 0; c < num_candidates; c++)
- {
- candidate_scores[c] = [];
- for(r = 0; r < num_candidates; r++)
- candidate_scores[c][r] = 0;
- }
- // perform the KP transform
- approval_ballots = [];
- for(a = 0; a < num_ballots; a++)
- {
- var response = responses[a];
- var score_ballot = [];
- for(z = 0; z < formItems.length; z++)
- if(formItems[z].getType() == FormApp.ItemType.SCALE)
- {
- var scoreResponse = response.getResponseForItem(formItems[z]);
- if (scoreResponse != null)
- score_ballot.push(parseInt(scoreResponse.getResponse()));
- else
- score_ballot.push(0);
- }
- for(b = 0; b < NUM_KP_BALLOTS; b++)
- {
- var approval_ballot = [];
- for(c = 0; c < num_candidates; c++)
- approval_ballot[c] = score_ballot[c] > b;
- approval_ballots[a * NUM_KP_BALLOTS + b] = approval_ballot;
- }
- }
- // create initial ballot weight list
- weights = [];
- for(k = 0; k < approval_ballots.length; k++)
- weights[k] = 1.0;
- // calculate scores and winners for each round
- elected_candidates = [];
- for(r = 0; r < num_candidates; r++)
- {
- // calculate scores
- for(c = 0; c < num_candidates; c++)
- {
- if(elected_candidates.includes(c))
- candidate_scores[c][r] = -1;
- else
- for(k = 0; k < approval_ballots.length; k++)
- if(approval_ballots[k][c])
- candidate_scores[c][r] += weights[k];
- }
- // calculate winner
- max_score = -1;
- options = [];
- for(c = 0; c < num_candidates; c++)
- {
- if(candidate_scores[c][r] > max_score)
- {
- max_score = candidate_scores[c][r];
- options = [c];
- }
- else if(candidate_scores[c][r] == max_score)
- options.push(c);
- }
- if(options.length > 1)
- {
- // break tie by highest unweighted score
- max_unweighted_score = -1;
- new_options = [];
- for(o = 0; o < options.length; o++)
- {
- option = options[o]
- if(candidate_scores[option][0] > max_unweighted_score)
- {
- max_unweighted_score = candidate_scores[option][0];
- new_options = [option];
- }
- else if(candidate_scores[option][0] == max_unweighted_score)
- new_options.push(option);
- }
- // break any remaining ties pseudorandomly
- elected_candidates[r] = new_options[Math.floor(Math.random() * new_options.length)];
- }
- else
- elected_candidates[r] = options[0];
- // calculate new weights
- for(k = 0; k < approval_ballots.length; k++)
- {
- elected_candidates_approved = 0;
- for(c = 0; c < num_candidates; c++)
- if(approval_ballots[k][c] && elected_candidates.includes(c))
- elected_candidates_approved++;
- weights[k] = 1.0 / (1 + elected_candidates_approved);
- }
- }
- // write results to sheet
- result_sheet.appendRow(['Election Results:']);
- result_sheet.appendRow(['Candidate'].concat(rounds));
- for(c = 0; c < num_candidates; c++)
- {
- result_sheet.appendRow([candidate_names[c]].concat(candidate_scores[c]));
- result_sheet.getRange(3 + c, 2 + elected_candidates.indexOf(c)).setBackgroundRGB(128, 255, 128);
- }
- result_sheet.getRange(3, 2, num_candidates, num_candidates).setNumberFormat("0.##");
- result_sheet.appendRow([' ']);
- result_sheet.appendRow(['Winners'].concat(elected_candidates));
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement