Setting group level treatments with group_by_arrival_time

606 views
Skip to first unread message

Peter Cock

unread,
Aug 23, 2021, 8:34:34 AM8/23/21
to oTree help & discussion
Hello all,

I have a multi-round app where I wish to group players by arrival time (in round one, and retain the groups for the repeated rounds), so I am following:


The first page of the app is a WaitPage with:

class WaitAndGroup(WaitPage):
    group_by_arrival_time = True
    title_text = 'Waiting for other players to begin'
    @staticmethod
    def is_displayed(player):
        return player.round_number == 1

I want to apply a group level treatment, but the default creating_session function is too early (as per the documentation - there is only one group at that point). Equally the group_by_arrival_time_method function is too early - I want to hook into just after a group is created to set the treatment.

Should I use after_all_players_arrive on this wait page? If so, it would help if the documentation suggested this instead of creating_session. If not, where do you advise?

Thanks.

Peter

Chris @ oTree

unread,
Aug 23, 2021, 8:39:28 AM8/23/21
to oTree help & discussion
Yes, use after_all_players_arrive.

Chris @ oTree

unread,
Aug 23, 2021, 8:41:40 AM8/23/21
to oTree help & discussion
Although that wait page is only shown in the first round, so you may want to have a second wait page after that one that is displayed in every round, and use after_all_players_arrive on the second wait page instead.

Peter Cock

unread,
Aug 23, 2021, 10:05:53 AM8/23/21
to oTree help & discussion
In this experiment I want to preserve the grouping for all the rounds, so I think assigning the group treatment here on this first wait page makes most sense.

Is it acceptable to use the group.id field? It does not seem to be documented and the value isn't working as I might expect - I hope to have a reproducible test case if I can't figure this out...

Peter

Chris @ oTree

unread,
Aug 23, 2021, 10:11:47 AM8/23/21
to oTree help & discussion
I recommend storing it in a participant field like this:

def after_all_players_arrive(group):
  my_value = random.randint(1, 10)
  for p in group.get_players():
    p.participant.my_value = my_value

I don't recommend using group.id. It's not really part of oTree's documented API.

Peter Cock

unread,
Aug 23, 2021, 12:23:24 PM8/23/21
to oTree help & discussion
Hi Chris,

I wanted to store the treatment as a group field, which is seemed to be suggested here:


I was intending to allocated the boolean treatment field deterministically - for example alternating True/False on the groups.

It seems even without using group_by_arrival_time, group field values do not persist to later rounds. I'm coming to the conclusion that the group objects are recreated each round, and thus I must reinitialise the fields each round. This seems to work (with default grouping):

def creating_session(subsession):
    session = subsession.session
    if subsession.round_number > 1:
        # Tried following in case it preserved my boolean field:
        subsession.group_like_round(1)
    # Seems my boolean field does not "stick" on later rounds, so repeat each round:
    for group in subsession.get_groups():
        # Using a proxy for a stable group identifier:
        group.framing = bool(min(p.participant.id for p in group.get_players()) % 2)

So I think I follow why you suggest storing this on every participant (even if the value is determined by the group membership).

Are group fields only really suitable for single round games?

Thanks,

Peter

Chris @ oTree

unread,
Aug 23, 2021, 12:41:28 PM8/23/21
to oTree help & discussion
player/group/subsessions are specific to the round. See here: https://otree.readthedocs.io/en/latest/rounds.html#passing-data-between-rounds-or-apps
If you want to alternate True/False, you could store a list like [True, False, True, False ....] as a session field, then each time after_all_players_arrive executes, it pops a value from that list.

Peter Cock

unread,
Aug 24, 2021, 6:40:40 AM8/24/21
to oTree help & discussion
Unless subsession.group_like_round(...) could (optionally) copy group fields, I will follow your advice: Rather than using a group field (and having to manually repopulate this each round), I will use the group information to record a persistent participant field instead.


Right now that just uses the default group allocation (treatment alternates so odd vs even groups get different game framing), nothing using group_by_arrival_time yet.

Thank you,

Peter

Chris @ oTree

unread,
Aug 24, 2021, 6:45:22 AM8/24/21
to oTree help & discussion
group_like_round doesn't copy group fields, it just copies the group structure.

Peter Cock

unread,
Aug 24, 2021, 11:52:44 AM8/24/21
to oTree help & discussion
Cross reference "Treatment specific link (URL) to join" discussion, we'll probably be running two parallel sessions with a custom parameter in order to control the treatment.

That would make my question on this thread moot - I should be able to use group_by_arrival_time = True without any special code.

Kind regards,

Peter

Reply all
Reply to author
Forward
0 new messages