import itertools import json import json as json import math import random import random as random import numpy as np import pandas as pd from otree.api import * author = 'Your name here' doc = """ MPL """ class Constants(BaseConstants): name_in_url = '9H32Dcsfw2DDg' players_per_group = None num_rounds = 2 num_participants = 10 timeout = 40 play_rounds = 5 # ordering = ['BA','AB'] ### MPL max_amount = 40 increments = 2 no_decisions = math.floor((2 * max_amount / increments)) + 1 # Payoff Constants payoff_incorrect = cu(0) pwd_rate_high = 12 pwd_piecerate_high = cu(pwd_rate_high) math_rate_high = 12 math_piecerate_high = cu(math_rate_high) pwd_rate_low = 10 pwd_piecerate_low = cu(pwd_rate_low) math_rate_low = 10 math_piecerate_low = cu(math_rate_low) MPL_sequence = ['HighLow', 'LowHigh'] task = 'MPL' num_pwd_tasks = 10 num_math_tasks = 10 class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): task = models.StringField() MPL_sequence = models.StringField() MPL_high_time_spent = models.FloatField(blank=True) MPL_low_time_spent = models.FloatField(blank=True) Instructions_1_time_spent = models.FloatField(blank=True) Instructions_2_time_spent = models.FloatField(blank=True) MPL_Instructions_time_spent = models.FloatField(blank=True) MPL_high_warnings = models.IntegerField() MPL_low_warnings = models.IntegerField() Instructions_1_warnings = models.IntegerField() Instructions_2_warnings = models.IntegerField() MPL_Instructions_warnings = models.IntegerField() ### MPL increments = models.FloatField() max_amount = models.FloatField() no_decisions = models.IntegerField() # Decision numbers last_False_high = models.IntegerField() first_True_high = models.IntegerField() # Decision values last_False_val_high = models.FloatField() first_True_val_high = models.FloatField() # Lists decision_list_high = models.StringField() no_reminder_list_high = models.StringField() reminder_list_high = models.StringField() # Decision numbers last_False_low = models.IntegerField() first_True_low = models.IntegerField() # Decision values last_False_val_low = models.FloatField() first_True_val_low = models.FloatField() # Lists decision_list_low = models.StringField() no_reminder_list_low = models.StringField() reminder_list_low = models.StringField() ## Control questions control_q1 = models.PositiveIntegerField( choices=[ [0, 'You will get a recommendation. You will pay the cost listed on the right.'], [1, 'You will NOT get a recommendation. You will pay the cost listed on the left.'], ], initial=None, widget=widgets.RadioSelectHorizontal, ) control_q2 = models.PositiveIntegerField( choices=[[0, 'Only once.'], [1, 'Each round.']], initial=None, widget=widgets.RadioSelectHorizontal, ) control_q3 = models.PositiveIntegerField( choices=[i for i in range(Constants.no_decisions - 11, Constants.no_decisions + 9)], initial=None, ) # FUNCTIONS def creating_session(subsession: Subsession): MPL_sequence = Constants.MPL_sequence.copy() # shuffle the list random.shuffle(MPL_sequence) # make a cycle out of the shuffled list MPL_seq = itertools.cycle(MPL_sequence) for p in subsession.get_players(): # Establishes task ordering & Incentives for Math Task if subsession.round_number == 1: p.participant.vars['MPL_sequence'] = next(MPL_seq) p.participant.vars['MPL_max_amount'] = Constants.max_amount p.participant.vars['MPL_increments'] = Constants.increments p.participant.vars['MPL_no_decisions'] = Constants.no_decisions p.task = Constants.task p.MPL_sequence = p.participant.vars['MPL_sequence'] # MPL basics p.max_amount = p.participant.vars['MPL_max_amount'] p.increments = p.participant.vars['MPL_increments'] p.no_decisions = p.participant.vars['MPL_no_decisions'] def control_q1_error_message(player: Player, value): """Customized error message for control question 1.""" cond = value != 0 if cond: return 'Your answer is incorrect. Please try again!' def control_q2_error_message(player: Player, value): """Customized error message for control question 2.""" cond = value != 1 if cond: return 'Your answer is incorrect. Please try again!' # def control_q3_error_message(self,value): # """Customized error message for control question 3.""" # cond = (value != Constants.no_decisions) # if cond: # return 'Your input is incorrect. Please try again!' # PAGES class Instructions_1(Page): @staticmethod def is_displayed(player: Player): return player.round_number == 1 form_model = 'player' form_fields = ['Instructions_1_warnings', 'Instructions_1_time_spent'] @staticmethod def js_vars(player: Player): return dict(page_name='Instructions_1') class Instructions_2(Page): @staticmethod def is_displayed(player: Player): return player.round_number == 1 form_model = 'player' form_fields = ['Instructions_2_warnings', 'Instructions_2_time_spent'] @staticmethod def js_vars(player: Player): return dict(page_name='Instructions_2') class MPL_Instructions(Page): @staticmethod def is_displayed(player: Player): return player.round_number == 1 form_model = 'player' form_fields = [ 'control_q1', 'control_q2', #'control_q3', 'MPL_Instructions_warnings', 'MPL_Instructions_time_spent', ] @staticmethod def js_vars(player: Player): return dict(page_name='MPL_Instructions') @staticmethod def error_message(player: Player, values): """Customized error message for control question 2. The error message is not actually displayed. This function simply validates the form for us. For the actual error message code look at the html code of the page. """ cond_1 = values['control_q1'] != 0 cond_2 = values['control_q2'] != 1 # cond_3 = (values['control_q3'] != Constants.no_decisions) if cond_1: return 'Your input is incorrect! Please read the instructions again.' elif cond_2: return 'Your input is incorrect! Please read the instructions again.' # elif cond_3: # return 'Your input is incorrect! Please read the instructions again.' class MPL_high_Intro(Page): @staticmethod def is_displayed(player: Player): if player.MPL_sequence == 'HighLow': in_round = 1 elif player.MPL_sequence == 'LowHigh': in_round = 2 return player.round_number == in_round @staticmethod def vars_for_template(player: Player): pwd_piecerate = Constants.pwd_piecerate_high math_piecerate = Constants.math_piecerate_high max_payoff = (pwd_piecerate * Constants.num_pwd_tasks) + ( math_piecerate * Constants.num_math_tasks ) ex_pwd = 5 ex_math = 5 example_payoff = (pwd_piecerate * 5) + (math_piecerate * 5) return dict( pwd_piecerate=pwd_piecerate, math_piecerate=math_piecerate, max_payoff=max_payoff, ex_pwd=ex_pwd, ex_math=ex_math, example_payoff=example_payoff, ) class MPL_high(Page): @staticmethod def is_displayed(player: Player): if player.MPL_sequence == 'HighLow': in_round = 1 elif player.MPL_sequence == 'LowHigh': in_round = 2 return player.round_number == in_round form_model = 'player' form_fields = [ 'last_False_high', 'first_True_high', 'last_False_val_high', 'first_True_val_high', 'decision_list_high', 'reminder_list_high', 'no_reminder_list_high', 'MPL_high_warnings', 'MPL_high_time_spent', ] @staticmethod def vars_for_template(player: Player): pwd_piecerate = Constants.pwd_piecerate_high math_piecerate = Constants.math_piecerate_high max_payoff = (pwd_piecerate * Constants.num_pwd_tasks) + ( math_piecerate * Constants.num_math_tasks ) ex_pwd = 5 ex_math = 5 example_payoff = (pwd_piecerate * 5) + (math_piecerate * 5) return dict( pwd_piecerate=pwd_piecerate, math_piecerate=math_piecerate, max_payoff=max_payoff, ex_pwd=ex_pwd, ex_math=ex_math, example_payoff=example_payoff, ) @staticmethod def js_vars(player: Player): return dict( page_name='MPL_high', max_amount=Constants.max_amount, increments=Constants.increments, no_decisions=Constants.no_decisions, ) @staticmethod def before_next_page(player: Player, timeout_happened): player.participant.vars['MPL_last_False_high'] = player.last_False_high player.participant.vars['MPL_first_True_high'] = player.first_True_high player.participant.vars['MPL_last_False_val_high'] = player.last_False_val_high player.participant.vars['MPL_first_True_val_high'] = player.first_True_val_high player.participant.vars['MPL_decision_list_high'] = json.loads(player.decision_list_high) player.participant.vars['MPL_reminder_list_high'] = json.loads(player.reminder_list_high) player.participant.vars['MPL_no_reminder_list_high'] = json.loads( player.no_reminder_list_high ) class MPL_low_Intro(Page): @staticmethod def is_displayed(player: Player): if player.MPL_sequence == 'HighLow': in_round = 2 elif player.MPL_sequence == 'LowHigh': in_round = 1 return player.round_number == in_round @staticmethod def vars_for_template(player: Player): pwd_piecerate = Constants.pwd_piecerate_low math_piecerate = Constants.math_piecerate_low max_payoff = (pwd_piecerate * Constants.num_pwd_tasks) + ( math_piecerate * Constants.num_math_tasks ) return dict( pwd_piecerate=pwd_piecerate, math_piecerate=math_piecerate, max_payoff=max_payoff ) class MPL_low(Page): @staticmethod def is_displayed(player: Player): if player.MPL_sequence == 'LowHigh': in_round = 1 elif player.MPL_sequence == 'HighLow': in_round = 2 return player.round_number == in_round form_model = 'player' form_fields = [ 'last_False_low', 'first_True_low', 'last_False_val_low', 'first_True_val_low', 'decision_list_low', 'reminder_list_low', 'no_reminder_list_low', 'MPL_low_warnings', 'MPL_low_time_spent', ] @staticmethod def vars_for_template(player: Player): pwd_piecerate = Constants.pwd_piecerate_low math_piecerate = Constants.math_piecerate_low max_payoff = (pwd_piecerate * Constants.num_pwd_tasks) + ( math_piecerate * Constants.num_math_tasks ) ex_pwd = 5 ex_math = 5 example_payoff = (pwd_piecerate * 5) + (math_piecerate * 5) return dict( pwd_piecerate=pwd_piecerate, math_piecerate=math_piecerate, max_payoff=max_payoff, ex_pwd=ex_pwd, ex_math=ex_math, example_payoff=example_payoff, ) @staticmethod def js_vars(player: Player): return dict( page_name='MPL_low', max_amount=Constants.max_amount, increments=Constants.increments, no_decisions=Constants.no_decisions, ) @staticmethod def before_next_page(player: Player, timeout_happened): player.participant.vars['MPL_last_False_low'] = player.last_False_low player.participant.vars['MPL_first_True_low'] = player.first_True_low player.participant.vars['MPL_last_False_val_low'] = player.last_False_val_low player.participant.vars['MPL_first_True_val_low'] = player.first_True_val_low player.participant.vars['MPL_decision_list_low'] = json.loads(player.decision_list_low) player.participant.vars['MPL_reminder_list_low'] = json.loads(player.reminder_list_low) player.participant.vars['MPL_no_reminder_list_low'] = json.loads( player.no_reminder_list_low ) class MPL_Outro(Page): @staticmethod def is_displayed(player: Player): return player.round_number == Constants.num_rounds page_sequence = [ Instructions_1, # Instructions_2, MPL_Instructions, MPL_high, MPL_low, ]