diff --git a/html/index.js b/html/index.js index e38c355..6c20a96 100644 --- a/html/index.js +++ b/html/index.js @@ -209,7 +209,7 @@ async function clickCount() { // Display results elTd = document.createElement('td'); - elTd.innerText = result.comment; + elTd.innerText = result.stage + '. ' + result.comment; elComment.appendChild(elTd); for (let [candidate, countCard] of result.candidates) { @@ -223,8 +223,8 @@ async function clickCount() { elTd.classList.add('elected'); } elTd.style.borderTop = '1px solid black'; - if (countCard.transfers != '0.00' && countCard.transfers != '0') { - elTd.innerText = countCard.transfers; + if (countCard.transfers != '0.00') { + elTd.innerText = ppVotes(countCard.transfers); } else { elTd.innerHTML = ' '; } @@ -235,7 +235,7 @@ async function clickCount() { if (countCard.state === py.pyRCV2.model.CandidateState.ELECTED || countCard.state === py.pyRCV2.model.CandidateState.PROVISIONALLY_ELECTED || countCard.state === py.pyRCV2.model.CandidateState.DISTRIBUTING_SURPLUS) { elTd.classList.add('elected'); - elTd.innerText = countCard.votes; + elTd.innerText = ppVotes(countCard.votes); elTr1.querySelector('td:first-child').classList.add('elected'); } else { elTr1.querySelector('td:first-child').classList.remove('elected'); @@ -248,9 +248,9 @@ async function clickCount() { elTd.innerText = 'Ex'; } else if (countCard.state === py.pyRCV2.model.CandidateState.EXCLUDING) { elTd.classList.add('excluded'); - elTd.innerText = countCard.votes; + elTd.innerText = ppVotes(countCard.votes); } else { - elTd.innerText = countCard.votes; + elTd.innerText = ppVotes(countCard.votes); } } @@ -261,8 +261,8 @@ async function clickCount() { elTd = document.createElement('td'); elTd.classList.add('count'); elTd.style.borderTop = '1px solid black'; - if (result.exhausted.transfers != '0.00' && result.exhausted.transfers != '0') { - elTd.innerText = result.exhausted.transfers; + if (result.exhausted.transfers != '0.00') { + elTd.innerText = ppVotes(result.exhausted.transfers); } else { elTd.innerHTML = ' '; } @@ -270,15 +270,15 @@ async function clickCount() { elTd = document.createElement('td'); elTd.classList.add('count'); - elTd.innerText = result.exhausted.votes; + elTd.innerText = ppVotes(result.exhausted.votes); elExhausted2.appendChild(elTd); // Display loss to fraction elTd = document.createElement('td'); elTd.classList.add('count'); elTd.style.borderTop = '1px solid black'; - if (result.loss_fraction.transfers != '0.00' && result.loss_fraction.transfers != '-0.00' && result.loss_fraction.transfers != '0') { - elTd.innerText = result.loss_fraction.transfers; + if (result.loss_fraction.transfers != '0.00' && result.loss_fraction.transfers != '-0.00') { + elTd.innerText = ppVotes(result.loss_fraction.transfers); } else { elTd.innerHTML = ' '; } @@ -287,9 +287,9 @@ async function clickCount() { elTd = document.createElement('td'); elTd.classList.add('count'); if (result.loss_fraction.votes == '-0.00') { - elTd.innerText = '0.00'; + elTd.innerText = ppVotes('0.00'); } else { - elTd.innerText = result.loss_fraction.votes; + elTd.innerText = ppVotes(result.loss_fraction.votes); } elLTF2.appendChild(elTd); @@ -297,7 +297,7 @@ async function clickCount() { elTd = document.createElement('td'); elTd.classList.add('count'); elTd.style.borderTop = '1px solid black'; - elTd.innerText = result.total; + elTd.innerText = ppVotes(result.total); elTotal.appendChild(elTd); // Display quota @@ -305,7 +305,7 @@ async function clickCount() { elTd.classList.add('count'); elTd.style.borderTop = '1px solid black'; elTd.style.borderBottom = '1px solid black'; - elTd.innerText = result.quota; + elTd.innerText = ppVotes(result.quota); elQuota.appendChild(elTd); } } @@ -338,6 +338,24 @@ async function clickCount() { 'data': text } }); + + // Pretty printing helper functions + let ppDPs = 2; + if (document.getElementById('chkRoundVotes').checked) { + let ppDPs2 = parseInt(document.getElementById('txtRoundVotes').value); + if (ppDPs2 < ppDPs) { + ppDPs = ppDPs2; + } + } + if (document.getElementById('selNumbers').value === 'fixed') { + let ppDPs2 = parseInt(document.getElementById('txtDP').value); + if (ppDPs2 < ppDPs) { + ppDPs = ppDPs2; + } + } + function ppVotes(v) { + return parseFloat(v).toFixed(ppDPs); + } } // Provide a default seed diff --git a/html/worker.js b/html/worker.js index 58a02ca..8fdcd7e 100644 --- a/html/worker.js +++ b/html/worker.js @@ -18,7 +18,7 @@ importScripts('vendor/BigInt_BigRat-a5f89e2.min.js', 'vendor/big-6.0.0.min.js', 'vendor/sjcl-1.0.8.min.js', 'bundle.js'); -let result, counter, ppDP, tiesPrompt; +let stage, result, counter, ppDP, tiesPrompt; onmessage = function(evt) { if (evt.data.type === 'init') { @@ -62,9 +62,11 @@ onmessage = function(evt) { } // Reset + stage = 1; result = counter.reset(); postMessage({'type': 'result', 'result': { + 'stage': stage, 'comment': result.comment, 'candidates': result.candidates.py_items().map(([c, cc]) => [c.py_name, { 'transfers': cc.transfers.pp(ppDP), @@ -95,6 +97,7 @@ function stepElection() { while (true) { try { result = counter.step(); + stage += 1; } catch (ex) { if (py.isinstance(ex, py.pyRCV2.ties.RequireInput)) { // Signals we require input to break a tie @@ -111,6 +114,7 @@ function stepElection() { break; } else { postMessage({'type': 'result', 'result': { + 'stage': stage, 'comment': result.comment, 'candidates': result.candidates.py_items().map(([c, cc]) => [c.py_name, { 'transfers': cc.transfers.pp(ppDP), diff --git a/pyRCV2/cli/stv.py b/pyRCV2/cli/stv.py index 949e5b2..f746653 100644 --- a/pyRCV2/cli/stv.py +++ b/pyRCV2/cli/stv.py @@ -43,8 +43,8 @@ def add_parser(subparsers): parser.add_argument('--ties', '-t', action='append', choices=['backwards', 'prompt', 'random'], default=None, help='how to resolve ties (default: backwards then random)') parser.add_argument('--random-seed', default=None, help='arbitrary string used to seed the RNG for random tie breaking') -def print_step(result): - print(result.comment) +def print_step(stage, result): + print('{}. {}'.format(stage, result.comment)) for candidate, count_card in result.candidates.items(): state = None @@ -109,15 +109,17 @@ def main(args): counter.options['papers'] = 'transferable' if args.transferable_only else 'both' # Reset + stage = 1 result = counter.reset() - print_step(result) + print_step(stage, result) # Step election while True: + stage += 1 result = counter.step() if isinstance(result, pyRCV2.model.CountCompleted): break - print_step(result) + print_step(stage, result)