/* pyRCV2: Preferential vote counting Copyright © 2020–2021 Lee Yingtong Li (RunasSudo) This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ let candidates = []; let ballots = []; let inpFile = document.getElementById('inpFile'); let txtBallotValue = document.getElementById('txtBallotValue'); let tblBallot = document.getElementById('tblBallot'); let selBallots = document.getElementById('selBallots'); selBallots.value = 'new'; function initBallot() { // Init ballot table tblBallot.innerHTML = ''; for (let candidate of candidates) { let elTr = document.createElement('tr'); let elTd = document.createElement('td'); let elInput = document.createElement('input'); elInput.type = 'number'; elInput.min = '1'; elInput.style.width = '3em'; elTd.appendChild(elInput); elTr.appendChild(elTd); // Add listener elInput.addEventListener('keyup', function(evt) { if (evt.key === 'Enter') { evt.preventDefault(); clickSave(); } }); elTd = document.createElement('td'); elTd.innerText = candidate; elTr.appendChild(elTd); tblBallot.appendChild(elTr); } } function clickSave() { // Save ballot let ballot = {'value': txtBallotValue.value, 'preferences': []}; for (let elInput of tblBallot.querySelectorAll('input')) { ballot['preferences'].push(elInput.value); } if (selBallots.value === 'new') { // New ballot ballots.push(ballot); // Add new ballot '; selBallots.value = 'new'; for (let i = 0; i < ballots.length; i++) { let elOption = document.createElement('option'); elOption.innerText = 'Ballot ' + (i + 1); selBallots.insertBefore(elOption, selBallots.selectedOptions[0]); } inpFile.value = ''; } } function clickSaveJSON() { let result = { 'candidates': candidates, 'ballots': ballots, }; // Download file let url = URL.createObjectURL(new File([JSON.stringify(result)], 'ballots.json', {type: 'application/json'})); let elA = document.createElement('a'); elA.href = url; elA.download = ''; elA.click(); } function clickExportBLT() { let election = py.pyRCV2.model.Election(); let result = window.prompt('Enter the number of seats to elect:', '1'); if (result !== null) { election.seats = parseInt(result); } else { return; } result = window.prompt('Enter the name of the election:'); if (result !== null) { election.name = result; } else { return; } for (let candidate of candidates) { let py_candidate = py.pyRCV2.model.Candidate(candidate); election.candidates.push(py_candidate); } // Process ballots for (let ballot of ballots) { let py_ballot = py.pyRCV2.model.Ballot(py.pyRCV2.numbers.StringNum(ballot['value']), []); for (let i = 1; i < candidates.length + 1; i++) { let candidate = null; for (let j = 0; j < candidates.length; j++) { if (ballot.preferences[j].trim() === '' + i) { candidate = j; break; } } if (candidate !== null) { py_ballot.preferences.push(election.candidates[candidate]); } else { // No such preference break; } } election.ballots.push(py_ballot); } // Download file let url = URL.createObjectURL(new File([py.pyRCV2.blt.writeBLT(election)], 'election.blt', {type: 'application/json'})); let elA = document.createElement('a'); elA.href = url; elA.download = ''; elA.click(); } function clickEditCandidates() { document.getElementById('bltMain').style.display = 'none'; document.getElementById('divEditCandidates').style.display = ''; document.getElementById('txtCandidates').value = candidates.join('\n'); } function clickSaveCandidates() { candidates = []; for (let candidate of document.getElementById('txtCandidates').value.split('\n')) { if (candidate.trim() !== '') { candidates.push(candidate.trim()); } } // Update ballot entry initBallot(); changeBallot(); document.getElementById('bltMain').style.display = ''; document.getElementById('divEditCandidates').style.display = 'none'; }