Variable number of players per group

327 views
Skip to first unread message

Miriam

unread,
Nov 23, 2021, 9:15:48 AM11/23/21
to oTree help & discussion
Hi Chris,

to prevent too much dropout from happening, it would be great if we could use a variable number of group members by specifying only a minimum and maximum to build a group.

If I could define some kind of range in the Constants  variable players_per_group and then set a timeout in the Waitpages before an experiment that triggers the after_all_players_arrive function, could that work?

Thanks and best-
Miriam
Message has been deleted
Message has been deleted
Message has been deleted

Miriam

unread,
Nov 24, 2021, 8:43:34 AM11/24/21
to oTree help & discussion
For example, I am looking at the otree snippets. 


The timeout is defined in a page before the WaitPage. 
But I want to have a countdown on the wait page and as soon as a certain amount of time went by, people need to be grouped. 

I don't get, how something can be defined in a page before it is actually happening? 
How does this work? MyPage comes before the WaitPage... 

# PAGES class MyPage(Page): @staticmethod def before_next_page(player: Player, timeout_happened): import time # 15 seconds on wait page max player.timeout = time.time() + Constants.timeout class ResultsWaitPage(WaitPage): template_name = 'wait_page_timeout/ResultsWaitPage.html' @staticmethod def js_vars(player: Player): return dict(timeout=Constants.timeout) @staticmethod def vars_for_template(player: Player): import time timeout_happened = time.time() > player.timeout return dict(timeout_happened=timeout_happened) class Task(Page): pass page_sequence = [MyPage, ResultsWaitPage, Task]

On Wednesday, November 24, 2021 at 2:17:12 PM UTC+1 Miriam wrote:
Hi Chris,

num_waiting_players and all that needs to be defined by me, right? I cannot find any function in the readthedocs files called like that. 
And also the participant.wait_page_arrival needs to be defined by me first? How do I ensure that it takes the moment of arrival? Do I just set time.time() to a participant variable? 

