Implement randomisation of choices
This commit is contained in:
parent
db1955d628
commit
d264159237
@ -15,6 +15,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
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:
|
||||
@ -137,6 +139,21 @@ class ListChoiceQuestion(Question):
|
||||
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())
|
||||
|
||||
|
@ -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):
|
||||
|
@ -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)
|
||||
|
@ -22,11 +22,11 @@
|
||||
|
||||
<div id="question-choices" class="ui form" style="margin-bottom: 1em;">
|
||||
<div class="grouped fields">
|
||||
{% for choice in election.questions.__getitem__(questionNum).choices.impl %}
|
||||
{% for choice in election.questions.__getitem__(questionNum).randomised_choices().impl %}
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" id="question-choice-{{ loop.index0 }}" onchange="choicesChanged();">
|
||||
<label for="question-choice-{{ loop.index0 }}">{{ choice.name }}{% if choice.party %} – {{ choice.party }}{% endif %}</label>
|
||||
<input type="checkbox" id="question-choice-{{ election.questions.__getitem__(questionNum).choices.impl.indexOf(choice) }}" onchange="choicesChanged();">
|
||||
<label for="question-choice-{{ election.questions.__getitem__(questionNum).choices.impl.indexOf(choice) }}">{{ choice.name }}{% if choice.party %} – {{ choice.party }}{% endif %}</label>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
@ -58,10 +58,10 @@
|
||||
<div>Options not yet voted for:</div>
|
||||
<div class="dragarea">
|
||||
<div class="dragarea-hint"></div>
|
||||
{% for choice in election.questions.__getitem__(questionNum).choices.impl %}
|
||||
{% for choice in election.questions.__getitem__(questionNum).randomised_choices().impl %}
|
||||
{% if choice.choices %}
|
||||
{# Ticket #}
|
||||
<div class="preferential-choice ticket" data-ticketno="{{ loop.index0 }}">
|
||||
<div class="preferential-choice ticket">
|
||||
<div class="number"></div>
|
||||
<div class="content">
|
||||
<div class="party-name">{{ choice.name }}</div>
|
||||
|
@ -16,7 +16,7 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#}
|
||||
|
||||
<p><small>Approval voting. Vote for between {{ question.min_choices }} and {{ question.max_choices }} choices.</small></p>
|
||||
<p><small>Approval voting. Vote for between {{ question.min_choices }} and {{ question.max_choices }} choices.{% if question.randomise_choices %} Order of choices is randomised.{% endif %}</small></p>
|
||||
|
||||
<ul class="ui list">
|
||||
{% for choice in question.choices %}
|
||||
|
@ -16,7 +16,7 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#}
|
||||
|
||||
<p><small>Preferential voting. Vote for between {{ question.min_choices }} and {{ question.max_choices }} choices.</small></p>
|
||||
<p><small>Preferential voting. Vote for between {{ question.min_choices }} and {{ question.max_choices }} choices.{% if question.randomise_choices %} Order of choices is randomised.{% endif %}</small></p>
|
||||
|
||||
<ul class="ui list">
|
||||
{% for choice in question.choices %}
|
||||
|
Loading…
Reference in New Issue
Block a user