From d2641592378b13efc922ac0d13415178afe30451 Mon Sep 17 00:00:00 2001 From: RunasSudo Date: Mon, 11 Dec 2017 12:30:41 +1030 Subject: [PATCH] Implement randomisation of choices --- eos/base/election.py | 19 ++++++++++++++++++- eos/core/objects/__init__.py | 1 + eosweb/core/main.py | 2 +- .../question/approval/selections_make.html | 6 +++--- .../preferential/selections_make.html | 4 ++-- .../templates/question/approval/view.html | 2 +- .../templates/question/preferential/view.html | 2 +- 7 files changed, 27 insertions(+), 9 deletions(-) diff --git a/eos/base/election.py b/eos/base/election.py index 62cf3dc..d87aa63 100644 --- a/eos/base/election.py +++ b/eos/base/election.py @@ -15,6 +15,7 @@ # along with this program. If not, see . from eos.core.objects import * +from eos.core.bigint import * from eos.base.workflow import * class Answer(EmbeddedObject): @@ -110,11 +111,12 @@ class Result(EmbeddedObject): pass class ListChoiceQuestion(Question): - _ver = StringField(default='0.4') + _ver = StringField(default='0.5') choices = EmbeddedObjectListField() min_choices = IntField() max_choices = IntField() + randomise_choices = BooleanField(default=False) def pretty_answer(self, answer): if len(answer.choices) == 0: @@ -136,6 +138,21 @@ class ListChoiceQuestion(Question): else: flat_choices.append(choice) return flat_choices + + def randomised_choices(self): + if not self.randomise_choices: + return self.choices + else: + # Clone list + output = EosList([x for x in self.choices]) + # Fisher-Yates shuffle + i = len(output) + while i != 0: + rnd = BigInt.noncrypto_random(0, i - 1) + rnd = rnd.__int__() + i -= 1 + output[rnd], output[i] = output[i], output[rnd] + return output class ApprovalAnswer(Answer): choices = ListField(IntField()) diff --git a/eos/core/objects/__init__.py b/eos/core/objects/__init__.py index 4014b42..994105b 100644 --- a/eos/core/objects/__init__.py +++ b/eos/core/objects/__init__.py @@ -83,6 +83,7 @@ class PrimitiveField(Field): DictField = PrimitiveField IntField = PrimitiveField StringField = PrimitiveField +BooleanField = PrimitiveField class EmbeddedObjectField(Field): def __init__(self, object_type=None, *args, **kwargs): diff --git a/eosweb/core/main.py b/eosweb/core/main.py index 61a29f0..339e6f4 100644 --- a/eosweb/core/main.py +++ b/eosweb/core/main.py @@ -129,7 +129,7 @@ def setup_test_election(): Choice(name='Joe Bloggs', party='Independent ACME') ]), Choice(name='John Q. Public') - ], min_choices=0, max_choices=3) + ], min_choices=0, max_choices=3, randomise_choices=True) election.questions.append(question) question = ApprovalQuestion(prompt='Chairman', choices=[Choice(name='John Doe'), Choice(name='Andrew Citizen')], min_choices=0, max_choices=1) diff --git a/eosweb/core/static/nunjucks/question/approval/selections_make.html b/eosweb/core/static/nunjucks/question/approval/selections_make.html index 20d47cf..c938abc 100644 --- a/eosweb/core/static/nunjucks/question/approval/selections_make.html +++ b/eosweb/core/static/nunjucks/question/approval/selections_make.html @@ -22,11 +22,11 @@
- {% for choice in election.questions.__getitem__(questionNum).choices.impl %} + {% for choice in election.questions.__getitem__(questionNum).randomised_choices().impl %}
- - + +
{% endfor %} diff --git a/eosweb/core/static/nunjucks/question/preferential/selections_make.html b/eosweb/core/static/nunjucks/question/preferential/selections_make.html index 121341d..7a78041 100644 --- a/eosweb/core/static/nunjucks/question/preferential/selections_make.html +++ b/eosweb/core/static/nunjucks/question/preferential/selections_make.html @@ -58,10 +58,10 @@
Options not yet voted for:
- {% for choice in election.questions.__getitem__(questionNum).choices.impl %} + {% for choice in election.questions.__getitem__(questionNum).randomised_choices().impl %} {% if choice.choices %} {# Ticket #} -
+
{{ choice.name }}
diff --git a/eosweb/core/templates/question/approval/view.html b/eosweb/core/templates/question/approval/view.html index e40b4a9..4d49030 100644 --- a/eosweb/core/templates/question/approval/view.html +++ b/eosweb/core/templates/question/approval/view.html @@ -16,7 +16,7 @@ along with this program. If not, see . #} -

Approval voting. Vote for between {{ question.min_choices }} and {{ question.max_choices }} choices.

+

Approval voting. Vote for between {{ question.min_choices }} and {{ question.max_choices }} choices.{% if question.randomise_choices %} Order of choices is randomised.{% endif %}

    {% for choice in question.choices %} diff --git a/eosweb/core/templates/question/preferential/view.html b/eosweb/core/templates/question/preferential/view.html index cf546e4..c676012 100644 --- a/eosweb/core/templates/question/preferential/view.html +++ b/eosweb/core/templates/question/preferential/view.html @@ -16,7 +16,7 @@ along with this program. If not, see . #} -

    Preferential voting. Vote for between {{ question.min_choices }} and {{ question.max_choices }} choices.

    +

    Preferential voting. Vote for between {{ question.min_choices }} and {{ question.max_choices }} choices.{% if question.randomise_choices %} Order of choices is randomised.{% endif %}

      {% for choice in question.choices %}