From 25a9a2743403576b112cd9bbaf1f6538fba038dc Mon Sep 17 00:00:00 2001 From: RunasSudo Date: Fri, 15 Dec 2017 22:35:49 +1030 Subject: [PATCH] Implement BLT/JSON export --- eos/base/util/blt.py | 47 +++++++++++++++++++ eosweb/core/main.py | 10 ++++ eosweb/core/templates/election/view/view.html | 2 + .../question/preferential/result_raw.html | 2 + 4 files changed, 61 insertions(+) create mode 100644 eos/base/util/blt.py diff --git a/eos/base/util/blt.py b/eos/base/util/blt.py new file mode 100644 index 0000000..4228205 --- /dev/null +++ b/eos/base/util/blt.py @@ -0,0 +1,47 @@ +# Eos - Verifiable elections +# pyRCV - Preferential voting counting +# Copyright © 2016–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 . + +def writeBLT(election, q_num, seats, withdrawn=[]): + question = election.questions[q_num] + flat_choices = question.flatten_choices() + + electionLines = [] + + electionLines.append('{} {}\n'.format(len(flat_choices), seats)) + + if len(withdrawn) > 0: + electionLines.append(' '.join(['-{}'.format(flat_choices.index(candidate) + 1) for candidate in withdrawn]) + '\n') + + result = election.results[q_num].count() + + for answer, count in result: + if answer.choices: + electionLines.append('{} {} 0\n'.format(count, ' '.join(str(x + 1) for x in answer.choices))) + else: + electionLines.append('{} 0\n'.format(count)) + + electionLines.append('0\n') + + for candidate in flat_choices: + if candidate.party: + electionLines.append("'{} – {}'\n".format(candidate.name, candidate.party)) + else: + electionLines.append("'{}'\n".format(candidate.name)) + + electionLines.append("'{} – {}'\n".format(election.name, question.prompt)) + + return electionLines diff --git a/eosweb/core/main.py b/eosweb/core/main.py index 11be09b..e2bf47a 100644 --- a/eosweb/core/main.py +++ b/eosweb/core/main.py @@ -34,6 +34,7 @@ from datetime import datetime import functools import importlib +import io import json import os import pytz @@ -308,6 +309,15 @@ def election_api_cast_vote(election): 'vote': EosObject.serialise_and_wrap(vote, should_protect=True) }), mimetype='application/json') +@app.route('/election//export/question//') +@using_election +def election_api_export_question(election, q_num, format): + import eos.base.util.blt + #return flask.Response(''.join(eos.base.util.blt.writeBLT(election, q_num, 2)), mimetype='text/plain') + resp = flask.send_file(io.BytesIO(''.join(eos.base.util.blt.writeBLT(election, q_num, 2)).encode('utf-8')), mimetype='text/plain; charset=utf-8', attachment_filename='{}.blt'.format(q_num), as_attachment=True) + resp.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate' + return resp + @app.route('/auditor') def auditor(): return flask.render_template('election/auditor.html') diff --git a/eosweb/core/templates/election/view/view.html b/eosweb/core/templates/election/view/view.html index a553b7c..387e524 100644 --- a/eosweb/core/templates/election/view/view.html +++ b/eosweb/core/templates/election/view/view.html @@ -81,6 +81,8 @@ {% if (session.user and session.user.is_admin() and election.workflow.get_task('eos.base.workflow.TaskReleaseResults').status == Status.READY) or election.workflow.get_task('eos.base.workflow.TaskReleaseResults').status == Status.EXITED %}

Results

+

Export as Eos JSON

+ {% if election.workflow.get_task('eos.base.workflow.TaskReleaseResults').status == Status.EXITED %}

Results were released at {{ election.workflow.get_task('eos.base.workflow.TaskReleaseResults').exited_at|pretty_date }}.

{% else %} diff --git a/eosweb/core/templates/question/preferential/result_raw.html b/eosweb/core/templates/question/preferential/result_raw.html index 0b95044..8629157 100644 --- a/eosweb/core/templates/question/preferential/result_raw.html +++ b/eosweb/core/templates/question/preferential/result_raw.html @@ -16,6 +16,8 @@ along with this program. If not, see . #} +

Export as OpenSTV BLT

+ {% for answer, num in election.results[loop.index0].count() %}