import random from otree.api import * from random import choices doc = """ Software for experiment on methane emissions. June 2023. Treatments: (Task 1) Frequency method (Task 2) Interval method (Task 3) Quadratic scoring rule """ class C(BaseConstants): NAME_IN_URL = 'methane_emissions' PLAYERS_PER_GROUP = None NUM_ROUNDS = 1 distribution_bins = ['-10.0%; -9.6%', '-9.5%; -9.1%', '-9.0%; -8.6%', '-8.5%; -8.1%', '-8.0%; -7.6%', '-7.5%; -7.1%', '-7.0%; -6.6%'] distribution_real = [0, 7, 14, 28, 14, 7, 0] payoff_max = 25 class Subsession(BaseSubsession): pass def creating_session(subsession: Subsession): if subsession.round_number == 1: for p in subsession.get_players(): task_for_payment = random.randint(1, 3) p.task_for_payment = task_for_payment participant = p.participant participant.treatment_p = subsession.session.config['TREATMENT'] class Group(BaseGroup): pass class Player(BasePlayer): consent = models.BooleanField(widget=widgets.RadioSelect, choices=[[True, "DO IL MIO CONSENSO A PARTECIPARE ALLO STUDIO PROPOSTO."]], label="Ciò premesso,") slider1 = models.IntegerField(min=0, max=70, blank=True) slider2 = models.IntegerField(min=0, max=70, blank=True) slider3 = models.IntegerField(min=0, max=70, blank=True) slider4 = models.IntegerField(min=0, max=70, blank=True) slider5 = models.IntegerField(min=0, max=70, blank=True) slider6 = models.IntegerField(min=0, max=70, blank=True) slider7 = models.IntegerField(min=0, max=70, blank=True) slider1int = models.IntegerField(min=0, max=70, blank=True) slider2int = models.IntegerField(min=0, max=70, blank=True) slider3int = models.IntegerField(min=0, max=70, blank=True) slider4int = models.IntegerField(min=0, max=70, blank=True) slider5int = models.IntegerField(min=0, max=70, blank=True) slider6int = models.IntegerField(min=0, max=70, blank=True) slider7int = models.IntegerField(min=0, max=70, blank=True) slider1qsr = models.IntegerField(min=0, max=70, blank=True) slider2qsr = models.IntegerField(min=0, max=70, blank=True) slider3qsr = models.IntegerField(min=0, max=70, blank=True) slider4qsr = models.IntegerField(min=0, max=70, blank=True) slider5qsr = models.IntegerField(min=0, max=70, blank=True) slider6qsr = models.IntegerField(min=0, max=70, blank=True) slider7qsr = models.IntegerField(min=0, max=70, blank=True) frequency_payoff = models.CurrencyField() interval_payoff = models.CurrencyField() qsr_payoff_1 = models.CurrencyField(blank=True) qsr_payoff_2 = models.CurrencyField(blank=True) qsr_payoff_3 = models.CurrencyField(blank=True) qsr_payoff_4 = models.CurrencyField(blank=True) qsr_payoff_5 = models.CurrencyField(blank=True) qsr_payoff_6 = models.CurrencyField(blank=True) qsr_payoff_7 = models.CurrencyField(blank=True) qsr_payoff = models.CurrencyField() task_for_payment = models.IntegerField() # Questionnaire risk_attitude_1 = models.IntegerField(widget=widgets.RadioSelectHorizontal, choices=[ [1, "1"], [2, "2"], [3, "3"], [4, "4"], [5, "5"]], label="Investire il 10% del proprio reddito annuale in un fondo comune di investimento a crescita moderata:") risk_attitude_2 = models.IntegerField(widget=widgets.RadioSelectHorizontal, choices=[ [1, "1"], [2, "2"], [3, "3"], [4, "4"], [5, "5"]], label="Scommettere il guadagno di un giorno a una partita di poker ad alto rischio:") risk_attitude_3 = models.IntegerField(widget=widgets.RadioSelectHorizontal, choices=[ [1, "1"], [2, "2"], [3, "3"], [4, "4"], [5, "5"]], label="Investire il 5% del reddito annuale in un'azione molto speculativa:") risk_attitude_4 = models.IntegerField(widget=widgets.RadioSelectHorizontal, choices=[ [1, "1"], [2, "2"], [3, "3"], [4, "4"], [5, "5"]], label="Scommettere il guadagno di una giornata sull'esito di un evento sportivo:") risk_attitude_5 = models.IntegerField(widget=widgets.RadioSelectHorizontal, choices=[ [1, "1"], [2, "2"], [3, "3"], [4, "4"], [5, "5"]], label="Investire il 10% del proprio reddito annuale in una nuova impresa:") risk_attitude_6 = models.IntegerField(widget=widgets.RadioSelectHorizontal, choices=[ [1, "1"], [2, "2"], [3, "3"], [4, "4"], [5, "5"]], label="Scommettere il guadagno di una giornata alle corse dei cavalli:") risk_attitude_7 = models.IntegerField(widget=widgets.RadioSelectHorizontal, choices=[ [1, "1"], [2, "2"], [3, "3"], [4, "4"], [5, "5"]], label="Scegliere una carriera che piace veramente piuttosto che una più sicura:") risk_attitude_8 = models.IntegerField(widget=widgets.RadioSelectHorizontal, choices=[ [1, "1"], [2, "2"], [3, "3"], [4, "4"], [5, "5"]], label="Dire la propria opinione su una questione impopolare in una riunione di lavoro:") risk_attitude_9 = models.IntegerField(widget=widgets.RadioSelectHorizontal, choices=[ [1, "1"], [2, "2"], [3, "3"], [4, "4"], [5, "5"]], label="Trasferirsi in una città lontana dalla propria famiglia allargata:") risk_attitude_10 = models.IntegerField(widget=widgets.RadioSelectHorizontal, choices=[ [1, "1"], [2, "2"], [3, "3"], [4, "4"], [5, "5"]], label="Ammettere che i suoi gusti sono diversi da quelli di un’amica/o:") risk_attitude_11 = models.IntegerField(widget=widgets.RadioSelectHorizontal, choices=[ [1, "1"], [2, "2"], [3, "3"], [4, "4"], [5, "5"]], label="Non essere d’accordo con una figura autoritaria su una questione importante:") # risk_perception_1 = models.IntegerField(widget=widgets.RadioSelectHorizontal, choices=[1,2,3,4,5], label="1. Quanto la preoccupano i cambiamenti climatici?") # risk_perception_2 = models.IntegerField(widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5], label=" - In tutto il mondo il tenore di vita di molte persone diminuirà.") # risk_perception_3 = models.IntegerField(widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5], label=" - In tutto il mondo si verificherà una carenza d’acqua.") # risk_perception_4 = models.IntegerField(widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5], label=" - Aumento del tasso di malattie gravi in tutto il mondo.") # risk_perception_5 = models.IntegerField(widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5], label=" - Il mio tenore di vita diminuirà.") # risk_perception_6 = models.IntegerField(widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5], label=" - Si verificherà una carenza di acqua nel luogo in cui vivo.") # risk_perception_7 = models.IntegerField(widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5], label=" - La mia probabilità di contrarre una malattia grave aumenterà.") # risk_perception_8 = models.IntegerField(widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5], label="3. Quanto ritiene che il cambiamento climatico sia una grave minaccia per la natura? ") # risk_perception_9 = models.IntegerField(widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5], label="4. Quanto sono gravi gli impatti attuali del cambiamento climatico nel mondo secondo Lei?") wtp = models.IntegerField(choices=[[0, "Sì"], [1, "No"], [2, 'Non saprei'], [3, 'Non ho un allevamento']], label="Sarebbe disposta/o ad acquistare un olio essenziale da aggiungere al mangime abituale del suo bestiame in grado di ridurre le emissioni di metano?") open_question = models.LongStringField(blank=True, label="Quali fattori ha considerato nel decidere di distribure i gettoni in un certo modo? La domanda è facoltativa.") task1 = models.IntegerField(min=1,max=3, label="") task2 = models.IntegerField(min=1,max=3, label="") task3 = models.IntegerField(min=1,max=3, label="") # PAGES class Consent(Page): form_model = 'player' form_fields = ['consent'] class Introduction(Page): pass class Task_1_o(Page): def is_displayed(player: Player): return player.participant.treatment_p == "old" form_model = 'player' form_fields = ['slider1', 'slider2', 'slider3', 'slider4', 'slider5', 'slider6', 'slider7'] @staticmethod def error_message(player: Player, values): if values['slider1'] + values['slider2'] + values['slider3'] + values['slider4']\ + values['slider5'] + values['slider6'] + values['slider7'] != 70: return "La somma dei gettoni utilizzati deve essere uguale a 70." @staticmethod def before_next_page(player: Player, timeout_happened): answers_task_1 = [] answers_task_1.extend([player.slider1, player.slider2, player.slider3, player.slider4, player.slider5, player.slider6, player.slider7]) player.frequency_payoff = C.payoff_max if answers_task_1 == C.distribution_real else 0 class Task_1_n(Page): def is_displayed(player: Player): return player.participant.treatment_p == "new" form_model = 'player' form_fields = ['slider1', 'slider2', 'slider3', 'slider4', 'slider5', 'slider6', 'slider7'] @staticmethod def error_message(player: Player, values): if values['slider1'] + values['slider2'] + values['slider3'] + values['slider4']\ + values['slider5'] + values['slider6'] + values['slider7'] != 70: return "La somma dei gettoni utilizzati deve essere uguale a 70." @staticmethod def before_next_page(player: Player, timeout_happened): answers_task_1 = [] answers_task_1.extend([player.slider1, player.slider2, player.slider3, player.slider4, player.slider5, player.slider6, player.slider7]) player.frequency_payoff = C.payoff_max if answers_task_1 == C.distribution_real else 0 class Waiting_page_1(Page): pass class Task_2(Page): form_model = 'player' form_fields = ['slider1int', 'slider2int', 'slider3int', 'slider4int', 'slider5int', 'slider6int', 'slider7int'] @staticmethod def error_message(player: Player, values): if values['slider1int'] + values['slider2int'] + values['slider3int'] + values['slider4int']\ + values['slider5int'] + values['slider6int'] + values['slider7int'] != 70: return "La somma dei gettoni utilizzati deve essere uguale a 70." @staticmethod def before_next_page(player: Player, timeout_happened): answers_task_2 = [player.slider1int, player.slider2int, player.slider3int, player.slider4int, player.slider5int, player.slider6int, player.slider7int] margins_list_lower_bound = [] margins_list_higher_bound = [] for item in answers_task_2: if item == 70: margin = 7 elif 69 >= item >= 60: margin = 6 elif 59 <= item <= 50: margin = 5 elif 49 <= item <= 40: margin = 4 elif 30 <= item <= 39: margin = 3 elif 20 <= item <= 29: margin = 2 else: margin = 1 margins_list_higher_bound.append(item + margin) margins_list_lower_bound.append(item - margin) correct_answers = [] for index, item in enumerate(answers_task_2): if margins_list_lower_bound[index] <= C.distribution_real[index] <= margins_list_higher_bound[index]: correct_answers.append(C.distribution_real[index]) else: correct_answers.append(-1) player.interval_payoff = C.payoff_max if correct_answers == C.distribution_real else 0 class Waiting_page_2(Page): pass class Task_3_o(Page): def is_displayed(player: Player): return player.participant.treatment_p == "old" form_model = 'player' form_fields = ['slider1qsr', 'slider2qsr', 'slider3qsr', 'slider4qsr', 'slider5qsr', 'slider6qsr', 'slider7qsr'] @staticmethod def error_message(player: Player, values): if values['slider1qsr'] + values['slider2qsr'] + values['slider3qsr'] + values['slider4qsr']\ + values['slider5qsr'] + values['slider6qsr'] + values['slider7qsr'] != 70: return "La somma dei gettoni utilizzati deve essere uguale a 70." @staticmethod def live_method(player: Player, data): if data['clicked_button'] == 1: field1 = int(data['field1']) field2 = int(data['field2']) field3 = int(data['field3']) field4 = int(data['field4']) field5 = int(data['field5']) field6 = int(data['field6']) field7 = int(data['field7']) print(field1, field2, field3, field4, field5, field6, field7) # factor = (field1 / 70) * (field1 / 70) + (field2 / 70) * (field2 / 70) + (field3 / 70) * (field3 / 70) + \ # (field4 / 70) * (field4 / 70) + (field5 / 70) * (field5 / 70) + (field5 / 70) * (field5 / 70) + \ # (field6 / 70) * (field6 / 70) + (field7 / 70) * (field7 / 70) factor = 1 print(factor) payoff1 = round(C.payoff_max / 2 + C.payoff_max / 2 * (2 * field1 / 70 - factor), 2) payoff2 = round(C.payoff_max / 2 + C.payoff_max / 2 * (2 * field2 / 70 - factor), 2) payoff3 = round(C.payoff_max / 2 + C.payoff_max / 2 * (2 * field3 / 70 - factor), 2) payoff4 = round(C.payoff_max / 2 + C.payoff_max / 2 * (2 * field4 / 70 - factor), 2) payoff5 = round(C.payoff_max / 2 + C.payoff_max / 2 * (2 * field5 / 70 - factor), 2) payoff6 = round(C.payoff_max / 2 + C.payoff_max / 2 * (2 * field6 / 70 - factor), 2) payoff7 = round(C.payoff_max / 2 + C.payoff_max / 2 * (2 * field7 / 70 - factor), 2) fields = dict(payoff1=payoff1, payoff2=payoff2, payoff3=payoff3, payoff4=payoff4, payoff5=payoff5, payoff6=payoff6, payoff7=payoff7) player.qsr_payoff_1 = payoff1 player.qsr_payoff_2 = payoff2 player.qsr_payoff_3 = payoff3 player.qsr_payoff_4 = payoff4 player.qsr_payoff_5 = payoff5 player.qsr_payoff_6 = payoff6 player.qsr_payoff_7 = payoff7 return {player.id_in_group: fields} @staticmethod def before_next_page(player: Player, timeout_happened): interval = [0,1,2,3,4,5,6] distribution = [] for item in C.distribution_real: if item > 0: weights = item/70 else: weights = 0 distribution.append(weights) random_draw = choices(interval, distribution) print(random_draw) payoffs = [player.qsr_payoff_1, player.qsr_payoff_2, player.qsr_payoff_3, player.qsr_payoff_4, player.qsr_payoff_5, player.qsr_payoff_6, player.qsr_payoff_7] player.qsr_payoff = payoffs[random_draw[0]] print(player.qsr_payoff) class Task_3_n(Page): def is_displayed(player: Player): return player.participant.treatment_p == "new" form_model = 'player' form_fields = ['slider1qsr', 'slider2qsr', 'slider3qsr', 'slider4qsr', 'slider5qsr', 'slider6qsr', 'slider7qsr'] @staticmethod def error_message(player: Player, values): if values['slider1qsr'] + values['slider2qsr'] + values['slider3qsr'] + values['slider4qsr']\ + values['slider5qsr'] + values['slider6qsr'] + values['slider7qsr'] != 70: return "La somma dei gettoni utilizzati deve essere uguale a 70." @staticmethod def live_method(player: Player, data): if data['clicked_button'] == 1: field1 = int(data['field1']) field2 = int(data['field2']) field3 = int(data['field3']) field4 = int(data['field4']) field5 = int(data['field5']) field6 = int(data['field6']) field7 = int(data['field7']) print(field1, field2, field3, field4, field5, field6, field7) # factor = (field1 / 70) * (field1 / 70) + (field2 / 70) * (field2 / 70) + (field3 / 70) * (field3 / 70) + \ # (field4 / 70) * (field4 / 70) + (field5 / 70) * (field5 / 70) + (field5 / 70) * (field5 / 70) + \ # (field6 / 70) * (field6 / 70) + (field7 / 70) * (field7 / 70) factor = 1 print(factor) payoff1 = round(C.payoff_max / 2 + C.payoff_max / 2 * (2 * field1 / 70 - factor), 2) payoff2 = round(C.payoff_max / 2 + C.payoff_max / 2 * (2 * field2 / 70 - factor), 2) payoff3 = round(C.payoff_max / 2 + C.payoff_max / 2 * (2 * field3 / 70 - factor), 2) payoff4 = round(C.payoff_max / 2 + C.payoff_max / 2 * (2 * field4 / 70 - factor), 2) payoff5 = round(C.payoff_max / 2 + C.payoff_max / 2 * (2 * field5 / 70 - factor), 2) payoff6 = round(C.payoff_max / 2 + C.payoff_max / 2 * (2 * field6 / 70 - factor), 2) payoff7 = round(C.payoff_max / 2 + C.payoff_max / 2 * (2 * field7 / 70 - factor), 2) fields = dict(payoff1=payoff1, payoff2=payoff2, payoff3=payoff3, payoff4=payoff4, payoff5=payoff5, payoff6=payoff6, payoff7=payoff7) player.qsr_payoff_1 = payoff1 player.qsr_payoff_2 = payoff2 player.qsr_payoff_3 = payoff3 player.qsr_payoff_4 = payoff4 player.qsr_payoff_5 = payoff5 player.qsr_payoff_6 = payoff6 player.qsr_payoff_7 = payoff7 return {player.id_in_group: fields} @staticmethod def before_next_page(player: Player, timeout_happened): interval = [0,1,2,3,4,5,6] distribution = [] for item in C.distribution_real: if item > 0: weights = item/70 else: weights = 0 distribution.append(weights) random_draw = choices(interval, distribution) print(random_draw) payoffs = [player.qsr_payoff_1, player.qsr_payoff_2, player.qsr_payoff_3, player.qsr_payoff_4, player.qsr_payoff_5, player.qsr_payoff_6, player.qsr_payoff_7] player.qsr_payoff = payoffs[random_draw[0]] print(player.qsr_payoff) class Task_4(Page): class Task_1(Page): form_model = 'player' form_fields = ['slider1', 'slider2', 'slider3', 'slider4', 'slider5', 'slider6', 'slider7'] @staticmethod def error_message(player: Player, values): if values['slider1'] + values['slider2'] + values['slider3'] + values['slider4'] \ + values['slider5'] + values['slider6'] + values['slider7'] != 70: return "La somma dei gettoni utilizzati deve essere uguale a 70." @staticmethod def before_next_page(player: Player, timeout_happened): answers_task_1 = [] answers_task_1.extend([player.slider1, player.slider2, player.slider3, player.slider4, player.slider5, player.slider6, player.slider7]) player.frequency_payoff = C.payoff_max if answers_task_1 == C.distribution_real else 0 class Questionnaire_1(Page): form_model = 'player' def get_form_fields(self): import random questions = ['risk_attitude_1', 'risk_attitude_2', 'risk_attitude_3', 'risk_attitude_4', 'risk_attitude_5', 'risk_attitude_6', 'risk_attitude_7', 'risk_attitude_8', "risk_attitude_9", 'risk_attitude_10', 'risk_attitude_11'] random.shuffle(questions) return questions # class Questionnaire_2(Page): # form_model = 'player' # form_fields = ['risk_perception_1', 'risk_perception_2', 'risk_perception_3', 'risk_perception_4', # 'risk_perception_5', 'risk_perception_6', 'risk_perception_7', 'risk_perception_8', # 'risk_perception_9'] class Questionnaire_3(Page): form_model = 'player' form_fields = ['wtp'] class Questionnaire_4(Page): form_model = 'player' form_fields = ['open_question'] class Questionnaire_5(Page): form_model = "player" form_fields = ['task1', 'task2', 'task3'] def error_message(player: Player, values): if values['task1'] + values['task2'] + values['task3'] != 6: return "Si prega di selezionare una classifica unica" class Final(Page): @staticmethod def vars_for_template(player: Player): if player.task_for_payment == 1: distribution1 = player.slider1 distribution2 = player.slider2 distribution3 = player.slider3 distribution4 = player.slider4 distribution5 = player.slider5 distribution6 = player.slider6 distribution7 = player.slider7 payoff = player.frequency_payoff elif player.task_for_payment == 2: distribution1 = player.slider1int distribution2 = player.slider2int distribution3 = player.slider3int distribution4 = player.slider4int distribution5 = player.slider5int distribution6 = player.slider6int distribution7 = player.slider7int payoff = player.interval_payoff else: distribution1 = player.slider1qsr distribution2 = player.slider2qsr distribution3 = player.slider3qsr distribution4 = player.slider4qsr distribution5 = player.slider5qsr distribution6 = player.slider6qsr distribution7 = player.slider7qsr payoff = player.qsr_payoff return dict(distribution1=distribution1, distribution2=distribution2, distribution3=distribution3, distribution4=distribution4, distribution5=distribution5, distribution6=distribution6, distribution7=distribution7, payoff=payoff) page_sequence = [ Consent, Introduction, Task_1_o, Task_3_n, Waiting_page_1, Task_2, Waiting_page_2, Task_3_o, Task_1_n, # Task_4, Questionnaire_1, # Questionnaire_2, Questionnaire_3, Questionnaire_4, Questionnaire_5, Final]