from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range, ) import random import itertools author = 'Hamideh Mohtashami Borzadaran' doc = """ Your app description """ class Constants(BaseConstants): name_in_url = 'Experiment3' players_per_group = 2 num_rounds = 25 # """Amount allocated to each player""" multiplier = 0.75 pounds = 0.05 fixed = 1.10 def random_number(): import random num_rand = random.random() if num_rand > 0.5: return 1 else: return 0 def set_scale_choices_list(length): choices_list = [] for i in range(length): choices_list.append((i + 1, str(i + 1))) return choices_list def make_scale_field(label_string, length): return models.IntegerField( choices=set_scale_choices_list(length), widget=widgets.RadioSelectHorizontal, label=label_string # blank=True ) class Subsession(BaseSubsession): def creating_session(self): # treatments for p in self.get_groups(): if p.id_in_subsession: pressures = itertools.cycle([2, 1]) for player in self.get_groups(): player.code_treatment = next(pressures) if p.code_treatment == 1: p.treatment = "luck" else: p.treatment = "merit" for p in self.get_groups(): if p.id_in_subsession: codes = itertools.cycle([1, 2]) for player in self.get_groups(): player.codes = next(codes) # treatment in player section for p in self.get_players(): p.treatment = p.group.treatment p.codes = p.group.codes for p in self.get_players(): if p.treatment == "luck": if p.codes == 1: if p.id_in_group == 1: p.your_type = "high" p.my_type = 1 p.my_endowment = 30 p.other_endowment = 10 elif p.id_in_group == 2: p.your_type = "low" p.my_type = 2 p.my_endowment = 10 p.other_endowment = 30 elif p.codes == 2: if p.id_in_group == 1: p.your_type = "low" p.my_type = 2 p.my_endowment = 10 p.other_endowment = 30 elif p.id_in_group == 2: p.your_type = "high" p.my_type = 1 p.my_endowment = 30 p.other_endowment = 10 # real competition task for p in self.get_players(): letter = [str('A'), str('B'), str('C'), str('D'), str('E'), str('F'), str('G'), str('H'), str('I'), str('J'), str('K'), str('L'), str('M'), str('N'), str('O'), str('P'), str('Q'), str('R'), str('S'), str('T'), str('U'), str('V'), str('W'), str('X'), str('Y'), str('Z')] p.random_letter_1 = random.choice(letter) p.random_letter_2 = random.choice(letter) for p in self.get_players(): rand = [int(1), int(2), int(3), int(4), int(5), int(6), int(7), int(8), int(9), int(10), int(11), int(12), int(13), int(14), int(15), int(16), int(17), int(18), int(19), int(20), int(21), int(22), int(23), int(24), int(25), int(26), int(27), int(28), int(29), int(30), int(31), int(32), int(33), int(34), int(35), int(36), int(37), int(38), int(39), int(40), int(41), int(42), int(43), int(44), int(45), int(46), int(47), int(48), int(49), int(50), int(51), int(52), int(53), int(54), int(55), int(56), int(57), int(58), int(59), int(60), int(61), int(62), int(63), int(64), int(65), int(66), int(67), int(68), int(69), int(70), int(71), int(72), int(73), int(74), int(75), int(76), int(77), int(78), int(79), int(80), int(81), int(82), int(83), int(84), int(85), int(86), int(87), int(88), int(89), int(90), int(91), int(92), int(93), int(94), int(95), int(96), int(97), int(98), int(99), int(100)] p.digits1 = random.choice(rand) rand.remove(p.digits1) p.digits2 = random.choice(rand) rand.remove(p.digits2) p.digits3 = random.choice(rand) rand.remove(p.digits3) p.digits4 = random.choice(rand) rand.remove(p.digits4) p.digits5 = random.choice(rand) rand.remove(p.digits5) p.digits6 = random.choice(rand) rand.remove(p.digits6) p.digits7 = random.choice(rand) rand.remove(p.digits7) p.digits8 = random.choice(rand) rand.remove(p.digits8) p.digits9 = random.choice(rand) rand.remove(p.digits9) p.digits10 = random.choice(rand) rand.remove(p.digits10) p.digits11 = random.choice(rand) rand.remove(p.digits11) p.digits12 = random.choice(rand) rand.remove(p.digits12) p.digits13 = random.choice(rand) rand.remove(p.digits13) p.digits14 = random.choice(rand) rand.remove(p.digits14) p.digits15 = random.choice(rand) rand.remove(p.digits15) p.digits16 = random.choice(rand) rand.remove(p.digits16) p.digits17 = random.choice(rand) rand.remove(p.digits17) p.digits18 = random.choice(rand) rand.remove(p.digits18) p.digits19 = random.choice(rand) rand.remove(p.digits19) p.digits20 = random.choice(rand) rand.remove(p.digits20) p.digits21 = random.choice(rand) rand.remove(p.digits21) p.digits22 = random.choice(rand) rand.remove(p.digits22) p.digits23 = random.choice(rand) rand.remove(p.digits23) p.digits24 = random.choice(rand) rand.remove(p.digits24) p.digits25 = random.choice(rand) rand.remove(p.digits25) p.digits26 = random.choice(rand) rand.remove(p.digits26) # roles and endowment for p in self.get_players(): if p.random_letter_1 == 'A': p.answer_1 = p.digits1 elif p.random_letter_1 == 'B': p.answer_1 = p.digits2 elif p.random_letter_1 == 'C': p.answer_1 = p.digits3 elif p.random_letter_1 == 'D': p.answer_1 = p.digits4 elif p.random_letter_1 == 'E': p.answer_1 = p.digits5 elif p.random_letter_1 == 'F': p.answer_1 = p.digits6 elif p.random_letter_1 == 'G': p.answer_1 = p.digits7 elif p.random_letter_1 == 'H': p.answer_1 = p.digits8 elif p.random_letter_1 == 'I': p.answer_1 = p.digits9 elif p.random_letter_1 == 'J': p.answer_1 = p.digits10 elif p.random_letter_1 == 'K': p.answer_1 = p.digits11 elif p.random_letter_1 == 'L': p.answer_1 = p.digits12 elif p.random_letter_1 == 'M': p.answer_1 = p.digits13 elif p.random_letter_1 == 'N': p.answer_1 = p.digits14 elif p.random_letter_1 == 'O': p.answer_1 = p.digits15 elif p.random_letter_1 == 'P': p.answer_1 = p.digits16 elif p.random_letter_1 == 'Q': p.answer_1 = p.digits17 elif p.random_letter_1 == 'R': p.answer_1 = p.digits18 elif p.random_letter_1 == 'S': p.answer_1 = p.digits19 elif p.random_letter_1 == 'T': p.answer_1 = p.digits20 elif p.random_letter_1 == 'U': p.answer_1 = p.digits21 elif p.random_letter_1 == 'V': p.answer_1 = p.digits22 elif p.random_letter_1 == 'W': p.answer_1 = p.digits23 elif p.random_letter_1 == 'X': p.answer_1 = p.digits24 elif p.random_letter_1 == 'Y': p.answer_1 = p.digits25 elif p.random_letter_1 == 'Z': p.answer_1 = p.digits26 for p in self.get_players(): if p.random_letter_2 == 'A': p.answer_2 = p.digits1 elif p.random_letter_2 == 'B': p.answer_2 = p.digits2 elif p.random_letter_2 == 'C': p.answer_2 = p.digits3 elif p.random_letter_2 == 'D': p.answer_2 = p.digits4 elif p.random_letter_2 == 'E': p.answer_2 = p.digits5 elif p.random_letter_2 == 'F': p.answer_2 = p.digits6 elif p.random_letter_2 == 'G': p.answer_2 = p.digits7 elif p.random_letter_2 == 'H': p.answer_2 = p.digits8 elif p.random_letter_2 == 'I': p.answer_2 = p.digits9 elif p.random_letter_2 == 'J': p.answer_2 = p.digits10 elif p.random_letter_2 == 'K': p.answer_2 = p.digits11 elif p.random_letter_2 == 'L': p.answer_2 = p.digits12 elif p.random_letter_2 == 'M': p.answer_2 = p.digits13 elif p.random_letter_2 == 'N': p.answer_2 = p.digits14 elif p.random_letter_2 == 'O': p.answer_2 = p.digits15 elif p.random_letter_2 == 'P': p.answer_2 = p.digits16 elif p.random_letter_2 == 'Q': p.answer_2 = p.digits17 elif p.random_letter_2 == 'R': p.answer_2 = p.digits18 elif p.random_letter_2 == 'S': p.answer_2 = p.digits19 elif p.random_letter_2 == 'T': p.answer_2 = p.digits20 elif p.random_letter_2 == 'U': p.answer_2 = p.digits21 elif p.random_letter_2 == 'V': p.answer_2 = p.digits22 elif p.random_letter_2 == 'W': p.answer_2 = p.digits23 elif p.random_letter_2 == 'X': p.answer_2 = p.digits24 elif p.random_letter_2 == 'Y': p.answer_2 = p.digits25 elif p.random_letter_2 == 'Z': p.answer_2 = p.digits26 # prolific ID for p in self.get_players(): p.Prolific_ID = p.participant.label class Group(BaseGroup): treatment = models.StringField() code_treatment = models.IntegerField() codes = models.IntegerField() total_contribution = models.IntegerField() individual_share = models.FloatField() total_contribution_estimate = models.IntegerField() total_payoff = models.FloatField() sum_of_correct = models.IntegerField(label='', initial=0) total_correct = models.IntegerField(label='', initial=0) other_correct = models.IntegerField(label='', initial=0) def set_treatment(self): self.in_round(Constants.num_rounds).sum_of_correct = sum([p.in_round(Constants.num_rounds).total_correct for p in self.get_players()]) for p in self.get_players(): p.in_round(Constants.num_rounds).other_correct = \ self.in_round(Constants.num_rounds).sum_of_correct - p.in_round(Constants.num_rounds).total_correct my_type = models.IntegerField() your_type = models.StringField() def role(self): for p in self.get_players(): if p.round_number == Constants.num_rounds: if p.treatment == "merit": if p.total_correct > p.other_correct: p.your_type = "high" p.my_type = 3 p.my_endowment = 30 p.other_endowment = 10 elif p.total_correct < p.other_correct: p.your_type = "low" p.my_type = 4 p.my_endowment = 10 p.other_endowment = 30 elif p.total_correct == p.other_correct and p.codes == 1: if p.id_in_group == 1: p.your_type = "high" p.my_type = 5 p.my_endowment = 30 p.other_endowment = 10 else: p.your_type = "low" p.my_type = 6 p.my_endowment = 10 p.other_endowment = 30 elif p.total_correct == p.other_correct and p.codes == 2: if p.id_in_group == 1: p.your_type = "low" p.my_type = 6 p.my_endowment = 10 p.other_endowment = 30 else: p.your_type = "high" p.my_type = 5 p.my_endowment = 30 p.other_endowment = 10 def set_payoffs(self): self.total_contribution = sum([p.contribution for p in self.get_players()]) self.total_contribution_estimate = sum([p.contribution_estimate for p in self.get_players()]) self.individual_share = ( self.total_contribution * Constants.multiplier ) # / Constants.players_per_group for p in self.get_players(): p.my_payoff = (p.my_endowment - p.contribution) + self.individual_share for p in self.get_players(): p.other_contribution = self.total_contribution - p.contribution for p in self.get_players(): p.other_contribution_estimate = self.total_contribution_estimate - p.contribution_estimate for p in self.get_players(): if p.contribution_estimate == p.other_contribution: p.estimate_pay = 10 else: p.estimate_pay = 0 self.total_payoff = sum([p.my_payoff for p in self.get_players()]) for p in self.get_players(): p.other_payoff = self.total_payoff - p.my_payoff p.bonus_earnings = round(((p.my_payoff + p.estimate_pay) * Constants.pounds),2) p.fixed_earnings = Constants.fixed p.final_earnings = round(p.fixed_earnings + p.bonus_earnings,2) class Player(BasePlayer): Prolific_ID = models.StringField( label="Prolific ID", ) your_type = models.StringField() my_endowment = models.IntegerField() other_endowment = models.IntegerField() treatment = models.StringField() codes = models.IntegerField() digits1 = models.IntegerField() digits2 = models.IntegerField() digits3 = models.IntegerField() digits4 = models.IntegerField() digits5 = models.IntegerField() digits6 = models.IntegerField() digits7 = models.IntegerField() digits8 = models.IntegerField() digits9 = models.IntegerField() digits10 = models.IntegerField() digits11 = models.IntegerField() digits12 = models.IntegerField() digits13 = models.IntegerField() digits14 = models.IntegerField() digits15 = models.IntegerField() digits16 = models.IntegerField() digits17 = models.IntegerField() digits18 = models.IntegerField() digits19 = models.IntegerField() digits20 = models.IntegerField() digits21 = models.IntegerField() digits22 = models.IntegerField() digits23 = models.IntegerField() digits24 = models.IntegerField() digits25 = models.IntegerField() digits26 = models.IntegerField() random_letter_1 = models.StringField() random_letter_2 = models.StringField() digit_response_1 = models.IntegerField(label='', min=0, max=100) digit_response_2 = models.IntegerField(label='', min=0, max=100) answer_1 = models.IntegerField() answer_2 = models.IntegerField() correct = models.IntegerField(label='', initial=0) incorrect = models.IntegerField(label='', initial=0) def correct_answers(self): if {self.answer_1 == self.digit_response_1 and self.answer_2 == self.digit_response_2}: self.correct = 1 else: self.incorrect = 1 def digit_response_1_error_message(self, value): if value != self.answer_1: error_message = "Your answer is incorrect, please try again" return error_message def digit_response_2_error_message(self, value): if value != self.answer_2: error_message = "Your answer is incorrect, please try again" return error_message totalNumAttempted = models.FloatField() totalNumCorrect = models.IntegerField() total_correct = models.IntegerField(label='', initial=0) other_correct = models.IntegerField(label='', initial=0) sum_of_correct = models.IntegerField(label='', initial=0) total_incorrect = models.IntegerField(label='', initial=0) correct_prev = models.IntegerField(label='', initial=0) my_type = models.IntegerField() def sum_answer(self): self.totalNumCorrect = sum([p.correct for p in self.in_all_rounds()]) def prev_correct(self): if self.round_number != 0: self.in_round(self.round_number+1).correct_prev = self.in_round(self.round_number).totalNumCorrect else: self.correct_prev = 0 def show_answer(self): self.in_round(Constants.num_rounds).total_correct = sum([p.correct for p in self.in_all_rounds()]) self.in_round(Constants.num_rounds).total_incorrect = sum([p.incorrect for p in self.in_all_rounds()]) self.in_round(Constants.num_rounds).totalNumAttempted = \ self.in_round(Constants.num_rounds).total_correct + self.in_round(Constants.num_rounds).total_incorrect self.group.total_correct = self.in_round(Constants.num_rounds).total_correct self.in_round(Constants.num_rounds).sum_of_correct = \ self.in_round(Constants.num_rounds).group.sum_of_correct self.in_round(Constants.num_rounds).other_correct = \ self.in_round(Constants.num_rounds).group.other_correct #self.in_round(Constants.num_rounds).other_correct = \ #self.in_round(Constants.num_rounds).sum_of_correct - self.in_round(Constants.num_rounds).total_correct ########################################################## ################################################ contribution = models.IntegerField( label="Please now enter your contribution decision:", min=0, ) def contribution_error_message(self, value): contribution_answer_equal = self.my_endowment if value > contribution_answer_equal: error_message = "You cannot contribute more than the number of tokens you have been allocated. " \ "Please try again." return error_message ################################################ contribution_estimate = models.IntegerField( label="How many tokens do you estimate that the other group member you are matched with has contributed?", min=0, ) def contribution_estimate_error_message(self, value): contribution_estimate_answer_equal = self.other_endowment if value > contribution_estimate_answer_equal: error_message = "Your estimate cannot exceed the number of tokens the other group member has been " \ "allocated. Please try again." return error_message ################################################ other_contribution = models.IntegerField(label="", initial=0) other_contribution_estimate = models.IntegerField(label="", initial=0) other_payoff = models.FloatField(label="", initial=0) bonus_earnings = models.FloatField(label="", initial=0) fixed_earnings = models.FloatField(label="", initial=0) final_earnings = models.FloatField(label="", initial=0) my_payoff = models.FloatField(label="", initial=0) estimate_pay = models.FloatField(label="", initial=0) ################################################ control_question = models.StringField( choices=[ ['sequential_public_good_2', 'I agree to take part. Take me to the study.'], ['2', 'I do not agree to take part in this study. Take me back to Prolific.'], ], label="Do you agree to participate in this study?", widget=widgets.RadioSelect ) def control_question_error_message(self, value): correct_answer = 'sequential_public_good_2' if value != correct_answer: error_message = "If you do not agree to take part in this study, please close your browser tab." return error_message ################################################ question1 = models.IntegerField( label="", min=0, ) def question1_error_message(self, value): correct_unequal_q1 = 10 if self.treatment == 'luck' and value != correct_unequal_q1: error_unequal_q1 = "Answer: (10 - 0) + 0.75 x 0 = 10 points" return error_unequal_q1 elif self.treatment == 'merit' and value != correct_unequal_q1: error_unequal_q1 = "Answer: (10 - 0) + 0.75 x 0 = 10 points" return error_unequal_q1 ################################################ question2 = models.IntegerField( label="", min=0, ) def question2_error_message(self, value): correct_unequal_q2 = 31 if self.treatment == 'luck' and value != correct_unequal_q2: error_unequal_q2 = "Answer: (30 - 8) + 0.75 x 12 = 31 points" return error_unequal_q2 elif self.treatment == 'merit' and value != correct_unequal_q2: error_unequal_q2 = "Answer: (30 - 8) + 0.75 x 12 = 31 points" return error_unequal_q2 ################################################ bond_before = make_scale_field("I feel a bond with the other group member.", 7) solidarity_before = make_scale_field("I feel solidarity with the other group member.", 7) committed_before = make_scale_field("I feel committed to the other group member.", 7) glad_before = make_scale_field("I am glad to be with the other group member.", 7) proud_before = make_scale_field("I think that the other group member has a lot to be proud of.", 7) pleasant_before = make_scale_field("It is pleasant to be with the other group member.", 7) good_feeling_before = make_scale_field("Being with the other group member gives me a good feeling.", 7) member_before = make_scale_field("I often think about the fact that I am one member in the group.", 7) identity_before = make_scale_field("The fact that I am one member in the group is an important part of my " "identity.", 7) attention_check_before = make_scale_field("To see whether you respond carefully, please select ‘slightly disagree’ " "for this question.", 7) see_my_self_before = make_scale_field("Being one member in the group is an important part of how I see myself.", 7) common_before = make_scale_field("I have a lot in common with the other group member.", 7) similar_before = make_scale_field("I am similar to the other group member.", 7) a_lot_before = make_scale_field("The other group member has a lot in common with myself.", 7) similar_to_me_before = make_scale_field("The other group member is similar to myself.", 7) ################################################ ################################################ bond_after = make_scale_field("I feel a bond with the other group member.", 7) solidarity_after = make_scale_field("I feel solidarity with the other group member.", 7) committed_after = make_scale_field("I feel committed to the other group member.", 7) glad_after = make_scale_field("I am glad to be with the other group member.", 7) proud_after = make_scale_field("I think that the other group member has a lot to be proud of.", 7) pleasant_after = make_scale_field("It is pleasant to be with the other group member.", 7) good_feeling_after = make_scale_field("Being with the other group member gives me a good feeling.", 7) member_after = make_scale_field("I often think about the fact that I am one member in the group.", 7) identity_after = make_scale_field("The fact that I am one member in the group is an important part of my " "identity.", 7) attention_check_after = make_scale_field("To see whether you respond carefully, please select ‘slightly disagree’ " "for this question.", 7) see_my_self_after = make_scale_field("Being one member in the group is an important part of how I see myself.", 7) common_after = make_scale_field("I have a lot in common with the other group member.", 7) similar_after = make_scale_field("I am similar to the other group member.", 7) a_lot_after = make_scale_field("The other group member has a lot in common with myself.", 7) similar_to_me_after = make_scale_field("The other group member is similar to myself.", 7) ################################################ gender = models.StringField( choices=[ ['sequential_public_good_2', 'Male'], ['2', 'Female'], ['3', 'Other'], ], label="sequential_public_good_2. What is your gender?", widget=widgets.RadioSelect ) other_gender_belief = models.StringField( choices=[ ['sequential_public_good_2', 'Male'], ['2', 'Female'], ['3', 'Other'], ], label="2. What do you think was the gender of the other group member you were matched with?", widget=widgets.RadioSelect ) age = models.IntegerField( label="3. What is your age?", min = 0, ) height = models.StringField( label="4. What is your height (in cm)? ", ) #def hight_error_message(self, value): #if value == : #error_message = "Your other group member cannot contribution more than their endowment. " #return error_message language = models.StringField( choices=[ ['sequential_public_good_2', 'Yes'], ['2', 'No'], ], label="5. Is English your first language?", widget=widgets.RadioSelect ) max_income = models.StringField( choices=[ ['sequential_public_good_2', 'Very important'], ['2', 'Important'], ['3', 'Indifferent'], ['3', 'Not important'], ['3', 'Not important at all'], ], label="6. How important was for you to maximise your own income during the experiment?", widget=widgets.RadioSelect ) trust = models.StringField( choices=[ ['sequential_public_good_2', 'Most people can be trusted'], ['2', 'You need to be very careful in dealing with people'], ], label="7. Generally speaking, would you say that most people can be trusted or that you need to be very " "careful in dealing with people?", widget=widgets.RadioSelect ) risk = models.StringField( choices=[ ['sequential_public_good_2', ''], ['2', ''], ['3', ''], ['4', ''], ['5', ''], ['6', ''], ['7', ''], ['8', ''], ['9', ''], ['10', ''], ], label="", widget=widgets.RadioSelectHorizontal ) instructions = models.StringField( choices=[ ['sequential_public_good_2', 'Very difficult'], ['2', 'Difficult'], ['3', 'Neutral'], ['4', 'Easy'], ['5', 'Very easy'], ], label="9. How did you find the instructions?", widget=widgets.RadioSelect ) ################################################ fair_contribute = models.IntegerField( label="", min=0, ) def fair_contribute_error_message(self, value): contribution_estimate_answer_equal = self.my_endowment if value > contribution_estimate_answer_equal: error_message = "You cannot contribute more than the number of tokens you have been allocated." return error_message ################################################ other_fair_contribute = models.IntegerField( label="", min=0, ) def other_fair_contribute_error_message(self, value): contribution_estimate_answer_equal = self.other_endowment if value > contribution_estimate_answer_equal: error_message = "The other group member cannot contribute more than the number of tokens they have been " \ "allocated." return error_message ################################################ econ_exp = models.IntegerField( label="12. How many economics experiments have you participated in before this one? ", ) feedback = models.StringField( blank=True, label="13. Do you have any other comments or feedback regarding this experiment?", ) ################################################