from otree.api import * import time doc = """ group_by_arrival_time: fall back to a smaller group if not enough people show up """ class C(BaseConstants): NAME_IN_URL = 'gbat_fallback_smaller_group_part1' PLAYERS_PER_GROUP = 3 NUM_ROUNDS = 1 matching_timeout_mins = 0.5 class Subsession(BaseSubsession): pass def waiting_seconds(player): participant = player.participant wait = int(time.time() - participant.wait_page_arrival) print('Player', player.id_in_subsession, 'waiting for', wait, 'seconds') return wait def ranked_waiting_seconds(waiting_players): waits = [waiting_seconds(p) for p in waiting_players] waits.sort(reverse=True) print(waits) return waits def group_by_arrival_time_method(subsession, waiting_players): print("number of players waiting:", len(waiting_players)) num_waiting = len(waiting_players) subsession.session.vars['num_waiting'] = num_waiting print("number of waiting players:", num_waiting, " ", time.strftime('%X %x %Z')) if len(waiting_players) >= 3: print("creating group") return waiting_players[:3] waits = ranked_waiting_seconds(waiting_players) print(waits) if len(waits) == 2 and waits[1] > 0.2: print( "2 players have been waiting for longer than 20 seconds, " "so we settle for a group of 2", waiting_players ) return waiting_players if len(waits) == 1 and waits[0] > 30: print( "1 player has been waiting for longer than a 0.5 minute, " "so we settle for a group of 1", waiting_players ) return waiting_players # for p in waiting_players: # if p.waiting_too_long(): # return [p] class Group(BaseGroup): pass class Player(BasePlayer): favorite_color = models.StringField(label="What is your favorite color?") def waiting_too_long(player): return time.time() - player.participant.wait_page_arrival > C.matching_timeout_mins * 60 # Functions ###### class GBAT(WaitPage): title_text = ("Please stay on this screen - The tasks will start soon") body_text = "" group_by_arrival_time = True template_name = 'gbat_fallback_smaller_group_part1/Grouping.html' def is_displayed(self): return self.round_number == 1 @staticmethod def app_after_this_page(player: Player, upcoming_apps): if player.waiting_too_long(): return 'survey' @staticmethod def js_vars(player): return dict(arrival_time=player.participant.wait_page_arrival, current_time=time.time(), timeout_mins=C.matching_timeout_mins) @staticmethod def after_all_players_arrive(group: Group): # save each participant's current group ID so it can be # accessed in the next app. for p in group.get_players(): participant = p.participant participant.past_group_id = group.id class GroupTask(Page): form_model = 'player' form_fields = ['favorite_color'] class MyWait(WaitPage): pass class Results(Page): pass page_sequence = [GBAT, GroupTask]