oTree Forum >

Randomizing Pages without multiple Rounds

#1 by mlt_123

I'm quite aware of the random_task_order snippet, and it works in principle.
Yet i'd like to collect the data within a single round, any help would be appreciated.

Below you can find my _init_p.y.

Thanks

from otree.api import *
import random

class C(BaseConstants):
    NAME_IN_URL = 'embody'
    PLAYERS_PER_GROUP = None
    NUM_FIELDS =14
    TASKS = ["pyField" + str(i+1) for i in range(NUM_FIELDS)]
    #print(TASKS)
    NUM_ROUNDS = len(TASKS)

class Subsession(BaseSubsession):
    pass


class Group(BaseGroup):
    pass


class Player(BasePlayer):
    pyField1 =  models.LongStringField(blank=True)
    pyField2 = models.LongStringField(blank=True)
    pyField3 =  models.LongStringField(blank=True)
    pyField4 = models.LongStringField(blank=True)
    pyField5 =  models.LongStringField(blank=True)
    pyField6 = models.LongStringField(blank=True)
    pyField7 =  models.LongStringField(blank=True)
    pyField8 = models.LongStringField(blank=True)
    pyField9 =  models.LongStringField(blank=True)
    pyField10 = models.LongStringField(blank=True)
    pyField11 =  models.LongStringField(blank=True)
    pyField12 = models.LongStringField(blank=True)
    pyField13 =  models.LongStringField(blank=True)
    pyField14 = models.LongStringField(blank=True)
    rand_page_sequence = models.StringField()
# FUNCTIONS

def creating_session(subsession: Subsession):
    if subsession.round_number == 1:
        for p in subsession.get_players():
            round_numbers = list(range(1, C.NUM_ROUNDS + 1))
            random.shuffle(round_numbers)
            task_rounds = dict(zip(C.TASKS, round_numbers))
            print('player', p.id_in_subsession)
            print('task_rounds is', task_rounds)
            p.participant.task_rounds = task_rounds
            p.rand_page_sequence = str(list(task_rounds.values())).strip('[]')



# PAGES
class Field1(Page):
    form_model = 'player'
    form_fields = ['pyField1']
    def is_displayed(player: Player):
        participant = player.participant
        return player.round_number == participant.task_rounds['pyField1']

class Field2(Page):
    form_model = 'player'
    form_fields = ['pyField2']
    def is_displayed(player: Player):
        participant = player.participant
        return player.round_number == participant.task_rounds['pyField2']
class Field3(Page):
    form_model = 'player'
    form_fields = ['pyField3']
    def is_displayed(player: Player):
        participant = player.participant
        return player.round_number == participant.task_rounds['pyField3']

class Field4(Page):
    form_model = 'player'
    form_fields = ['pyField4']
    def is_displayed(player: Player):
        participant = player.participant
        return player.round_number == participant.task_rounds['pyField4']
class Field5(Page):
    form_model = 'player'
    form_fields = ['pyField5']
    def is_displayed(player: Player):
        participant = player.participant
        return player.round_number == participant.task_rounds['pyField5']
class Field6(Page):
    form_model = 'player'
    form_fields = ['pyField6']
    def is_displayed(player: Player):
        participant = player.participant
        return player.round_number == participant.task_rounds['pyField6']
class Field7(Page):
    form_model = 'player'
    form_fields = ['pyField7']
    def is_displayed(player: Player):
        participant = player.participant
        return player.round_number == participant.task_rounds['pyField7']
class Field8(Page):
    form_model = 'player'
    form_fields = ['pyField8']
    def is_displayed(player: Player):
        participant = player.participant
        return player.round_number == participant.task_rounds['pyField8']

class Field9(Page):
    form_model = 'player'
    form_fields = ['pyField9']
    def is_displayed(player: Player):
        participant = player.participant
        return player.round_number == participant.task_rounds['pyField9']

class Field10(Page):
    form_model = 'player'
    form_fields = ['pyField10']
    def is_displayed(player: Player):
        participant = player.participant
        return player.round_number == participant.task_rounds['pyField10']

class Field11(Page):
    form_model = 'player'
    form_fields = ['pyField11']
    def is_displayed(player: Player):
        participant = player.participant
        return player.round_number == participant.task_rounds['pyField11']
class Field12(Page):
    form_model = 'player'
    form_fields = ['pyField12']
    def is_displayed(player: Player):
        participant = player.participant
        return player.round_number == participant.task_rounds['pyField12']

class Field13(Page):
    form_model = 'player'
    form_fields = ['pyField13']
    def is_displayed(player: Player):
        participant = player.participant
        return player.round_number == participant.task_rounds['pyField13']

