from otree.api import * import random #import string # import csv doc = """ Your app description """ # Payoff rule # Idea: We select a random number between 0 and 10. If 0 is picked the first decision is taken and so on. Then, for the taken decision, the binarized scoring rule is applied. # this has to be repeated for the other beliefs as well ... ########################################################################################################### ################################## MODELS ################################ ########################################################################################################### class Constants(BaseConstants): name_in_url = 'work_memory_beliefs' players_per_group = 10 num_rounds = 1 first_role = '10' second_role = '20' third_role = '30' fourth_role = '40' fifth_role = '50' sixth_role = '60' seventh_role = '70' eigth_role = '80' ninth_role = '90' tenth_role = '100' base_payment = 14 extra_payoff = 6 days_single = 14 days_double = 28 base_tasks = 40 QuestionnaireChoices = [ [1, '1'], [2, '2'], [3, '3'], [4, '4'], [5, '5'], ] class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): Melessa_ID = models.StringField() PositiveFeedback = models.IntegerField() NegativeFeedback = models.IntegerField() ConfirmPosFeedback = models.IntegerField(label='', min=0, max=3, blank=True) ConfirmNegFeedback = models.IntegerField(label='', min=0, max=3, blank=True) payoutrelevant1 = models.IntegerField(initial=10) extraPayoff1 = models.IntegerField(initial=0) BeliefTopHalf1 = models.IntegerField( label='Your guess: (enter a value between 0 and 100)', max=100, min=0, initial=None, ) details_matching=models.BooleanField(initial=False) details_beliefs_1_1=models.BooleanField(initial=False) details_beliefs_1_2 = models.BooleanField(initial=False) details_beliefs_1_3 = models.BooleanField(initial=False) details_beliefs_1_4 = models.BooleanField(initial=False) details_feedback_1 = models.BooleanField(initial=False) BeliefBottomHalf1 = models.IntegerField(initial=None) Belief1_1 = models.IntegerField(min=0, max=100, initial=None) Belief2_1 = models.IntegerField(min=0, max=100, initial=None) Belief3_1 = models.IntegerField(min=0, max=100, initial=None) Belief4_1 = models.IntegerField(min=0, max=100, initial=None) Belief5_1 = models.IntegerField(min=0, max=100, initial=None) Belief6_1 = models.IntegerField(min=0, max=100, initial=None) Belief7_1 = models.IntegerField(min=0, max=100, initial=None) Belief8_1 = models.IntegerField(min=0, max=100, initial=None) Belief9_1 = models.IntegerField(min=0, max=100, initial=None) Belief10_1 = models.IntegerField(min=0, max=100, initial=None) matching_control_1 = models.IntegerField( label='Imagine one person out of your groups has to solve 40 additional sequences. Is it possible that you also have to solve 40 additional sequences?', choices=[ [0, 'Yes'], [1, 'No'], ], #widget=widgets.RadioSelectVertical, blank=True, ) matching_control_2 = models.IntegerField( label='What is more likely: That a participant is assigned to solve 8 additional sequences or that a participant is assigned to solve 80 additional sequences?', choices=[ [0, 'It is more likely that you have to solve 8 than 80 additional sequences.'], [1, 'Both are equally likely.'], [2, 'It is more probable that you have to solve 80 than 80 additional sequences.'], ], #widget=widgets.RadioSelectVertical, blank=True ) feedback_order = models.IntegerField() ########################################################################################################### ################################## FUNCTIONS ################################ ########################################################################################################### #Get the variable Melessa ID from the other app def get_id(player:Player): player.Melessa_ID = player.participant.melessa_id # This function determines whether or not the player receives extra payoff. This depends on his stated beliefs. # e use the binarized scoring rule # Only one out of all beliefs are payoff relevant. # This Function works as follows: First, I determine which belief of the 11 first ones is payout relevant, # then I determine the payoff according to the binarized scoring rule # THIS FUNCTION SHOULD WORK FINE def set_extrapayoff1(player: Player): player.payoutrelevant1 = random.randint(0, 10) if player.payoutrelevant1 == 0: if player.role == '10' and player.BeliefTopHalf1 > max([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.role == '20' and player.BeliefTopHalf1 > max([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.role == '30' and player.BeliefTopHalf1 > max([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.role == '40' and player.BeliefTopHalf1 > max([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.role == '50' and player.BeliefTopHalf1 > max([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.role == '60' and player.BeliefTopHalf1 < min([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.role == '70' and player.BeliefTopHalf1 < min([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.role == '80' and player.BeliefTopHalf1 < min([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.role == '90' and player.BeliefTopHalf1 < min([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.role == '100' and player.BeliefTopHalf1 < min([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff else: player.extraPayoff1 = 0 if player.payoutrelevant1 == 1: if player.role == '10' and player.Belief1_1 > max([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.role != '10' and player.Belief1_1 < min([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff else: player.extraPayoff1 = 0 if player.payoutrelevant1 == 2: if player.role == '20' and player.Belief2_1 > max([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.role != '20' and player.Belief2_1 < min([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff else: player.extraPayoff1 = 0 if player.payoutrelevant1 == 3: if player.role == '30' and player.Belief3_1 > max([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.role != '30' and player.Belief3_1 < min([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff else: player.extraPayoff1 = 0 if player.payoutrelevant1 == 4: if player.role == '40' and player.Belief4_1 > max([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.role != '40' and player.Belief4_1 < min([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff else: player.extraPayoff1 = 0 if player.payoutrelevant1 == 5: if player.role == '50' and player.Belief5_1 > max([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.role != '50' and player.Belief5_1 < min([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff else: player.extraPayoff1 = 0 if player.payoutrelevant1 == 6: if player.role == '60' and player.Belief6_1 > max([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.role != '60' and player.Belief6_1 < min([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff else: player.extraPayoff1 = 0 if player.payoutrelevant1 == 7: if player.role == '70' and player.Belief7_1 > max([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.role != '70' and player.Belief7_1 < min([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff else: player.extraPayoff1 = 0 if player.payoutrelevant1 == 8: if player.role == '80' and player.Belief8_1 > max([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.role != '80' and player.Belief8_1 < min([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff else: player.extraPayoff1 = 0 if player.payoutrelevant1 == 9: if player.role == '90' and player.Belief9_1 > max([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.role != '90' and player.Belief9_1 < min([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff else: player.extraPayoff1 = 0 if player.payoutrelevant1 == 10: if player.role == '100' and player.Belief10_1 > max([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff elif player.role != '100' and player.Belief10_1 < min([random.randint(0, 100), random.randint(0, 100)]): player.extraPayoff1 = Constants.extra_payoff else: player.extraPayoff1 = 0 # Compared to three other participants, positive feedback is the number of others who are ranked worse. def set_PositiveFeedback(player): if player.role == '10': player.PositiveFeedback = 3 elif player.role == '20': player.PositiveFeedback = 0 # I don't actually compare them with the other players as it is easier without the interaction # and we know which ranks are possible newlist = random.sample([100, 10, 30, 40, 50, 60, 70, 80, 90], k=3) for m in newlist: if m > 20: player.PositiveFeedback += 1 elif player.role == '30': player.PositiveFeedback = 0 newlist = random.sample([100, 20, 10, 40, 50, 60, 70, 80, 90], k=3) for m in newlist: if m > 30: player.PositiveFeedback += 1 elif player.role == '40': player.PositiveFeedback = 0 newlist = random.sample([100, 20, 10, 30, 50, 60, 70, 80, 90], k=3) for m in newlist: if m > 40: player.PositiveFeedback += 1 elif player.role == '50': player.PositiveFeedback = 0 newlist = random.sample([100, 20, 10, 40, 30, 60, 70, 80, 90], k=3) for m in newlist: if m > 50: player.PositiveFeedback += 1 elif player.role == '60': player.PositiveFeedback = 0 newlist = random.sample([100, 20, 10, 40, 50, 30, 70, 80, 90], k=3) for m in newlist: if m > 60: player.PositiveFeedback += 1 elif player.role == '70': player.PositiveFeedback = 0 newlist = random.sample([100, 20, 10, 40, 50, 60, 30, 80, 90], k=3) for m in newlist: if m > 70: player.PositiveFeedback += 1 elif player.role == '80': player.PositiveFeedback = 0 newlist = random.sample([100, 20, 10, 40, 50, 60, 70, 30, 90], k=3) for m in newlist: if m > 80: player.PositiveFeedback += 1 elif player.role == '90': player.PositiveFeedback = 0 newlist = random.sample([100, 20, 10, 40, 50, 60, 70, 80, 30], k=3) for m in newlist: if m > 90: player.PositiveFeedback += 1 else: player.PositiveFeedback = 0 # This function defines the number of negative feedback individuals get def set_NegativeFeedback(player): player.NegativeFeedback = 3 - player.PositiveFeedback ########################################################################################################### ################################## PAGES ################################ ########################################################################################################### class MatchingB(Page): form_model = 'player' form_fields = ['matching_control_1', 'matching_control_2'] @staticmethod def is_displayed(player: Player): return player.details_matching==True @staticmethod def error_message(player: Player, values): if values['matching_control_1']!=1 or values['matching_control_2']!=1: return 'At least one of the questions was answered wrongly. Please read the instructions again and retry.' class MatchingA(Page): form_model = 'player' form_fields = ['details_matching', 'matching_control_1', 'matching_control_2'] @staticmethod def error_message(player: Player, values): if (values['matching_control_1']==None or values['matching_control_2']==None) and values['details_matching']==False: return 'You need to answer the comprehension questions' elif (values['matching_control_1']!=1 or values['matching_control_2']!=1) and values['details_matching']==False: return 'At least one of the questions was answered wrongly. Please read the instructions again and retry' class BeliefInstructions1(Page): pass class BeliefInstructions1a(Page): form_model = 'player' form_fields = ['details_beliefs_1_1'] class BeliefInstructions1b(Page): @staticmethod def is_displayed(player: Player): return player.details_beliefs_1_1==True # Here we elicit subjects belief that they are in the top half class BelievesTopHalf1(Page): form_model = 'player' form_fields = ['BeliefTopHalf1'] # on this page we want to elicit probabilistic beliefs class BeliefDistributionTopHalf1(Page): form_model = 'player' form_fields = ['Belief1_1', 'Belief2_1', 'Belief3_1', 'Belief4_1', 'Belief5_1'] @staticmethod def error_message(player:Player, values): summe = values['Belief1_1'] + values['Belief2_1'] + values['Belief3_1'] + values['Belief4_1'] + values[ 'Belief5_1'] if summe != player.BeliefTopHalf1: return 'The sum is {}. The numbers must add up to {}.'.format(summe, player.BeliefTopHalf1) # Now we have the same for probabilistic beliefs in the lower half. class BeliefDistributionBottomHalf1(Page): form_model = 'player' form_fields = ['Belief6_1', 'Belief7_1', 'Belief8_1', 'Belief9_1', 'Belief10_1'] @staticmethod def vars_for_template(player: Player): return dict( BeliefBottomHalf1=100 - player.BeliefTopHalf1 ) @staticmethod def before_next_page(player: Player, timeout_happened): player.feedback_order = random.randint(0, 1) @staticmethod def error_message(player:Player, values): summe = values['Belief6_1'] + values['Belief7_1'] + values['Belief8_1'] + values['Belief9_1'] + values[ 'Belief10_1'] if summe != 100 - player.BeliefTopHalf1: return 'The sum is {}. The numbers must add up to {}.'.format(summe, 100 - player.BeliefTopHalf1) # Here we give people the feedback class FeedbackGivenNegFirst(Page): @staticmethod def is_displayed(player: Player): return player.feedback_order == 0 @staticmethod def vars_for_template(player:Player): return dict ( PositiveFeedback = set_PositiveFeedback(player), NegativeFeedback = set_NegativeFeedback(player), ) class FeedbackGivenPosFirst(Page): @staticmethod def is_displayed(player: Player): return player.feedback_order == 1 @staticmethod def vars_for_template(player: Player): return dict( PositiveFeedback=set_PositiveFeedback(player), NegativeFeedback=set_NegativeFeedback(player), ) class FeedbackRepetitionNegFirsta(Page): @staticmethod def is_displayed(player: Player): return player.feedback_order == 0 form_model = 'player' form_fields = ['ConfirmNegFeedback', 'ConfirmPosFeedback','details_feedback_1'] @staticmethod def error_message(player: Player, values): if (values['ConfirmNegFeedback'] == None or values['ConfirmPosFeedback'] == None) and values['details_feedback_1']==False: return 'You need to fill in the fields' @staticmethod def before_next_page(player, timeout_happened): return dict( extraPayoff1=set_extrapayoff1(player), ) class FeedbackRepetitionPosFirsta(Page): @staticmethod def is_displayed(player: Player): return player.feedback_order == 1 form_model = 'player' form_fields = ['ConfirmNegFeedback', 'ConfirmPosFeedback','details_feedback_1'] @staticmethod def error_message(player: Player, values): if (values['ConfirmNegFeedback'] == None or values['ConfirmPosFeedback'] == None) and values['details_feedback_1']==False: return 'You need to fill in the fields' class FeedbackRepetitionNegFirstb(Page): @staticmethod def is_displayed(player: Player): return player.feedback_order == 0 and player.details_feedback_1==True form_model = 'player' form_fields = ['ConfirmNegFeedback', 'ConfirmPosFeedback'] @staticmethod def error_message(player: Player, values): if values['ConfirmNegFeedback']==None or values['ConfirmPosFeedback']==None: return 'You need to fill in the fields' @staticmethod def before_next_page(player, timeout_happened): return dict( extraPayoff1 = set_extrapayoff1(player), ) class FeedbackRepetitionPosFirstb(Page): @staticmethod def is_displayed(player: Player): return player.feedback_order == 1 and player.details_feedback_1==True form_model = 'player' form_fields = ['ConfirmNegFeedback', 'ConfirmPosFeedback'] @staticmethod def error_message(player: Player, values): if values['ConfirmNegFeedback']==None or values['ConfirmPosFeedback']==None: return 'You need to fill in the fields' # Now all the beliefs Stuff is repeated exactly (only minor chang in the wording if instructions) @staticmethod def before_next_page(player, timeout_happened): return dict( extraPayoff1 = set_extrapayoff1(player), ) class Part2(Page): pass page_sequence = [#Generalinstructions, Part2, MatchingA, MatchingB, BeliefInstructions1a, BeliefInstructions1b, BelievesTopHalf1, BeliefDistributionTopHalf1, BeliefDistributionBottomHalf1, FeedbackGivenNegFirst, FeedbackRepetitionNegFirsta, FeedbackRepetitionNegFirstb, FeedbackGivenPosFirst, FeedbackRepetitionPosFirsta, FeedbackRepetitionPosFirstb, #Demographics, #Big5, #LastPage ]