63 lines
2.2 KiB
Python
63 lines
2.2 KiB
Python
# Eos - Verifiable elections
|
|
# Copyright © 2017 RunasSudo (Yingtong Li)
|
|
#
|
|
# 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 <http://www.gnu.org/licenses/>.
|
|
|
|
from eos.core.objects import *
|
|
from eos.core.tasks import *
|
|
from eos.base.election import *
|
|
|
|
import eos.base.util.blt
|
|
|
|
import pyRCV.stv
|
|
import pyRCV.utils.blt
|
|
|
|
import base64
|
|
|
|
class QuietSTVCounter(pyRCV.stv.STVCounter):
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self.randdata = base64.b64decode(self.args['randjson']['result']['random']['data'][0])
|
|
|
|
self.output = []
|
|
|
|
def log(self, string, *args):
|
|
self.output.append(string.format(*args))
|
|
|
|
class TaskTallySTV(Task):
|
|
election_id = UUIDField()
|
|
q_num = IntField()
|
|
random = BlobField()
|
|
num_seats = IntField()
|
|
|
|
def _run(self):
|
|
election = Election.get_by_id(self.election_id)
|
|
|
|
# Count the ballots
|
|
blt = eos.base.util.blt.writeBLT(election, self.q_num, self.num_seats)
|
|
ballots, candidates, seats = pyRCV.utils.blt.readBLT(blt)
|
|
counter = QuietSTVCounter(ballots, candidates, seats=seats, ties=['backwards', 'random'], randjson=self.random, verbose=True, quota='gt-hb')
|
|
elected, exhausted = counter.countVotes()
|
|
|
|
election.results[self.q_num] = MultipleResult(results=[election.results[self.q_num]])
|
|
result = STVResult(elected=[candidates.index(x) for x in elected], log='\n'.join(counter.output), random=self.random)
|
|
|
|
election.results[self.q_num].results.append(result)
|
|
election.save()
|
|
|
|
@property
|
|
def label(self):
|
|
election = Election.get_by_id(self.election_id)
|
|
return 'Tally STV question – ' + election.questions[self.q_num].prompt + ' – ' + election.name
|