from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range, ) from random import randint author = 'Nanyin Yang' doc = """ Your app description """ class Constants(BaseConstants): name_in_url = 'concealed_reputation' 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 initial_earning = 10 class Subsession(BaseSubsession): #pass def creating_session(self): self.group_randomly(fixed_id_in_group=True) def set_ratings_subsession(self): for g in self.get_groups(): g.set_ratings_for_client() class Group(BaseGroup): #pass def set_payoffs(self): player1 = self.get_player_by_role('player1') player2 = self.get_player_by_role('player2') for p in self.get_players(): p.set_payoff() 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() 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() def set_ratings(self): player1 = self.get_player_by_role('player1') player2 = self.get_player_by_role('player2') player1.give_rating = player2.give_rating if self.round_number == Constants.starting_round: player1.average_rating = player1.give_rating player2.average_rating = player1.average_rating #else: elif self.round_number > Constants.starting_round: prev_player = player1.in_round(player1.round_number - 1) player1.average_rating = (player1.give_rating+prev_player.average_rating*(player1.round_number-(Constants.num_rounds/2)-1))/(player1.round_number-Constants.num_rounds/2) player2.average_rating = player1.average_rating def set_ratings_for_client(self): player1 = self.get_player_by_role('player1') player2 = self.get_player_by_role('player2') if self.round_number > Constants.starting_round: prev_player = player2.in_round(player2.round_number - 1) player2.view_rating = prev_player.average_rating # 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) 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 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 ) diagnostic_result = models.IntegerField() diagnostic_cost = models.IntegerField() 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' ) 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 <=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 <=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))) 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 give_rating = models.IntegerField( label = '', choices = [1, 2, 3, 4, 5], widget=widgets.RadioSelectHorizontal, blank = True ) average_rating = models.FloatField(blank = True) view_rating = models.FloatField(blank = True) # 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'], [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.'