2020-12-31 01:52:04 +11:00
# 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/>.
2020-12-31 17:00:23 +11:00
from pytest_steps import test_steps
2020-12-31 01:52:04 +11:00
import pyRCV2 . blt
import pyRCV2 . numbers
from pyRCV2 . method . base_stv import UIGSTVCounter
from pyRCV2 . model import CandidateState , CountCompleted
import csv
import gzip
2020-12-31 17:00:23 +11:00
# Read model CSV
2021-01-02 23:34:09 +11:00
with open ( ' tests/data/aec-senate-formalpreferences-24310-TAS.csv ' , ' r ' , newline = ' ' ) as f :
2020-12-31 17:00:23 +11:00
reader = csv . reader ( f )
data = [ x for x in reader ]
candidates = [ data [ i ] [ 0 ] for i in range ( 2 , len ( data ) - 2 ) ]
@test_steps ( * [ ' Stage {} ' . format ( data [ 0 ] [ i ] ) for i in range ( 1 , len ( data [ 0 ] ) , 2 ) ] )
2020-12-31 01:52:04 +11:00
def test_aec_tas19 ( ) :
""" Compare count of aec-senate-formalpreferences-24310-TAS.blt.gz with model result at https://results.aec.gov.au/24310/Website/External/SenateStateDop-24310-TAS.pdf """
pyRCV2 . numbers . set_numclass ( pyRCV2 . numbers . NativeInt )
2021-01-02 23:34:09 +11:00
with gzip . open ( ' tests/data/aec-senate-formalpreferences-24310-TAS.blt.gz ' , ' rt ' ) as f :
2020-12-31 01:52:04 +11:00
election = pyRCV2 . blt . readBLT ( f . read ( ) )
assert len ( election . candidates ) == len ( candidates )
counter = UIGSTVCounter ( election , {
' surplus_order ' : ' order ' ,
2020-12-31 16:43:50 +11:00
' exclusion ' : ' by_value '
2020-12-31 01:52:04 +11:00
} )
result = counter . reset ( )
for i in range ( 1 , len ( data [ 0 ] ) , 2 ) :
stage = int ( data [ 0 ] [ i ] )
while len ( counter . step_results ) < stage :
result = counter . step ( )
comment = data [ 1 ] [ i ]
assert result . comment == comment , ' Failed to verify stage {} comment ' . format ( stage )
for j , cand in enumerate ( candidates ) :
votes = pyRCV2 . numbers . Num ( data [ j + 2 ] [ i ] )
cc = next ( cc for c , cc in result . candidates . items ( ) if c . name == cand )
assert cc . votes == votes , ' Failed to verify stage {} candidate " {} " votes, got {} expected {} ' . format ( stage , cand , cc . votes . pp ( 0 ) , votes . pp ( 0 ) )
state = data [ j + 2 ] [ i + 1 ] if len ( data [ j + 2 ] ) > ( i + 1 ) else ' '
accept = { ' ' : CandidateState . HOPEFUL , ' PEL ' : CandidateState . PROVISIONALLY_ELECTED , ' EL ' : CandidateState . ELECTED , ' EX ' : CandidateState . EXCLUDED , ' EXCLUDING ' : CandidateState . EXCLUDING }
assert cc . state == accept [ state ] , ' Failed to verify stage {} candidate " {} " state ' . format ( stage , cand )
exhausted = pyRCV2 . numbers . Num ( data [ len ( candidates ) + 2 ] [ i ] )
assert result . exhausted . votes == exhausted , ' Failed to verify stage {} exhausted votes, got {} expected {} ' . format ( stage , result . exhausted . votes . pp ( 0 ) , exhausted . pp ( 0 ) )
loss_fraction = pyRCV2 . numbers . Num ( data [ len ( candidates ) + 3 ] [ i ] )
assert result . loss_fraction . votes == loss_fraction , ' Failed to verify stage {} loss to fraction, got {} expected {} ' . format ( stage , result . loss_fraction . votes . pp ( 0 ) , loss_fraction . pp ( 0 ) )
2020-12-31 17:00:23 +11:00
yield ' Stage {} ' . format ( stage )