from otree.api import * import random import itertools import time doc = """ CM experiment. Discrete choice task. """ class C(BaseConstants): NAME_IN_URL = 'CM_DCE_2' PLAYERS_PER_GROUP = 12 TASKS = [1, 2, 3, 4, 5, 6, 7, 8, 9] DC_rounds = ['1', '2', '3', '4', '5', '6', '7', '8', '9'] NUM_ROUNDS = len(DC_rounds) timeout = 3 # CHANGE ACCORDINGLY #Randomizing discrete choice task #Order of tuples: (good 1, its price, good 2, its price) #Code for goods: 1 = black public, 2 = black private, 3 = green public, 4 = green private, 5 - black, 6 - green DC_scenarios = [(2, 5.5, 5, 4.5), (1, 6, 4, 4), (5, 4.5, 3, 5.5), (4, 5, 5, 4.5), (3, 4, 2, 6), (6, 4.5, 1, 5), (1, 4, 6, 5.5), (2, 5, 3, 5), (6, 5.5, 2, 4)] # Experimental budget budget = 6 # Exchange rate exchange_pounds = 0.87 matching_timeout_mins = 5 smaller_group = 8 class Subsession(BaseSubsession): pass class Group(BaseGroup): pass def make_field(label): return models.IntegerField( choices=[[1, "A"], [2, "B"], [3, "Nessun"]], label=label, widget=widgets.RadioSelect, blank=False, ) class Player(BasePlayer): CE_choice_1 = make_field('Scelta') CE_choice_2 = make_field('Scelta') CE_choice_3 = make_field('Scelta') CE_choice_4 = make_field('Scelta') CE_choice_5 = make_field('Scelta') CE_choice_6 = make_field('Scelta') CE_choice_7 = make_field('Scelta') CE_choice_8 = make_field('Scelta') CE_choice_9 = make_field('Scelta') group_size = models.IntegerField() scenario_list = models.LongStringField() choice = models.IntegerField() level1 = models.FloatField() level2 = models.FloatField() product_1 = models.IntegerField() product_2 = models.IntegerField() def waiting_too_long(player): return time.time() - player.participant.wait_page_arrival > C.matching_timeout_mins * 63 # Functions def creating_session(subsession: Subsession): if subsession.round_number == 1: for p in subsession.get_players(): p.participant.is_dropout = False round_numbers = list(range(1, C.NUM_ROUNDS + 1)) random.shuffle(round_numbers) p.participant.DC_rounds = dict(zip(C.DC_rounds, round_numbers)) p.participant.num_rounds = C.NUM_ROUNDS 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] return waits def group_by_arrival_time_method(subsession, 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) >= C.PLAYERS_PER_GROUP: for p in waiting_players: p.group_size = len(waiting_players) print('group size is', p.group_size) return waiting_players[:12] waits = ranked_waiting_seconds(waiting_players) waits.sort(reverse=False) print(waits) # Actual code if len(waits) == 11 and waits[10] > 60*C.matching_timeout_mins: return waiting_players if len(waits) == 10 and waits[9] > 60*C.matching_timeout_mins : return waiting_players if len(waits) == 9 and waits[8] > 60*C.matching_timeout_mins: return waiting_players if len(waits) == 8 and waits[7] > 60*C.matching_timeout_mins: return waiting_players if len(waits) == 7 and waits[6] > 60*C.matching_timeout_mins: return waiting_players if len(waits) == 6 and waits[5] > 60*C.matching_timeout_mins: return waiting_players if len(waits) == 5 and waits[4] > 60*C.matching_timeout_mins: return waiting_players if len(waits) == 4 and waits[3] > 60*C.matching_timeout_mins: return waiting_players if len(waits) == 3 and waits[2] > 60*C.matching_timeout_mins: return waiting_players if len(waits) == 2 and waits[1] > 60*C.matching_timeout_mins: return waiting_players if len(waits) == 1 and waits[0] > 60*C.matching_timeout_mins: return waiting_players ##################################### PAGES #################################################### class GBAT(WaitPage): title_text = ("Si prega di rimanere su questa pagina - La fase 1 inizierà a breve") body_text = "" group_by_arrival_time = True template_name = 'CM_DCE_2/Grouping.html' @staticmethod def is_displayed(player: Player): return player.round_number == 1 @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 group_size = len(group.get_players()) participant.group_size = group_size print(participant.group_size) @staticmethod def app_after_this_page(player: Player, upcoming_apps): # if player.waiting_too_long() and player.participant.group_size < C.smaller_group: if player.participant.group_size < C.smaller_group: return 'CM_final_no_group' class Pre_DC(Page): @staticmethod def is_displayed(player: Player): return player.round_number == 1 # For dropouts @staticmethod def get_timeout_seconds(player): participant = player.participant if participant.is_dropout: return 1 # instant timeout, 1 second else: return C.timeout*60 @staticmethod def before_next_page(player, timeout_happened): participant = player.participant if timeout_happened: participant.is_dropout = True class DCE_1(Page): @staticmethod def is_displayed(player: Player): return player.round_number == player.participant.DC_rounds['1'] form_model = 'player' form_fields = ['CE_choice_1'] @staticmethod def vars_for_template(player: Player): tuple_list = C.DC_scenarios scenario = tuple_list[0] product_1 = scenario[0] level1 = scenario[1] product_2 = scenario[2] level2 = scenario[3] return dict(level1=level1, level2=level2, product_1=product_1, product_2=product_2) # For dropouts @staticmethod def get_timeout_seconds(player): participant = player.participant if participant.is_dropout: return 0.1 # instant timeout, 1 second else: return C.timeout*60 @staticmethod def before_next_page(player, timeout_happened): participant = player.participant if timeout_happened: player.CE_choice_1 = random.randint(1, 3) participant.is_dropout = True participant.CE_choice_1 = player.CE_choice_1 participant.page_no_1 = player.round_number class DCE_2(Page): @staticmethod def is_displayed(player: Player): return player.round_number == player.participant.DC_rounds['2'] form_model = 'player' form_fields = ['CE_choice_2'] def vars_for_template(player: Player): tuple_list = C.DC_scenarios scenario = tuple_list[1] product_1 = scenario[0] level1 = scenario[1] product_2 = scenario[2] level2 = scenario[3] return dict(level1=level1, level2=level2, product_1=product_1, product_2=product_2) # For dropouts @staticmethod def get_timeout_seconds(player): participant = player.participant if participant.is_dropout: return 0.1 # instant timeout, 1 second else: return C.timeout*60 @staticmethod def before_next_page(player, timeout_happened): participant = player.participant if timeout_happened: player.CE_choice_2 = random.randint(1, 3) participant.is_dropout = True participant.CE_choice_2 = player.CE_choice_2 participant.page_no_2 = player.round_number class DCE_3(Page): @staticmethod def is_displayed(player: Player): return player.round_number == player.participant.DC_rounds['3'] form_model = 'player' form_fields = ['CE_choice_3'] def vars_for_template(player: Player): tuple_list = C.DC_scenarios scenario = tuple_list[2] product_1 = scenario[0] level1 = scenario[1] product_2 = scenario[2] level2 = scenario[3] return dict(level1=level1, level2=level2, product_1=product_1, product_2=product_2) # For dropouts @staticmethod def get_timeout_seconds(player): participant = player.participant if participant.is_dropout: return 0.1 # instant timeout, 1 second else: return C.timeout*60 @staticmethod def before_next_page(player, timeout_happened): participant = player.participant if timeout_happened: player.CE_choice_3 = random.randint(1, 3) participant.is_dropout = True participant.CE_choice_3 = player.CE_choice_3 participant.page_no_3 = player.round_number class DCE_4(Page): @staticmethod def is_displayed(player: Player): return player.round_number == player.participant.DC_rounds['4'] form_model = 'player' form_fields = ['CE_choice_4'] def vars_for_template(player: Player): tuple_list = C.DC_scenarios scenario = tuple_list[3] product_1 = scenario[0] level1 = scenario[1] product_2 = scenario[2] level2 = scenario[3] return dict(level1=level1, level2=level2, product_1=product_1, product_2=product_2) # For dropouts @staticmethod def get_timeout_seconds(player): participant = player.participant if participant.is_dropout: return 0.1 # instant timeout, 1 second else: return C.timeout*60 @staticmethod def before_next_page(player, timeout_happened): participant = player.participant if timeout_happened: player.CE_choice_4 = random.randint(1, 3) participant.is_dropout = True participant.CE_choice_4 = player.CE_choice_4 participant.page_no_4 = player.round_number class DCE_5(Page): @staticmethod def is_displayed(player: Player): return player.round_number == player.participant.DC_rounds['5'] form_model = 'player' form_fields = ['CE_choice_5'] def vars_for_template(player: Player): tuple_list = C.DC_scenarios scenario = tuple_list[4] product_1 = scenario[0] level1 = scenario[1] product_2 = scenario[2] level2 = scenario[3] return dict(level1=level1, level2=level2, product_1=product_1, product_2=product_2) # For dropouts @staticmethod def get_timeout_seconds(player): participant = player.participant if participant.is_dropout: return 0.1 # instant timeout, 1 second else: return C.timeout*60 @staticmethod def before_next_page(player, timeout_happened): participant = player.participant if timeout_happened: player.CE_choice_5 = random.randint(1, 3) participant.is_dropout = True participant.CE_choice_5 = player.CE_choice_5 participant.page_no_5 = player.round_number class DCE_6(Page): @staticmethod def is_displayed(player: Player): return player.round_number == player.participant.DC_rounds['6'] form_model = 'player' form_fields = ['CE_choice_6'] def vars_for_template(player: Player): tuple_list = C.DC_scenarios scenario = tuple_list[5] product_1 = scenario[0] level1 = scenario[1] product_2 = scenario[2] level2 = scenario[3] return dict(level1=level1, level2=level2, product_1=product_1, product_2=product_2) # For dropouts @staticmethod def get_timeout_seconds(player): participant = player.participant if participant.is_dropout: return 0.1 # instant timeout, 1 second else: return C.timeout*60 @staticmethod def before_next_page(player, timeout_happened): participant = player.participant if timeout_happened: player.CE_choice_6 = random.randint(1, 3) participant.is_dropout = True participant.CE_choice_6 = player.CE_choice_6 participant.page_no_6 = player.round_number class DCE_7(Page): @staticmethod def is_displayed(player: Player): return player.round_number == player.participant.DC_rounds['7'] form_model = 'player' form_fields = ['CE_choice_7'] def vars_for_template(player: Player): tuple_list = C.DC_scenarios scenario = tuple_list[6] product_1 = scenario[0] level1 = scenario[1] product_2 = scenario[2] level2 = scenario[3] return dict(level1=level1, level2=level2, product_1=product_1, product_2=product_2) # For dropouts @staticmethod def get_timeout_seconds(player): participant = player.participant if participant.is_dropout: return 0.1 # instant timeout, 1 second else: return C.timeout*60 @staticmethod def before_next_page(player, timeout_happened): participant = player.participant if timeout_happened: player.CE_choice_7 = random.randint(1, 3) participant.is_dropout = True participant.CE_choice_7 = player.CE_choice_7 participant.page_no_7 = player.round_number class DCE_8(Page): @staticmethod def is_displayed(player: Player): return player.round_number == player.participant.DC_rounds['8'] form_model = 'player' form_fields = ['CE_choice_8'] def vars_for_template(player: Player): tuple_list = C.DC_scenarios scenario = tuple_list[7] product_1 = scenario[0] level1 = scenario[1] product_2 = scenario[2] level2 = scenario[3] return dict(level1=level1, level2=level2, product_1=product_1, product_2=product_2) # For dropouts @staticmethod def get_timeout_seconds(player): participant = player.participant if participant.is_dropout: return 0.1 # instant timeout, 1 second else: return C.timeout*60 @staticmethod def before_next_page(player, timeout_happened): participant = player.participant if timeout_happened: player.CE_choice_8 = random.randint(1, 3) participant.is_dropout = True participant.CE_choice_8 = player.CE_choice_8 participant.page_no_8 = player.round_number class DCE_9(Page): @staticmethod def is_displayed(player: Player): return player.round_number == player.participant.DC_rounds['9'] form_model = 'player' form_fields = ['CE_choice_9'] # For dropouts @staticmethod def get_timeout_seconds(player): participant = player.participant if participant.is_dropout: return 0.1 # instant timeout, 1 second else: return C.timeout*60 def vars_for_template(player: Player): tuple_list = C.DC_scenarios scenario = tuple_list[8] product_1 = scenario[0] level1 = scenario[1] product_2 = scenario[2] level2 = scenario[3] return dict(level1=level1, level2=level2, product_1=product_1, product_2=product_2) def before_next_page(player: Player, timeout_happened): participant = player.participant participant.dropout_mark = 0 if timeout_happened: player.CE_choice_9 = random.randint(1, 3) participant.is_dropout = True participant.dropout_mark = 1 participant.CE_choice_9 = player.CE_choice_9 participant.page_no_9 = player.round_number page_sequence = [ GBAT, Pre_DC, DCE_1, DCE_2, DCE_3, DCE_4, DCE_5, DCE_6, DCE_7, DCE_8, DCE_9, # Pre_CM, ]