Visual improvements to HTML/JS interface
This commit is contained in:
parent
5c185b386c
commit
1ad1684e67
@ -202,7 +202,8 @@ async function clickCount() {
|
||||
// Step election
|
||||
let worker = new Worker('worker.js');
|
||||
let election;
|
||||
let trComment, trExhausted1, trExhausted2, trLTF1, trLTF2, trTotal, trQuota, trVRE;
|
||||
let trStageNo, trStageKind, trComment;
|
||||
let trExhausted1, trExhausted2, trLTF1, trLTF2, trTotal, trQuota, trVRE;
|
||||
let olLogs;
|
||||
|
||||
worker.onmessage = function(evt) {
|
||||
@ -220,9 +221,22 @@ async function clickCount() {
|
||||
if (evt.data.type === 'init') {
|
||||
election = evt.data.election;
|
||||
|
||||
// Comment row
|
||||
trComment = document.createElement('tr');
|
||||
// Comment rows
|
||||
trStageNo = document.createElement('tr');
|
||||
trStageNo.classList.add('stage-no');
|
||||
let elTd = document.createElement('td');
|
||||
trStageNo.appendChild(elTd);
|
||||
tblResults.appendChild(trStageNo);
|
||||
|
||||
trStageKind = document.createElement('tr');
|
||||
trStageKind.classList.add('stage-kind');
|
||||
elTd = document.createElement('td');
|
||||
trStageKind.appendChild(elTd);
|
||||
tblResults.appendChild(trStageKind);
|
||||
|
||||
trComment = document.createElement('tr');
|
||||
trComment.classList.add('stage-comment');
|
||||
elTd = document.createElement('td');
|
||||
trComment.appendChild(elTd);
|
||||
tblResults.appendChild(trComment);
|
||||
|
||||
@ -233,7 +247,7 @@ async function clickCount() {
|
||||
|
||||
elTd = document.createElement('td');
|
||||
elTd.setAttribute('rowspan', '2');
|
||||
elTd.style.borderTop = '1px solid black';
|
||||
elTd.classList.add('bt');
|
||||
elTd.innerText = candidate;
|
||||
elTr1.appendChild(elTd);
|
||||
|
||||
@ -251,7 +265,7 @@ async function clickCount() {
|
||||
|
||||
elTd = document.createElement('td');
|
||||
elTd.setAttribute('rowspan', '2');
|
||||
elTd.style.borderTop = '1px solid black';
|
||||
elTd.classList.add('bt');
|
||||
elTd.innerText = 'Exhausted';
|
||||
trExhausted1.appendChild(elTd);
|
||||
|
||||
@ -268,7 +282,7 @@ async function clickCount() {
|
||||
|
||||
elTd = document.createElement('td');
|
||||
elTd.setAttribute('rowspan', '2');
|
||||
elTd.style.borderTop = '1px solid black';
|
||||
elTd.classList.add('bt');
|
||||
elTd.innerText = 'Loss to fraction';
|
||||
trLTF1.appendChild(elTd);
|
||||
|
||||
@ -279,7 +293,7 @@ async function clickCount() {
|
||||
trTotal = document.createElement('tr');
|
||||
trTotal.classList.add('info');
|
||||
elTd = document.createElement('td');
|
||||
elTd.style.borderTop = '1px solid black';
|
||||
elTd.classList.add('bt');
|
||||
elTd.innerText = 'Total';
|
||||
trTotal.appendChild(elTd);
|
||||
tblResults.appendChild(trTotal);
|
||||
@ -288,8 +302,8 @@ async function clickCount() {
|
||||
trQuota = document.createElement('tr');
|
||||
trQuota.classList.add('info');
|
||||
elTd = document.createElement('td');
|
||||
elTd.style.borderTop = '1px solid black';
|
||||
elTd.style.borderBottom = '1px solid black';
|
||||
elTd.classList.add('bt');
|
||||
elTd.classList.add('bb');
|
||||
elTd.innerText = 'Quota';
|
||||
trQuota.appendChild(elTd);
|
||||
tblResults.appendChild(trQuota);
|
||||
@ -299,8 +313,8 @@ async function clickCount() {
|
||||
trVRE = document.createElement('tr');
|
||||
trVRE.classList.add('info');
|
||||
elTd = document.createElement('td');
|
||||
elTd.style.borderTop = '1px solid black';
|
||||
elTd.style.borderBottom = '1px solid black';
|
||||
elTd.classList.add('bt');
|
||||
elTd.classList.add('bb');
|
||||
elTd.innerText = 'Vote required for election';
|
||||
trVRE.appendChild(elTd);
|
||||
tblResults.appendChild(trVRE);
|
||||
@ -336,7 +350,15 @@ async function clickCount() {
|
||||
|
||||
// Display results
|
||||
elTd = document.createElement('td');
|
||||
elTd.innerText = result.stage + '. ' + result.comment;
|
||||
elTd.innerText = result.stage;
|
||||
trStageNo.appendChild(elTd);
|
||||
|
||||
elTd = document.createElement('td');
|
||||
elTd.innerText = result.stage_kind;
|
||||
trStageKind.appendChild(elTd);
|
||||
|
||||
elTd = document.createElement('td');
|
||||
elTd.innerText = result.comment;
|
||||
trComment.appendChild(elTd);
|
||||
|
||||
for (let [candidate, countCard] of result.candidates) {
|
||||
@ -349,7 +371,7 @@ async function clickCount() {
|
||||
} else 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.style.borderTop = '1px solid black';
|
||||
elTd.classList.add('bt');
|
||||
elTd.innerHTML = ppVotes(countCard.transfers);
|
||||
elTr1.appendChild(elTd);
|
||||
|
||||
@ -383,7 +405,7 @@ async function clickCount() {
|
||||
// Display exhausted votes
|
||||
elTd = document.createElement('td');
|
||||
elTd.classList.add('count');
|
||||
elTd.style.borderTop = '1px solid black';
|
||||
elTd.classList.add('bt');
|
||||
elTd.innerHTML = ppVotes(result.exhausted.transfers);
|
||||
trExhausted1.appendChild(elTd);
|
||||
|
||||
@ -395,7 +417,7 @@ async function clickCount() {
|
||||
// Display loss to fraction
|
||||
elTd = document.createElement('td');
|
||||
elTd.classList.add('count');
|
||||
elTd.style.borderTop = '1px solid black';
|
||||
elTd.classList.add('bt');
|
||||
elTd.innerHTML = ppVotes(result.loss_fraction.transfers);
|
||||
trLTF1.appendChild(elTd);
|
||||
|
||||
@ -413,15 +435,15 @@ async function clickCount() {
|
||||
// Display total
|
||||
elTd = document.createElement('td');
|
||||
elTd.classList.add('count');
|
||||
elTd.style.borderTop = '1px solid black';
|
||||
elTd.classList.add('bt');
|
||||
elTd.innerHTML = ppVotes(result.total);
|
||||
trTotal.appendChild(elTd);
|
||||
|
||||
// Display quota
|
||||
elTd = document.createElement('td');
|
||||
elTd.classList.add('count');
|
||||
elTd.style.borderTop = '1px solid black';
|
||||
elTd.style.borderBottom = '1px solid black';
|
||||
elTd.classList.add('bt');
|
||||
elTd.classList.add('bb');
|
||||
elTd.innerHTML = ppVotes(result.quota);
|
||||
trQuota.appendChild(elTd);
|
||||
|
||||
@ -429,8 +451,8 @@ async function clickCount() {
|
||||
if (result.vote_required_election !== null) {
|
||||
elTd = document.createElement('td');
|
||||
elTd.classList.add('count');
|
||||
elTd.style.borderTop = '1px solid black';
|
||||
elTd.style.borderBottom = '1px solid black';
|
||||
elTd.classList.add('bt');
|
||||
elTd.classList.add('bb');
|
||||
elTd.innerHTML = ppVotes(result.vote_required_election);
|
||||
trVRE.appendChild(elTd);
|
||||
}
|
||||
@ -462,11 +484,11 @@ async function clickCount() {
|
||||
elTd.innerHTML = 'ELECTED ' + countCard.order_elected;
|
||||
winners.append([candidate, countCard]);
|
||||
}
|
||||
elTd.style.borderTop = '1px solid black';
|
||||
elTd.classList.add('bt');
|
||||
elTr1.appendChild(elTd);
|
||||
}
|
||||
|
||||
elTd.style.borderBottom = '1px solid black';
|
||||
elTd.classList.add('bb');
|
||||
|
||||
let elP = document.createElement('p');
|
||||
elP.innerText = 'Count complete. The winning candidates are, in order of election:'
|
||||
@ -541,6 +563,7 @@ async function clickCount() {
|
||||
if (result.indexOf('.') >= 0) {
|
||||
result = result.substring(0, result.indexOf('.')) + '<sup>' + result.substring(result.indexOf('.')) + '</sup>';
|
||||
}
|
||||
result = result.replace('-', '−');
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -16,14 +16,25 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
@import url('https://fonts.googleapis.com/css2?family=Source+Sans+Pro&display=swap');
|
||||
|
||||
html, body {
|
||||
font-family: 'Liberation Sans', FreeSans, Helvetica, Arial, sans-serif;
|
||||
font-family: 'Source Sans Pro', sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #1d46c4;
|
||||
text-decoration: none;
|
||||
}
|
||||
a:hover {
|
||||
color: #1d3da2;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* Menu styling */
|
||||
|
||||
.menudiv {
|
||||
@ -69,24 +80,41 @@ td.count sup {
|
||||
font-size: 0.6rem;
|
||||
top: 0;
|
||||
}
|
||||
.result tr:first-child td {
|
||||
vertical-align: bottom;
|
||||
tr.stage-no td, tr.stage-kind td, tr.stage-comment td {
|
||||
text-align: center;
|
||||
}
|
||||
tr.stage-no td:not(:first-child) {
|
||||
border-top: 1px solid #76858c;
|
||||
}
|
||||
tr.stage-kind td:not(:first-child) {
|
||||
font-size: 0.75em;
|
||||
min-width: 5rem;
|
||||
color: #1b2839;
|
||||
background-color: #f0f5fb;
|
||||
color-adjust: exact;
|
||||
-webkit-print-color-adjust: exact;
|
||||
}
|
||||
td.excluded {
|
||||
background-color: #fecfcfff;
|
||||
background-color: #fde2e2;
|
||||
color-adjust: exact;
|
||||
-webkit-print-color-adjust: exact;
|
||||
}
|
||||
td.elected {
|
||||
background-color: #d1fca7ff;
|
||||
background-color: #e0fdc5;
|
||||
color-adjust: exact;
|
||||
-webkit-print-color-adjust: exact;
|
||||
}
|
||||
tr.info td {
|
||||
background-color: #edededff;
|
||||
background-color: #f0f5fb;
|
||||
color-adjust: exact;
|
||||
-webkit-print-color-adjust: exact;
|
||||
}
|
||||
td.bt {
|
||||
border-top: 1px solid #76858c;
|
||||
}
|
||||
td.bb {
|
||||
border-bottom: 1px solid #76858c;
|
||||
}
|
||||
|
||||
/* BLT input tool */
|
||||
|
||||
|
@ -145,6 +145,7 @@ function handleException(ex) {
|
||||
function resultToJS(result) {
|
||||
return {
|
||||
'stage': stage,
|
||||
'stage_kind': result.stage_kind,
|
||||
'comment': result.comment,
|
||||
'logs': result.logs,
|
||||
'candidates': result.candidates.py_items().map(([c, cc]) => [c.py_name, {
|
||||
|
@ -61,6 +61,9 @@ def add_parser(subparsers):
|
||||
parser.add_argument('--pp-decimals', type=int, default=2, help='print votes to specified decimal places in results report (default: 2)')
|
||||
|
||||
def print_step(args, stage, result):
|
||||
if result.stage_kind:
|
||||
print('{}. {} {}'.format(stage, result.stage_kind, result.comment))
|
||||
else:
|
||||
print('{}. {}'.format(stage, result.comment))
|
||||
|
||||
if result.logs:
|
||||
|
@ -99,7 +99,7 @@ class BaseSTVCounter:
|
||||
self.compute_quota()
|
||||
self.elect_meeting_quota()
|
||||
|
||||
return self.make_result('First preferences')
|
||||
return self.make_result(None, 'First preferences')
|
||||
|
||||
def distribute_first_preferences(self):
|
||||
"""
|
||||
@ -180,6 +180,7 @@ class BaseSTVCounter:
|
||||
if self.num_elected >= self.election.seats:
|
||||
__pragma__('opov')
|
||||
return CountCompleted(
|
||||
None,
|
||||
'Count complete',
|
||||
self.logs,
|
||||
self.candidates,
|
||||
@ -193,7 +194,6 @@ class BaseSTVCounter:
|
||||
|
||||
# Are there just enough candidates to fill all the seats?
|
||||
if self.options['bulk_elect']:
|
||||
# Include EXCLUDING to avoid interrupting an exclusion
|
||||
if len(self.election.candidates) - self.num_withdrawn - self.num_excluded + sum(1 for c, cc in self.candidates.items() if cc.state == CandidateState.EXCLUDING) <= self.election.seats:
|
||||
# Declare elected all remaining candidates
|
||||
candidates_elected = [(c, cc) for c, cc in self.candidates.items() if cc.state == CandidateState.HOPEFUL or cc.state == CandidateState.GUARDED]
|
||||
@ -212,7 +212,7 @@ class BaseSTVCounter:
|
||||
constraints.stabilise_matrix(self)
|
||||
self.logs.extend(constraints.guard_or_doom(self))
|
||||
|
||||
return self.make_result('Bulk election')
|
||||
return self.make_result(None, 'Bulk election')
|
||||
|
||||
def can_defer_surpluses(self, has_surplus):
|
||||
"""
|
||||
@ -301,7 +301,7 @@ class BaseSTVCounter:
|
||||
|
||||
self.elect_meeting_quota()
|
||||
|
||||
return self.make_result('Surplus of ' + candidate_surplus.name)
|
||||
return self.make_result('Surplus of', candidate_surplus.name)
|
||||
|
||||
def do_surplus(self, candidate_surplus, count_card, surplus):
|
||||
"""
|
||||
@ -317,7 +317,8 @@ class BaseSTVCounter:
|
||||
|
||||
# If we did not perform bulk election in before_surpluses: Are there just enough candidates to fill all the seats?
|
||||
if not self.options['bulk_elect']:
|
||||
if len(self.election.candidates) - self.num_withdrawn - self.num_excluded <= self.election.seats:
|
||||
# Include EXCLUDING to avoid interrupting an exclusion
|
||||
if len(self.election.candidates) - self.num_withdrawn - self.num_excluded + sum(1 for c, cc in self.candidates.items() if cc.state == CandidateState.EXCLUDING) <= self.election.seats:
|
||||
# Declare elected one remaining candidate at a time
|
||||
hopefuls = [(c, cc) for c, cc in self.candidates.items() if cc.state == CandidateState.HOPEFUL or cc.state == CandidateState.GUARDED]
|
||||
hopefuls.sort(key=lambda x: x[1].votes, reverse=True)
|
||||
@ -344,7 +345,7 @@ class BaseSTVCounter:
|
||||
else:
|
||||
self.logs.append(self.pretty_join(order_elected) + ' are elected to fill the remaining vacancies.')
|
||||
|
||||
return self.make_result('Bulk election')
|
||||
return self.make_result(None, 'Bulk election')
|
||||
|
||||
def exclude_doomed(self):
|
||||
"""
|
||||
@ -369,6 +370,13 @@ class BaseSTVCounter:
|
||||
Exclude the lowest ranked hopeful(s)
|
||||
"""
|
||||
|
||||
# Continue current exclusion if applicable
|
||||
if self._exclusion is not None:
|
||||
self.logs.append('Continuing exclusion of ' + self.pretty_join([c.name for c, cc in self._exclusion[0]]) + '.')
|
||||
__pragma__('opov')
|
||||
candidates_excluded = self._exclusion[0]
|
||||
__pragma__('noopov')
|
||||
else:
|
||||
candidates_excluded = self.candidates_to_exclude()
|
||||
if len(candidates_excluded) > 0:
|
||||
if len(candidates_excluded) == 1:
|
||||
@ -376,6 +384,7 @@ class BaseSTVCounter:
|
||||
else:
|
||||
self.logs.append('No surpluses to distribute, so ' + self.pretty_join([c.name for c, cc in candidates_excluded]) + ' are excluded.')
|
||||
|
||||
if len(candidates_excluded) > 0:
|
||||
return self.exclude_candidates(candidates_excluded)
|
||||
|
||||
def exclude_candidates(self, candidates_excluded):
|
||||
@ -434,7 +443,7 @@ class BaseSTVCounter:
|
||||
|
||||
self.elect_meeting_quota()
|
||||
|
||||
return self.make_result('Exclusion of ' + ', '.join([c.name for c, cc in candidates_excluded]))
|
||||
return self.make_result('Exclusion of', ', '.join([c.name for c, cc in candidates_excluded]))
|
||||
|
||||
def candidates_to_bulk_exclude(self, hopefuls):
|
||||
"""
|
||||
@ -479,13 +488,6 @@ class BaseSTVCounter:
|
||||
Returns List[Tuple[Candidate, CountCard]]
|
||||
"""
|
||||
|
||||
# Continue current exclusion if applicable
|
||||
if self._exclusion is not None:
|
||||
self.logs.append('Continuing exclusion of ' + self.pretty_join([c.name for c, cc in self._exclusion[0]]) + '.')
|
||||
__pragma__('opov')
|
||||
return self._exclusion[0]
|
||||
__pragma__('noopov')
|
||||
|
||||
hopefuls = [(c, cc) for c, cc in self.candidates.items() if cc.state == CandidateState.HOPEFUL]
|
||||
hopefuls.sort(key=lambda x: x[1].votes)
|
||||
|
||||
@ -775,9 +777,10 @@ class BaseSTVCounter:
|
||||
return num
|
||||
return num.round(self.options['round_tvs'], num.ROUND_DOWN)
|
||||
|
||||
def make_result(self, comment):
|
||||
def make_result(self, stage_kind, comment):
|
||||
__pragma__('opov')
|
||||
result = CountStepResult(
|
||||
stage_kind,
|
||||
comment,
|
||||
self.logs,
|
||||
self.candidates,
|
||||
|
@ -141,7 +141,7 @@ class MeekSTVCounter(BaseSTVCounter):
|
||||
self.logs.append(self.total.pp(2) + ' usable votes, so the quota is ' + self.quota.pp(2) + '.')
|
||||
self.elect_meeting_quota()
|
||||
|
||||
return self.make_result('First preferences')
|
||||
return self.make_result(None, 'First preferences')
|
||||
|
||||
def distribute_recursively(self, tree, remaining_multiplier):
|
||||
if tree.next_exhausted is None:
|
||||
@ -266,7 +266,7 @@ class MeekSTVCounter(BaseSTVCounter):
|
||||
# NB: We could do this earlier, but this shows the flow of the election more clearly in the count sheet
|
||||
self.elect_meeting_quota()
|
||||
|
||||
return self.make_result('Surpluses distributed')
|
||||
return self.make_result(None, 'Surpluses distributed')
|
||||
|
||||
def do_exclusion(self, candidates_excluded):
|
||||
"""
|
||||
|
@ -155,7 +155,8 @@ class CountCard:
|
||||
__pragma__('noopov')
|
||||
|
||||
class CountStepResult:
|
||||
def __init__(self, comment, logs, candidates, exhausted, loss_fraction, total, quota, vote_required_election):
|
||||
def __init__(self, stage_kind, comment, logs, candidates, exhausted, loss_fraction, total, quota, vote_required_election):
|
||||
self.stage_kind = stage_kind
|
||||
self.comment = comment
|
||||
self.logs = logs
|
||||
|
||||
@ -176,7 +177,7 @@ class CountStepResult:
|
||||
candidates[c] = cc.clone()
|
||||
__pragma__('noopov')
|
||||
|
||||
return CountStepResult(self.comment, candidates, self.exhausted.clone(), self.loss_fraction.clone(), self.total, self.quota)
|
||||
return CountStepResult(self.stage_kind, self.comment, candidates, self.exhausted.clone(), self.loss_fraction.clone(), self.total, self.quota)
|
||||
|
||||
class CountCompleted(CountStepResult):
|
||||
pass
|
||||
|
@ -60,7 +60,8 @@ def test_aec_tas19():
|
||||
result = counter.step()
|
||||
|
||||
comment = data[1][i]
|
||||
assert result.comment == comment, 'Failed to verify comment'
|
||||
result_comment = (result.stage_kind + ' ' + result.comment) if result.stage_kind else result.comment
|
||||
assert result_comment == comment, 'Failed to verify comment'
|
||||
|
||||
for j, cand in enumerate(candidates):
|
||||
votes = pyRCV2.numbers.Num(data[j + 2][i])
|
||||
|
@ -67,7 +67,8 @@ def test_ers97_py():
|
||||
result = counter.step()
|
||||
|
||||
comment = data[1][i]
|
||||
assert result.comment == comment, 'Failed to verify comment'
|
||||
result_comment = (result.stage_kind + ' ' + result.comment) if result.stage_kind else result.comment
|
||||
assert result_comment == comment, 'Failed to verify comment'
|
||||
|
||||
for j, cand in enumerate(candidates):
|
||||
votes = pyRCV2.numbers.Num(data[j + 2][i])
|
||||
@ -112,7 +113,8 @@ def test_ers97_js():
|
||||
assert ctx.eval('result = counter.step();')
|
||||
|
||||
comment = data[1][i]
|
||||
assert ctx.eval('result.comment') == comment, 'Failed to verify comment'
|
||||
result_comment = ctx.eval('result.stage_kind ? (result.stage_kind + " " + result.comment) : result.comment')
|
||||
assert result_comment == comment, 'Failed to verify comment'
|
||||
|
||||
for j, cand in enumerate(candidates):
|
||||
ctx.eval('votes = py.pyRCV2.numbers.Num("{}");'.format(data[j + 2][i]))
|
||||
|
@ -69,7 +69,8 @@ def test_prsa1():
|
||||
|
||||
# Stage 2
|
||||
result = counter.step()
|
||||
assert result.comment == 'Surplus of Grey'
|
||||
assert result.stage_kind == 'Surplus of'
|
||||
assert result.comment == 'Grey'
|
||||
assert isclose(result.candidates[c_evans].votes, 2234)
|
||||
assert isclose(result.candidates[c_grey].votes, 13001)
|
||||
assert isclose(result.candidates[c_thomson].votes, 7468)
|
||||
@ -81,7 +82,8 @@ def test_prsa1():
|
||||
|
||||
# Stage 3
|
||||
result = counter.step()
|
||||
assert result.comment == 'Surplus of Ames'
|
||||
assert result.stage_kind == 'Surplus of'
|
||||
assert result.comment == 'Ames'
|
||||
assert isclose(result.candidates[c_evans].votes, 3038)
|
||||
assert isclose(result.candidates[c_grey].votes, 13001)
|
||||
assert isclose(result.candidates[c_thomson].votes, 8674)
|
||||
@ -93,7 +95,8 @@ def test_prsa1():
|
||||
|
||||
# Stage 4
|
||||
result = counter.step()
|
||||
assert result.comment == 'Surplus of Spears'
|
||||
assert result.stage_kind == 'Surplus of'
|
||||
assert result.comment == 'Spears'
|
||||
assert isclose(result.candidates[c_evans].votes, 4823)
|
||||
assert isclose(result.candidates[c_grey].votes, 13001)
|
||||
assert isclose(result.candidates[c_thomson].votes, 8674)
|
||||
@ -105,25 +108,29 @@ def test_prsa1():
|
||||
|
||||
# Stage 5
|
||||
result = counter.step()
|
||||
assert result.comment == 'Exclusion of Reid'
|
||||
assert result.stage_kind == 'Exclusion of'
|
||||
assert result.comment == 'Reid'
|
||||
assert isclose(result.candidates[c_reid].transfers, -1000)
|
||||
assert isclose(result.candidates[c_white].transfers, 1000)
|
||||
|
||||
# Stage 6
|
||||
result = counter.step()
|
||||
assert result.comment == 'Exclusion of Reid'
|
||||
assert result.stage_kind == 'Exclusion of'
|
||||
assert result.comment == 'Reid'
|
||||
assert isclose(result.candidates[c_reid].transfers, -617)
|
||||
assert isclose(result.candidates[c_white].transfers, 617)
|
||||
|
||||
# Stage 7
|
||||
result = counter.step()
|
||||
assert result.comment == 'Exclusion of Reid'
|
||||
assert result.stage_kind == 'Exclusion of'
|
||||
assert result.comment == 'Reid'
|
||||
assert isclose(result.candidates[c_reid].transfers, -402)
|
||||
assert isclose(result.candidates[c_evans].transfers, 402)
|
||||
|
||||
# Stage 8
|
||||
result = counter.step()
|
||||
assert result.comment == 'Exclusion of Reid'
|
||||
assert result.stage_kind == 'Exclusion of'
|
||||
assert result.comment == 'Reid'
|
||||
assert isclose(result.candidates[c_reid].transfers, -1785)
|
||||
assert isclose(result.candidates[c_evans].transfers, 595)
|
||||
assert isclose(result.candidates[c_thomson].transfers, 1190)
|
||||
@ -139,39 +146,45 @@ def test_prsa1():
|
||||
|
||||
# Stage 9
|
||||
result = counter.step()
|
||||
assert result.comment == 'Exclusion of Evans'
|
||||
assert result.stage_kind == 'Exclusion of'
|
||||
assert result.comment == 'Evans'
|
||||
assert isclose(result.candidates[c_evans].transfers, -1000)
|
||||
assert isclose(result.candidates[c_thomson].transfers, 1000)
|
||||
|
||||
# Stage 10
|
||||
result = counter.step()
|
||||
assert result.comment == 'Exclusion of Evans'
|
||||
assert result.stage_kind == 'Exclusion of'
|
||||
assert result.comment == 'Evans'
|
||||
assert isclose(result.candidates[c_evans].transfers, -1234)
|
||||
assert isclose(result.exhausted.transfers, 1234)
|
||||
|
||||
# Stage 11
|
||||
result = counter.step()
|
||||
assert result.comment == 'Exclusion of Evans'
|
||||
assert result.stage_kind == 'Exclusion of'
|
||||
assert result.comment == 'Evans'
|
||||
assert isclose(result.candidates[c_evans].transfers, -804)
|
||||
assert isclose(result.candidates[c_thomson].transfers, 402)
|
||||
assert isclose(result.candidates[c_white].transfers, 402)
|
||||
|
||||
# Stage 12
|
||||
result = counter.step()
|
||||
assert result.comment == 'Exclusion of Evans'
|
||||
assert result.stage_kind == 'Exclusion of'
|
||||
assert result.comment == 'Evans'
|
||||
assert isclose(result.candidates[c_evans].transfers, -1785)
|
||||
assert isclose(result.candidates[c_white].transfers, 1190)
|
||||
assert isclose(result.exhausted.transfers, 595)
|
||||
|
||||
# Stage 13
|
||||
result = counter.step()
|
||||
assert result.comment == 'Exclusion of Evans'
|
||||
assert result.stage_kind == 'Exclusion of'
|
||||
assert result.comment == 'Evans'
|
||||
assert isclose(result.candidates[c_evans].transfers, -402)
|
||||
assert isclose(result.candidates[c_thomson].transfers, 402)
|
||||
|
||||
# Stage 14
|
||||
result = counter.step()
|
||||
assert result.comment == 'Exclusion of Evans'
|
||||
assert result.stage_kind == 'Exclusion of'
|
||||
assert result.comment == 'Evans'
|
||||
assert isclose(result.candidates[c_evans].transfers, -595)
|
||||
assert isclose(result.candidates[c_white].transfers, 595)
|
||||
|
||||
@ -186,19 +199,22 @@ def test_prsa1():
|
||||
|
||||
# Stage 15
|
||||
result = counter.step()
|
||||
assert result.comment == 'Exclusion of Thomson'
|
||||
assert result.stage_kind == 'Exclusion of'
|
||||
assert result.comment == 'Thomson'
|
||||
assert isclose(result.candidates[c_thomson].transfers, -5000)
|
||||
assert isclose(result.exhausted.transfers, 5000)
|
||||
|
||||
# Stage 16
|
||||
result = counter.step()
|
||||
assert result.comment == 'Exclusion of Thomson'
|
||||
assert result.stage_kind == 'Exclusion of'
|
||||
assert result.comment == 'Thomson'
|
||||
assert isclose(result.candidates[c_thomson].transfers, -2468)
|
||||
assert isclose(result.exhausted.transfers, 2468)
|
||||
|
||||
# Stage 17
|
||||
result = counter.step()
|
||||
assert result.comment == 'Exclusion of Thomson'
|
||||
assert result.stage_kind == 'Exclusion of'
|
||||
assert result.comment == 'Thomson'
|
||||
assert isclose(result.candidates[c_thomson].transfers, -1206)
|
||||
assert isclose(result.candidates[c_white].transfers, 1206)
|
||||
|
||||
|
Reference in New Issue
Block a user