Add test case based on CSM15 ballot data
This commit is contained in:
parent
fb8d8981d7
commit
f0e8bac4b7
@ -34,6 +34,7 @@ class WrightSTVCounter(WIGSTVCounter):
|
||||
count_card.state = CandidateState.EXCLUDED
|
||||
|
||||
# Reset the count
|
||||
# Carry over certain candidate states
|
||||
new_candidates = SafeDict()
|
||||
for candidate, count_card in self.candidates.items():
|
||||
new_count_card = CountCard()
|
||||
@ -52,7 +53,9 @@ class WrightSTVCounter(WIGSTVCounter):
|
||||
self.loss_fraction = CountCard()
|
||||
self.num_elected = 0
|
||||
|
||||
step_results = self.step_results # Carry over step results
|
||||
result = self.reset()
|
||||
self.step_results = step_results
|
||||
result.comment = 'Exclusion of ' + candidate_excluded.name
|
||||
|
||||
return result
|
||||
|
10536
tests/CSM15.blt
Normal file
10536
tests/CSM15.blt
Normal file
File diff suppressed because it is too large
Load Diff
252
tests/test_csm.py
Normal file
252
tests/test_csm.py
Normal file
@ -0,0 +1,252 @@
|
||||
# pyRCV2: Preferential vote counting
|
||||
# Copyright © 2020 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
from pytest import approx
|
||||
|
||||
import pyRCV2.blt
|
||||
import pyRCV2.numbers
|
||||
from pyRCV2.method.wright import WrightSTVCounter
|
||||
from pyRCV2.model import CandidateState, CountCompleted
|
||||
|
||||
def count_until_exclude(counter):
|
||||
while True:
|
||||
result = counter.step()
|
||||
if isinstance(result, CountCompleted):
|
||||
return result
|
||||
if result.comment.startswith('Exclusion of '):
|
||||
return result
|
||||
|
||||
def test_csm15():
|
||||
"""Compare count of CSM15.blt with model result at https://www.eveonline.com/article/qbtyyo/meet-the-new-council"""
|
||||
|
||||
pyRCV2.numbers.set_numclass(pyRCV2.numbers.Native)
|
||||
|
||||
with open('tests/CSM15.blt', 'r') as f:
|
||||
election = pyRCV2.blt.readBLT(f.read())
|
||||
|
||||
assert len(election.candidates) == 40
|
||||
|
||||
cands = {c.name: c for c in election.candidates}
|
||||
|
||||
counter = WrightSTVCounter(election)
|
||||
|
||||
# Round 1
|
||||
result = counter.reset()
|
||||
assert result.candidates[cands['Merkelchen']].votes.impl == 5325
|
||||
assert result.candidates[cands['Gobbins']].votes.impl == 3709
|
||||
assert result.candidates[cands['Vily']].votes.impl == 2789
|
||||
assert result.candidates[cands['Maria Taylor']].votes.impl == 2556
|
||||
assert result.candidates[cands['Brisc Rubal']].votes.impl == 1794
|
||||
assert result.candidates[cands['Ikarus Cesaille']].votes.impl == 1471
|
||||
assert result.candidates[cands['Phantomite']].votes.impl == 1462
|
||||
assert result.candidates[cands['Juvenius Drakonius']].votes.impl == 1375
|
||||
assert result.candidates[cands['Torvald Uruz']].votes.impl == 1297
|
||||
assert result.candidates[cands['Mike Azariah']].votes.impl == 1242
|
||||
assert result.candidates[cands['BlazingBunny']].votes.impl == 1042
|
||||
assert result.candidates[cands['ExookiZ']].votes.impl == 961
|
||||
assert result.candidates[cands['Loroseco Kross']].votes.impl == 938
|
||||
assert result.candidates[cands['Kenneth Feld']].votes.impl == 874
|
||||
assert result.candidates[cands['Jurius Doctor']].votes.impl == 747
|
||||
assert result.candidates[cands['Stitch Kaneland']].votes.impl == 698
|
||||
assert result.candidates[cands['DutchGunner']].votes.impl == 690
|
||||
assert result.candidates[cands['Insidious Sainthood']].votes.impl == 583
|
||||
assert result.candidates[cands['Alexis Finch']].votes.impl == 526
|
||||
assert result.candidates[cands['Steadyo']].votes.impl == 499
|
||||
assert result.candidates[cands['Innominate']].votes.impl == 493
|
||||
assert result.candidates[cands['Meredith en Thielles']].votes.impl == 477
|
||||
assert result.candidates[cands['Ironwulf']].votes.impl == 472
|
||||
assert result.candidates[cands['PJHustle']].votes.impl == 443
|
||||
assert result.candidates[cands['Darius Caliente']].votes.impl == 442
|
||||
assert result.candidates[cands['January Valentine']].votes.impl == 414
|
||||
assert result.candidates[cands['The Oz']].votes.impl == 407
|
||||
assert result.candidates[cands['Pandora Singularity']].votes.impl == 355
|
||||
assert result.candidates[cands['UAxDEATH']].votes.impl == 323
|
||||
assert result.candidates[cands['Komi Valentine']].votes.impl == 277
|
||||
assert result.candidates[cands['Murray Rothbardo']].votes.impl == 184
|
||||
assert result.candidates[cands['Xenuria']].votes.impl == 179
|
||||
assert result.candidates[cands['Prospektor Schipplock']].votes.impl == 177
|
||||
assert result.candidates[cands['Styxx']].votes.impl == 172
|
||||
assert result.candidates[cands['boernl']].votes.impl == 171
|
||||
assert result.candidates[cands['Dhuras']].votes.impl == 162
|
||||
assert result.candidates[cands['Rheaha Preynar']].votes.impl == 125
|
||||
assert result.candidates[cands['Kalen Tsero']].votes.impl == 113
|
||||
assert result.candidates[cands['Storm Delay']].votes.impl == 96
|
||||
assert result.candidates[cands['Leehams DaWildabeast']].votes.impl == 60
|
||||
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['Leehams DaWildabeast']].votes.impl == approx(63.208412)
|
||||
assert result.candidates[cands['Leehams DaWildabeast']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 2
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['Storm Delay']].votes.impl == approx(112.229279)
|
||||
assert result.candidates[cands['Storm Delay']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 3
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['Kalen Tsero']].votes.impl == approx(115.888433)
|
||||
assert result.candidates[cands['Kalen Tsero']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 4
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['Rheaha Preynar']].votes.impl == approx(133.122193)
|
||||
assert result.candidates[cands['Rheaha Preynar']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 5
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['Dhuras']].votes.impl == approx(170.123665)
|
||||
assert result.candidates[cands['Dhuras']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 6
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['boernl']].votes.impl == approx(181.377165)
|
||||
assert result.candidates[cands['boernl']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 7
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['Styxx']].votes.impl == approx(184.463008)
|
||||
assert result.candidates[cands['Styxx']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 8
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['Murray Rothbardo']].votes.impl == approx(189.651433)
|
||||
assert result.candidates[cands['Murray Rothbardo']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 9
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['Xenuria']].votes.impl == approx(198.266912)
|
||||
assert result.candidates[cands['Xenuria']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 10
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['Prospektor Schipplock']].votes.impl == approx(213.386936)
|
||||
assert result.candidates[cands['Prospektor Schipplock']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 11
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['Komi Valentine']].votes.impl == approx(336.404306)
|
||||
assert result.candidates[cands['Komi Valentine']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 12
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['UAxDEATH']].votes.impl == approx(357.732024)
|
||||
assert result.candidates[cands['UAxDEATH']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 13
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['Pandora Singularity']].votes.impl == approx(413.808353)
|
||||
assert result.candidates[cands['Pandora Singularity']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 14
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['PJHustle']].votes.impl == approx(478.737771)
|
||||
assert result.candidates[cands['PJHustle']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 15
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['Ironwulf']].votes.impl == approx(528.845712)
|
||||
assert result.candidates[cands['Ironwulf']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 16
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['January Valentine']].votes.impl == approx(557.154707)
|
||||
assert result.candidates[cands['January Valentine']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 17
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['Darius Caliente']].votes.impl == approx(620.307162)
|
||||
assert result.candidates[cands['Darius Caliente']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 18
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['Alexis Finch']].votes.impl == approx(630.517365)
|
||||
assert result.candidates[cands['Alexis Finch']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 19
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['The Oz']].votes.impl == approx(673.241462)
|
||||
assert result.candidates[cands['The Oz']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 20
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['Steadyo']].votes.impl == approx(693.622387)
|
||||
assert result.candidates[cands['Steadyo']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 21
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['Insidious Sainthood']].votes.impl == approx(711.112702)
|
||||
assert result.candidates[cands['Insidious Sainthood']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 22
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['Meredith en Thielles']].votes.impl == approx(773.804223)
|
||||
assert result.candidates[cands['Meredith en Thielles']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 23
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['Stitch Kaneland']].votes.impl == approx(944.597498)
|
||||
assert result.candidates[cands['Stitch Kaneland']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 24
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['DutchGunner']].votes.impl == approx(1056.847624)
|
||||
assert result.candidates[cands['DutchGunner']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 25
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['Jurius Doctor']].votes.impl == approx(1254.134642)
|
||||
assert result.candidates[cands['Jurius Doctor']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 26
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['BlazingBunny']].votes.impl == approx(1448.527563)
|
||||
assert result.candidates[cands['BlazingBunny']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 27
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['ExookiZ']].votes.impl == approx(1527.088745)
|
||||
assert result.candidates[cands['ExookiZ']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 28
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['Juvenius Drakonius']].votes.impl == approx(1614.455637)
|
||||
assert result.candidates[cands['Juvenius Drakonius']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 29
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['Ikarus Cesaille']].votes.impl == approx(1938.970656)
|
||||
assert result.candidates[cands['Ikarus Cesaille']].state == CandidateState.EXCLUDED
|
||||
|
||||
# Round 30
|
||||
result = count_until_exclude(counter)
|
||||
assert counter.step_results[-2].candidates[cands['Loroseco Kross']].votes.impl == approx(2306.134123)
|
||||
assert result.candidates[cands['Loroseco Kross']].state == CandidateState.EXCLUDED
|
||||
|
||||
result = counter.step()
|
||||
assert result.comment == 'Bulk election'
|
||||
assert result.candidates[cands['Vily']].state == CandidateState.PROVISIONALLY_ELECTED
|
||||
assert result.candidates[cands['Phantomite']].state == CandidateState.PROVISIONALLY_ELECTED
|
||||
assert result.candidates[cands['Kenneth Feld']].state == CandidateState.PROVISIONALLY_ELECTED
|
||||
assert result.candidates[cands['Merkelchen']].state == CandidateState.PROVISIONALLY_ELECTED
|
||||
assert result.candidates[cands['Maria Taylor']].state == CandidateState.PROVISIONALLY_ELECTED
|
||||
assert result.candidates[cands['Brisc Rubal']].state == CandidateState.PROVISIONALLY_ELECTED
|
||||
assert result.candidates[cands['Gobbins']].state == CandidateState.PROVISIONALLY_ELECTED
|
||||
assert result.candidates[cands['Torvald Uruz']].state == CandidateState.PROVISIONALLY_ELECTED
|
||||
assert result.candidates[cands['Mike Azariah']].state == CandidateState.PROVISIONALLY_ELECTED
|
||||
assert result.candidates[cands['Innominate']].state == CandidateState.PROVISIONALLY_ELECTED
|
||||
|
||||
result = counter.step()
|
||||
assert isinstance(result, CountCompleted)
|
Reference in New Issue
Block a user