from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range, ) from random import randint author = 'Nanyin Yang' doc = """ Participants play 20 rounds of communication condition, continuously. """ class Constants(BaseConstants): name_in_url = 'Communication_20' players_per_group = 2 num_rounds = 20 #starting_round = num_rounds/2+1 expert_q1a = 2 expert_q2a = 4 expert_q3_1a = 119 expert_q3_2a = 104 expert_q4a = 1 expert_q5a = 2 client_q1a = 2 client_q2a = 3 client_q3a = 3 client_q4a = 1 #exchange_rate = 0.005 exchange_rate = 0.1 initial_earning = 10 ## round when the player have been selected to get paid round_selected = randint(1, num_rounds) class Subsession(BaseSubsession): #pass def creating_session(self): self.group_randomly(fixed_id_in_group=True) class Group(BaseGroup): #pass def set_payoffs(self): player1 = self.get_player_by_role('player1') player2 = self.get_player_by_role('player2') player2.set_final_treatment() player1.treatment_final = player2.treatment_final player1.treatment_final_letter = player2.treatment_final_letter player2.display_activeness() player2.display_active_cost() for p in self.get_players(): p.set_payoff() def set_problems_and_signals(self): player1 = self.get_player_by_role('player1') player2 = self.get_player_by_role('player2') for p in self.get_players(): player2.set_problem() player1.problem = player2.problem player1.problem_letter = player2.problem_letter player2.get_signal() player2.set_letter_signal() # For displaying in the payoff page # def set_final_treatments(self): # player1 = self.get_player_by_role('player1') # player2 = self.get_player_by_role('player2') # for p in self.get_players(): # player2.set_final_treatment() # player1.treatment_final = player2.treatment_final # player1.treatment_final_letter = player2.treatment_final_letter # def set_private_signals(self): # for p in self.get_players(): # if p.id_in_group == 2: # p.set_private_signal() class Player(BasePlayer): final_payment = models.FloatField(initial=0.0, min=0) problem = models.IntegerField(choices = [[0, "A"],[1, "B"]]) problem_letter = models.StringField() private_signal = models.IntegerField() private_signal_letter = models.StringField(blank = True) # Before communication diagnosis_letter1 = models.StringField(blank = True) recommend_soln_letter1 = models.StringField(blank = True) # After communication diagnosis_letter = models.StringField(blank = True) recommend_soln_letter = models.StringField(blank = True) treatment_choice = models.IntegerField(widget=widgets.RadioSelect, choices=[ [0, 'Solution A*'], [1, 'Solution B*'], ], blank=True) treatment_final = models.IntegerField() treatment_final_letter = models.StringField() #treatment_choice = models.IntegerField(blank=True) #treatment_choice_letter = models.StringField(widget=widgets.RadioSelect, choices=["Solution A*", "Solution B*"], blank = True) belief_precision = models.FloatField( choices=[ [0.5, "50%"], [0.6, "60%"], [0.7, "70%"], [0.8, "80%"], [0.9, "90%"], [1, "100%"], ], blank=True ) # expert's choice of precision # Before communication precision_choice1 = models.FloatField( choices = [ [0.5, "50%"], [0.6, "60%"], [0.7, "70%"], [0.8, "80%"], [0.9, "90%"], [1, "100%"], ], widget = widgets.RadioSelectHorizontal, blank = True ) # After communication precision_choice = models.FloatField( choices = [ [0.5, "50%"], [0.6, "60%"], [0.7, "70%"], [0.8, "80%"], [0.9, "90%"], [1, "100%"], ], widget = widgets.RadioSelectHorizontal, blank = True ) # Before communication diagnostic_result1 = models.IntegerField() diagnostic_cost1 = models.IntegerField() # After communication diagnostic_result = models.IntegerField() diagnostic_cost = models.IntegerField() # Whether to revise the precision choice revise = models.IntegerField( choices = [ [1, "Yes. Revise the diagnostic accuracy."], [0, "No. Keep my original decision."] ], widget=widgets.RadioSelectHorizontal, blank=True, label = '', ) payment = models.IntegerField() # active1 = models.IntegerField( # choices = [ # [1, 'Make own decision & Pay 30 tokens'], # [2, 'Follow the expert & Pay 0 tokens'], # ], # widget=widgets.RadioSelectHorizontal, # label='Decision 1' # ) # # active2 = models.IntegerField( # choices = [ # [1, 'Make own decision & Pay 20 tokens'], # [2, 'Follow the expert & Pay 0 tokens'], # ], # widget=widgets.RadioSelectHorizontal, # label='Decision 2' # ) # # active3 = models.IntegerField( # choices = [ # [1, 'Make own decision & Pay 10 tokens'], # [2, 'Follow the expert & Pay 0 token'], # ], # widget=widgets.RadioSelectHorizontal, # label='Decision 3' # ) # # active4 = models.IntegerField( # choices = [ # [1, 'Make own decision & Pay 0 token'], # [2, 'Follow the expert & Pay 0 token'], # ], # widget=widgets.RadioSelectHorizontal, # label='Decision 4' # ) # # active5 = models.IntegerField( # choices = [ # [1, 'Make own decision & Pay 0 token'], # [2, 'Follow the expert & Pay 10 tokens'], # ], # widget=widgets.RadioSelectHorizontal, # label='Decision 5' # ) # # active6 = models.IntegerField( # choices = [ # [1, 'Make own decision & Pay 0 token'], # [2, 'Follow the expert & Pay 20 tokens'], # ], # widget=widgets.RadioSelectHorizontal, # label='Decision 6' # ) # # active7 = models.IntegerField( # choices = [ # [1, 'Make own decision & Pay 0 token'], # [2, 'Follow the expert & Pay 30 tokens'], # ], # widget=widgets.RadioSelectHorizontal, # label='Decision 7' # ) # New version: only 2 WTP: # New version: only 2 WTP: active1 = models.IntegerField( choices = [ [1, 'Make own decision & Pay 10 tokens'], [2, 'Follow the expert & Pay 0 tokens'], ], widget=widgets.RadioSelectHorizontal, label='Decision 1' ) active2 = models.IntegerField( choices = [ [1, 'Make own decision & Pay 0 tokens'], [2, 'Follow the expert & Pay 10 tokens'], ], widget=widgets.RadioSelectHorizontal, label='Decision 2' ) activeness = models.IntegerField() activeness_chosen = models.IntegerField() active_result_display = models.StringField(blank = True) active_cost_display = models.IntegerField(blank = True) def display_activeness(self): # This is for displaying the randomization result in the result page for the client if self.id_in_group == 2: if self.activeness_chosen == 1: if self.activeness == 1: self.active_result_display = "Make own decision & Pay 10 tokens" else: self.active_result_display = "Follow the expert & Pay 0 tokens" elif self.activeness_chosen == 2: if self.activeness == 1: self.active_result_display = "Make own decision & Pay 0 tokens" else: self.active_result_display = "Follow the expert & Pay 10 tokens" # if self.id_in_group == 2: # if self.activeness_chosen <=4: # if self.activeness == 2: # self.active_result_display = "Follow the expert & Pay 0 tokens" # elif self.activeness ==1: # if self.activeness_chosen == 1: # self.active_result_display = "Make own decision & Pay 30 tokens" # elif self.activeness_chosen == 2: # self.active_result_display = "Make own decision & Pay 20 tokens" # elif self.activeness_chosen == 3: # self.active_result_display = "Make own decision & Pay 10 tokens" # elif self.activeness_chosen == 4: # self.active_result_display = "Make own decision & Pay 0 token" # # else: # if self.activeness == 1: # self.active_result_display = "Make own decision & Pay 0 token" # elif self.activeness == 2: # if self.activeness_chosen == 5: # self.active_result_display = "Follow the expert &pay 10 tokens" # elif self.activeness_chosen == 6: # self.active_result_display = "Follow the expert &pay 20 tokens" # elif self.activeness_chosen == 7: # self.active_result_display = "Follow the expert & pay 30 tokens" def display_active_cost(self): # This is for displaying the cost of activeness in the result page for the client if self.id_in_group == 2: if self.activeness_chosen == 1: if self.activeness == 1: self.active_cost_display = 10 else: self.active_cost_display = 0 elif self.activeness_chosen == 2: if self.activeness == 1: self.active_cost_display = 0 else: self.active_cost_display = 10 # if self.id_in_group == 2: # if self.activeness_chosen <=4: # if self.activeness == 2: # self.active_cost_display = 0 # elif self.activeness ==1: # if self.activeness_chosen == 1: # self.active_cost_display = 30 # elif self.activeness_chosen == 2: # self.active_cost_display = 20 # elif self.activeness_chosen == 3: # self.active_cost_display = 10 # elif self.activeness_chosen == 4: # self.active_cost_display = 0 # # else: # if self.activeness == 1: # self.active_cost_display = 0 # elif self.activeness == 2: # if self.activeness_chosen == 5: # self.active_cost_display = 10 # elif self.activeness_chosen == 6: # self.active_cost_display = 20 # elif self.activeness_chosen == 7: # self.active_cost_display = 30 def role(self): if self.id_in_group == 1: return 'player1' else: return 'player2' def set_payoff(self): if self.id_in_group == 1: # expert self.payment = 120 - self.diagnostic_cost else: # client # patient's payment depends on his choice of treatment. And his choice of treatment depends on his activeness status. #self.treatment_choice = 0*(self.treatment_choice_letter == "Solution A*") + 1*(self.treatment_choice_letter == "Solution B*") # self.payment = 20+100*(1-abs((self.activeness == 1)*self.treatment_choice + (self.activeness ==2)* self.diagnostic_result - self.problem))+ \ # (self.activeness_chosen == 1)*(abs(self.activeness - 2)*(-30)) \ # + ((self.activeness_chosen == 2)*(abs(self.activeness - 2)*(-20))) \ # + ((self.activeness_chosen == 3) * (abs(self.activeness - 2) * (-10))) \ # + (self.activeness_chosen == 5)*(abs(self.activeness-1)*(-10)) + \ # (self.activeness_chosen == 6)*(abs(self.activeness-1)*(-20))\ # + ((self.activeness_chosen == 7)*(abs(self.activeness - 1)*(-30))) # New version: self.payment = 20 + 100 * (1 - abs((self.activeness == 1) * self.treatment_choice + ( self.activeness == 2) * self.diagnostic_result - self.problem)) \ - (self.activeness_chosen == 1) * ((self.activeness == 1) * 10) - ( self.activeness_chosen == 2) * ((self.activeness == 2) * 10) def set_problem(self): if self.id_in_group == 2: random_num = randint(1, 100) if random_num <=50: self.problem = 0 self.problem_letter = "A" else: self.problem = 1 self.problem_letter = "B" def get_signal(self): if self.id_in_group == 2: random_num = randint(1, 100) if random_num <=60: self.private_signal = self.problem else: self.private_signal = abs(self.problem - 1) def set_letter_signal(self): if self.private_signal == 0: self.private_signal_letter = "A" elif self.private_signal == 1: self.private_signal_letter = "B" def set_final_treatment(self): if self.activeness == 1: self.treatment_final = self.treatment_choice if self.treatment_final == 0: self.treatment_final_letter = "A*" else: self.treatment_final_letter = "B*" else: self.treatment_final = self.diagnostic_result self.treatment_final_letter = self.recommend_soln_letter # Control questions # Expert expert_q1 = models.IntegerField(label='Suppose you choose 50% as your diagnostic accuracy, and your diagnosis is ' '“Problem A”. Which of the following is true?', choices = [ [1, 'There is a 0% of chance that the client’s problem is “Problem A”.'], [2, 'There is a 50% of chance that the client’s problem is “Problem A”.'], [3, 'There is an 80% of chance that the client’s problem is “Problem A”.'], [4, 'There is a 100% of chance that the client’s problem is “Problem A”.'] ],widget=widgets.RadioSelect,blank = True) def expert_q1_error_message(self, value): if self.id_in_group ==1: if value != Constants.expert_q1a: return 'Your answer to this question is wrong. Please check the hint.' expert_q2 = models.IntegerField(label='Suppose you choose 100% as your accuracy, and your diagnosis is “Problem B”. ' 'Which of the following is true?', choices = [ [1, 'There is a 0% of chance that the client’s problem is “Problem B”.'], [2, 'There is a 50% of chance that the client’s problem is “Problem B".'], [3, 'There is an 80% of chance that the client’s problem is “Problem B”.'], [4, 'There is a 100% of chance that the client’s problem is “Problem B”.'] ],widget=widgets.RadioSelect,blank = True) def expert_q2_error_message(self, value): if self.id_in_group ==1: if value != Constants.expert_q2a: return 'Your answer to this question is wrong. Please check the hint.' expert_q3_1 = models.IntegerField(label = 'Suppose you choose 60%, your income from this round will be:', blank = True) def expert_q3_1_error_message(self, value): if self.id_in_group ==1: if value != Constants.expert_q3_1a: return 'Your answer to this question is wrong. Please check the hint.' expert_q3_2 = models.IntegerField(label='Suppose you choose 90%, then your income from this round will be:', blank = True) def expert_q3_2_error_message(self, value): if self.id_in_group ==1: if value != Constants.expert_q3_2a: return 'Your answer to this question is wrong. Please check the hint.' expert_q4 = models.IntegerField(label = '', choices=[ [1, 'True.'], [2, 'False.'] ], widget=widgets.RadioSelect, blank = True) def expert_q4_error_message(self, value): if self.id_in_group ==1: if value != Constants.expert_q4a: return 'Your answer to this question is wrong. Please check the hint.' expert_q5 = models.IntegerField( label='Suppose you are matched with an Active client, and you recommend solution B* to the client. Which of the following statement is true?', choices=[ [1, 'The client will always follow my recommendation and choose receive solution B*.'], [2, 'The client might not necessarily receive solution B. He/she can instead choose solution A* if he/she likes.'] ], widget=widgets.RadioSelect, blank=True) def expert_q5_error_message(self, value): if self.id_in_group == 1: if value != Constants.expert_q5a: return 'Your answer to this question is wrong. Please check the hint.' client_q1 = models.IntegerField( # label='Suppose you make the following choices, ' # 'and the computer randomly chooses the third row ' # '(“Make own decision & pay 10”, and “follow the expert”, highlighted by the yellow color). ' # 'What will be your status in this round?', label='', choices=[ [1, 'Make own decision and pay 0 token.'], [2, 'Make own decision and pay 10 tokens.'], [3, 'Follow the expert and pay 0 token.'], [4, 'Follow the expert and pay 10 tokens.'] ], widget=widgets.RadioSelect, blank=True) def client_q1_error_message(self, value): if self.id_in_group == 2: if value != Constants.client_q1a: return 'Your answer to this question is wrong. Please check the hint.' client_q2 = models.IntegerField( # label='Suppose you see the following page. Which statements are true?', label='', choices=[ [1, '(i) & (iii)'], [2, '(ii) & (iii)'], [3, '(i) & (iv)'], [4, '(ii) & (iv)'] ], widget=widgets.RadioSelect, blank=True) def client_q2_error_message(self, value): if self.id_in_group == 2: if value != Constants.client_q2a: return 'Your answer to this question is wrong. Please check the hint.' client_q3 = models.IntegerField( label='', choices=[ [1, '120 tokens'], # [2, '-20 tokens'], # [3, '100 tokens'], [2, '-10 tokens'], [3, '110 tokens'], [4, '0 token'], ], widget=widgets.RadioSelect, blank=True ) def client_q3_error_message(self, value): if self.id_in_group == 2: if value != Constants.client_q3a: return 'Your answer to this question is wrong. Please check the hint.' client_q4 = models.IntegerField( label='', choices=[ [1, '10 tokens'], [2, '100 tokens'], [3, '90 tokens'], [4, '80 token'], ], widget=widgets.RadioSelect, blank=True ) def client_q4_error_message(self, value): if self.id_in_group == 2: if value != Constants.client_q4a: return 'Your answer to this question is wrong. Please check the hint.'