from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range ) import itertools from otree_tools.widgets import AdvancedSliderWidget author = 'Elisa' doc = """ Signaling Game (Creditworthiness) """ class Constants(BaseConstants): name_in_url = 'signaling' players_per_group = 3 num_rounds = 1 tot_participants = 3 instructions_template = 'signaling/instructions.html' instructions_receiver = 'signaling/instructions_r.html' instructions_sender = 'signaling/instructions_s.html' # payments info show_up_fee = c(1) endowment = c(0.5) minbonus = c(0) bonus = c(0.5) maxbonus = c(5) penalty = c(0.05) bonus_rater = c(2) # comprehension questions correct answers correct_answers = {'uq1': 3, 'uq2': 1, 'uq3': 3, 'uq4': 1, 'uq5': 1} # treatment information = ['symmetric', 'asymmetric'] # context class Subsession(BaseSubsession): def creating_session(self): info = itertools.cycle(Constants.information) for g in self.get_groups(): g.information = next(info) i = 1 while i <= Constants.tot_participants: for p in self.get_players(): p.player_number = i i += 1 class Group(BaseGroup): # Group Treatments: information = models.StringField() # Payoffs: def set_payoffs(self): players = self.get_players() sender = self.get_player_by_role('sender') receiver = self.get_player_by_role('receiver') receiver_rating = [receiver.rating_c_p2, receiver.rating_c_p3] # 3 players per group if sender.change_c == 'True': # if the sender chooses to update info # depending on what the sender chooses to update if sender.change_c_choice == 1: # age for i in range(2, Constants.players_per_group + 1): if sender.id_in_group == i: sender.earnings_credit = receiver_rating[i-1]*Constants.bonus + Constants.endowment - \ sender.unit_change_c_age * Constants.penalty elif sender.change_c_choice == 2: # weight for i in range(2, Constants.players_per_group + 1): if sender.id_in_group == i: sender.earnings_credit = receiver_rating[i-1]*Constants.bonus + Constants.endowment - \ sender.unit_change_c_weight * Constants.penalty else: # height for i in range(2, Constants.players_per_group + 1): if sender.id_in_group == i: sender.earnings_credit = receiver_rating[i - 1]*Constants.bonus + Constants.endowment - \ sender.unit_change_c_height * Constants.penalty else: for i in range(2, Constants.players_per_group + 1): if sender.id_in_group == i: sender.earnings_credit = receiver_rating[i - 1] * Constants.bonus + Constants.endowment sender.payoff = sender.earnings_credit class Player(BasePlayer): def role(self): if self.id_in_group == 1: return 'receiver' elif self.id_in_group >= 2: return 'sender' # Check variables for forcing slider movements (one slider for each sender rated) checkslider1 = models.IntegerField(blank=True) checkslider2 = models.IntegerField(blank=True) # Comprehension Questions cp_error = models.BooleanField() # error error1 = models.BooleanField() # first error error2 = models.BooleanField() error3 = models.BooleanField() # second error flagged = models.BooleanField() # if you make 3 mistakes uq1 = models.IntegerField( choices=[[1, 'You will have the chance to modify your characteristics for free.'], [2, 'You will have to describe someone else.'], [3, 'You will have the chance to pay to modify your existing description.'], ], widget=widgets.RadioSelect, label="In this game:") uq2 = models.IntegerField( choices=[[1, 'To convince another MTurk worker from your country, the Receiver, that you are creditworthy.'], [2, 'To convince the experimenters to rate you as high as possible.'], [3, 'To be truthful about your characteristics.'], ], widget=widgets.RadioSelect, label="To obtain the highest earnings in the game, the best strategy is:") uq3 = models.IntegerField( choices=[[1, 'will be deduced from your show-up fee.'], [2, 'be covered by the experimenters.'], [3, "will be deduced from your extra endowment for this section. The other" "sections' earnings and your show-up fee will be paid entirely."], ], widget=widgets.RadioSelect, label="The cost of any modification:") uq4 = models.IntegerField( choices=[[1, 'You will have to rate 2 other participants to the study' ', MTurk workers from your country, based on a set of characteristics.'], [2, 'You will have to rate four other participants to the study,' ' from other countries, based on a set of characteristics.'], [3, 'You will have to rate one other participant to the study without ' 'any additional information.'], ], widget=widgets.RadioSelect, label="In this game:") uq5 = models.IntegerField( choices=[[1, "To provide your best guess on each Senders' creditworthiness based on a set of information."], [2, 'To answer randomly.'], [3, 'To please the researchers with your answers.'], ], widget=widgets.RadioSelect, label="The aim of the game is:") # Choices change_c = models.BooleanField( doc="""Whether agent accepts proposal""", widget=widgets.RadioSelect, choices=[ [True, 'Yes, I want to update one information before sending.'], [False, 'No, I want to send these information.'], ] ) change_c_choice = models.IntegerField(choices = [[1, 'Your age'], [2, 'Your weight'], [3, 'Your height']], widget=widgets.RadioSelectHorizontal, label =""" Which characteristic do you want to change? Please, select 1 """, blank=True) unit_change_c_age = models.IntegerField(widget = AdvancedSliderWidget(attrs={'step': 1, 'tick_interval': 5, 'suffix': 'year(s)', 'min': -10, 'max': 10})) unit_change_c_weight = models.IntegerField(widget=AdvancedSliderWidget(attrs={'step': 1, 'tick_interval': 5, 'suffix': 'kg', 'min': -10, 'max': 10})) unit_change_c_height = models.IntegerField(widget=AdvancedSliderWidget(attrs={'step': 1, 'tick_interval': 5, 'suffix': 'cm', 'min': -10, 'max': 10})) rating_c_p2 = models.IntegerField(widget=widgets.Slider(attrs={'step': '1'}, show_value=True), default=5, min=0, max=10, doc = "Based on these information, how would you rate Sender 1's creditworthiness on a scale from 0 to 10? " " [0 = 'not creditworthy'; 10 = 'very creditworthy'] ") rating_c_p3 = models.IntegerField(widget=widgets.Slider(attrs={'step': '1'}, show_value=True), default=5, min=0, max=10, doc="Based on these information, how would you rate Sender 2's creditworthiness on a scale from 0 to 10? " " [0 = 'not creditworthy'; 10 = 'very creditworthy'] ") update_age = models.IntegerField() update_weight = models.IntegerField() update_height = models.IntegerField() update_income = models.CurrencyField() # Treatments player_number = models.IntegerField() # Results earnings_credit = models.CurrencyField()