class Field14(Page):
    form_model = 'player'
    form_fields = ['pyField14']
    def is_displayed(player: Player):
        participant = player.participant
        return player.round_number == participant.task_rounds['pyField14']

page_sequence = [Field1,Field2,Field3,Field4,Field5,Field6,Field7,Field8,Field9,Field10,Field11,Field12,Field13,Field14]

#2 by BonnEconLab

I haven’t tried this – but shouldn’t adding

page_sequence = random.sample(page_sequence, len(page_sequence))

after your final line work?

#3 by mlt_123

I believe that'd define the same (random) page sequence for all participants?

#4 by BonnEconLab

Yes, that would probably set the same random page sequence for all participants.

If you desire an individually drawn sequence for each participant and simultaneously avoid using multiple rounds, I think you have to stick to a single page only and show/hide the respective questions via JavaScript. Below is some code that works, according to my testing.



In *settings.py*, add

PARTICIPANT_FIELDS = ['rand_q_sequence']



*** Contents of __init__.py: ***

from otree.api import *
import random

doc = """
Questions in random order on a single page
"""


class C(BaseConstants):
    NAME_IN_URL = 'Random_divs'
    PLAYERS_PER_GROUP = None
    NUM_ROUNDS = 1


class Subsession(BaseSubsession):
    pass


class Group(BaseGroup):
    pass


class Player(BasePlayer):

    pyField1 = models.LongStringField(blank=False)
    pyField2 = models.LongStringField(blank=False)
    pyField3 = models.LongStringField(blank=False)
    pyField4 = models.LongStringField(blank=False)
    pyField5 = models.LongStringField(blank=False)
    pyField6 = models.LongStringField(blank=False)
    pyField7 = models.LongStringField(blank=False)
    pyField8 = models.LongStringField(blank=False)
    pyField9 = models.LongStringField(blank=False)
    pyField10 = models.LongStringField(blank=False)
    pyField11 = models.LongStringField(blank=False)
    pyField12 = models.LongStringField(blank=False)
    pyField13 = models.LongStringField(blank=False)
    pyField14 = models.LongStringField(blank=False)
    rand_q_sequence = models.StringField()


# FUNCTIONS

def creating_session(subsession: Subsession):
    if subsession.round_number == 1:
        for p in subsession.get_players():
            p.participant.rand_q_sequence = random.sample(range(0, 14), 14)


# PAGES

class Questionnaire(Page):

    form_model = 'player'
    form_fields = [
        'pyField1', 'pyField2', 'pyField3', 'pyField4', 'pyField5', 'pyField6', 'pyField7',
        'pyField8', 'pyField9', 'pyField10', 'pyField11', 'pyField12', 'pyField13', 'pyField14',
    ]

    def vars_for_template(player):
        return dict(
            pyFields_shuffled = [Questionnaire.form_fields[i] for i in player.participant.rand_q_sequence],
        )


page_sequence = [Questionnaire]




*** Contents of Questionnaire.html ****


{% block title %}

<code>div</code>s in random order with oTree

{% endblock %}


{% block scripts %}

<script type="text/javascript">
  function displayDiv(div_id, inc) {
    document.getElementById("QDiv" + div_id).style.display = "none";
    document.getElementById("QDiv" + (div_id + inc)).style.display = "block";
  }
</script>

{% endblock %}


{% block content %}

{% for pyField in pyFields_shuffled %}
  <div id="QDiv{{ forloop.counter }}" style="display: {% if forloop.counter == 1 %} block {% else %} none {% endif %}; width: 100%;">
    <div>
      <h4><code>div</code> no.&nbsp;{{ forloop.counter }}</h4>
      {% formfield pyField %}
    </div>
    <div>
      <table style="width: 100%;">
        <tr>
          <td style="width: 50%; text-align: left; vertical-align: top;">
            {% if forloop.counter == 1 %}
            {% else %}
              <button type="button" id="previous" class="btn btn-outline-primary" onclick="displayDiv({{ forloop.counter}}, -1)">Previous question</button>
            {% endif %}
          </td>
          <td style="width: 50%; text-align: right; vertical-align: top;">
            {% if forloop.counter == 14 %}
              {{ next_button }}
            {% else %}
              <button type="button" id="next" class="btn btn-outline-primary" onclick="displayDiv({{ forloop.counter}}, +1)">Next question</button>
            {% endif %}
          </td>
        </tr>
      </table>
    </div>
  </div>
{% endfor %}

{% endblock %}

#5 by mlt_123

That's quite a bit of work you put into that, great work. I appreciate it greatly.

Thanks :)

Write a reply

Set forum username