Sorry, but often seemingly trivial information is missing for me (as I am not a programmer), which costs me hours to figure out.. :( 

Thanks and best-
Miriam


On Tuesday, November 23, 2021 at 4:48:32 PM UTC+1 Miriam wrote:

Hi Chris,

Thank you for your fast response.  Just to make sure that I understand this code correctly.. 
That sounds like what I need, yes! I will try that, thank you!

Cheers,
Miriam
On Tuesday, November 23, 2021 at 4:11:33 PM UTC+1 Chris @ oTree wrote:
Take a look at waiting_too_long in otree-snippets. that app tries to group people into groups of 2, but if someone is waiting for more than X minutes they get put into a solo task.
It sounds like what you want is a modification of that. For example, the below code tries to group people into groups of 4, but if at least 3 people have been waiting longer than 5 minutes, it groups them, and if 2 people have been waiting longer than 6 minutes, it groups them. Does this solve your use case?

def waiting_seconds(player):
    participant = player.participant

    import time

    return time.time() - participant.wait_page_arrival


def num_waiting_minutes(waiting_players, num_minutes):
    count = 0
    for p in waiting_players:
        if waiting_seconds(p) >= num_minutes * 60:
            count += 1
    return count


def group_by_arrival_time_method(subsession, waiting_players):
    if len(waiting_players) >= 4:
        return waiting_players[:4]
    if num_waiting_minutes(waiting_players, 5) >= 3:
        return waiting_players
    if num_waiting_minutes(waiting_players, 6) >= 2:
        return waiting_players
    # etc...


Miriam

unread,
Nov 25, 2021, 7:09:54 AM11/25/21
to oTree help & discussion
Hi Chris,

is there a way to implement this functionality on the otree <5 version? Or is this only possible in the newer version?
It seems that the functionality is quite different - I am not sure where I would define the waiting_seconds(player) function... 

Miriam

unread,
Nov 26, 2021, 3:32:11 AM11/26/21
to oTree help & discussion
Hi Chris,

I am trying to upgrade to the new so-self format but received the following errors. 

Upgrading Introduction_Game

Traceback (most recent call last):

  File "/usr/local/bin/otree", line 8, in <module>

    sys.exit(execute_from_command_line())

  File "/usr/local/lib/python3.7/site-packages/otree/main.py", line 113, in execute_from_command_line

    call_command(cmd, *argv[2:])

  File "/usr/local/lib/python3.7/site-packages/otree/cli/base.py", line 32, in call_command

    module.Command().outer_handle(args)

  File "/usr/local/lib/python3.7/site-packages/otree/cli/base.py", line 10, in outer_handle

    return self.handle(**vars(options))

  File "/usr/local/lib/python3.7/site-packages/otree/cli/remove_self.py", line 49, in handle

    make_noself(app_name)

  File "/usr/local/lib/python3.7/site-packages/otree/cli/remove_self.py", line 251, in make_noself

    write(black_format('\n'.join(lines2)))

  File "/usr/local/lib/python3.7/site-packages/otree/cli/remove_self.py", line 285, in black_format

    txt, mode=black.Mode(line_length=100, string_normalization=False)

  File "/usr/local/lib/python3.7/site-packages/black/__init__.py", line 1057, in format_str

    src_node = lib2to3_parse(src_contents.lstrip(), mode.target_versions)

  File "/usr/local/lib/python3.7/site-packages/black/parsing.py", line 96, in lib2to3_parse

    raise exc from None

black.parsing.InvalidInput: Cannot parse: 18:0: class Group(BaseGroup):

--- Even after running  otree update_my_code am I doing something wrong?

Any help would be greatly appreciated, I am stuck here for some days now... :( 

Cheers,
Miriam

Chris @ oTree

unread,
Nov 26, 2021, 3:34:00 AM11/26/21
to oTree help & discussion
Hi, if you send me your project I can try to update it for you.

Miriam

unread,
Nov 26, 2021, 3:41:10 AM11/26/21
to oTree help & discussion
Hi, 

I sent it to you via email.

Thank you very much!
Miriam

Peter Cock

unread,
Nov 26, 2021, 6:04:07 AM11/26/21
to oTree help & discussion
That seems like a useful example which might work for us too
(groups of 6 where if the players have been waiting we might
want them to progress as a reduced group of 4 or 5, but keep
waiting if there are only 1, 2 or 3 players).

It seems worth adding to the snippets library :)

Peter

On Tuesday, 23 November 2021 at 15:11:33 UTC Chris @ oTree wrote:
Take a look at waiting_too_long in otree-snippets. that app tries to group people into groups of 2, but if someone is waiting for more than X minutes they get put into a solo task.
It sounds like what you want is a modification of that. For example, the below code tries to group people into groups of 4, but if at least 3 people have been waiting longer than 5 minutes, it groups them, and if 2 people have been waiting longer than 6 minutes, it groups them. Does this solve your use case?

def waiting_seconds(player):
    participant = player.participant

    import time

    return time.time() - participant.wait_page_arrival


def num_waiting_minutes(waiting_players, num_minutes):
    count = 0
    for p in waiting_players:
        if waiting_seconds(p) >= num_minutes * 60:
            count += 1
    return count


def group_by_arrival_time_method(subsession, waiting_players):
    if len(waiting_players) >= 4:
        return waiting_players[:4]
    if num_waiting_minutes(waiting_players, 5) >= 3:
        return waiting_players
    if num_waiting_minutes(waiting_players, 6) >= 2:
        return waiting_players
    # etc...


On Tuesday, November 23, 2021 at 6:15:48 AM UTC-8 Miriam wrote:
Message has been deleted
Message has been deleted

Chris @ oTree

unread,
Nov 26, 2021, 8:09:34 PM11/26/21
to oTree help & discussion
OK sure, I added gbat_fallback_smaller_group to otree-snippets. Also gave "waiting_too_long" app a more descriptive name.
Reply all
Reply to author
Forward
Message has been deleted
0 new messages