from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range, ) import csv import random author = 'Alexander Coutts, Boon Han Koh, Zahra Murad' doc = """ Feedback/Gender Experiment: Managers (Main Feedback Task) """ class Constants(BaseConstants): name_in_url = 'fg_m_feedback' players_per_group = None num_rounds = 1 # Tournament rate tournament_rate = 0.2 # Piece rate piece_rate = 0.05 # Payment for beliefs belief_payment = 0.20 # Payment for final attention check (worker characteristics) attncheck_payment = 0.05 # Define probabilities of receiving each type of feedback prob_precise = 0.6 prob_vague = 0.3 prob_none = 0.1 # Import worker.csv file here with open('data/worker_mock_200806-formatted.csv', encoding='utf-8') as workerfile: workerlist = list(csv.DictReader(workerfile)) class Subsession(BaseSubsession): def creating_session(self): # extract all workers self.session.vars['workerlist'] = Constants.workerlist.copy() # Print distributions of manager's probabilities print('Prob(precise feedback):', Constants.prob_precise) print('Prob(vague feedback):', Constants.prob_vague) print('Prob(no feedback):', Constants.prob_none) # extract treatments and matched worker for player in self.get_players(): player.treatcompfirst = self.session.config['treatcompfirst'] player.treatgender = self.session.config['treatgender'] # extract worker's information worker_data = self.session.vars['workerlist'][player.id_in_group-1] player.workerID = worker_data['fg_all_intro.1.player.prolificID'] player.workerfemale = int(worker_data['fg_all_demographic.1.player.female']) player.workerquarterbirth = int(worker_data['fg_all_demographic.1.player.quarterbirth']) player.workerfavecolor = worker_data['fg_all_demographic.1.player.fave_color'] player.workerfavebeverage = worker_data['fg_all_demographic.1.player.fave_beverage'] player.workerrank = int(worker_data['rank']) if player.workerfemale == 1: player.workergenderdesc = "Female" player.workerpronouncap = "She" player.workerpronounsmall = "she" player.workerpronounobjective = "her" player.workerpronounpossessive = "her" player.workerpronounpossessivecap = "Her" player.workerverb = "is" player.workersingular = "s" player.workerhashave = "has" elif player.workerfemale == 0: player.workergenderdesc = "Male" player.workerpronouncap = "He" player.workerpronounsmall = "he" player.workerpronounobjective = "him" player.workerpronounpossessive = "his" player.workerpronounpossessivecap = "His" player.workerverb = "is" player.workersingular = "s" player.workerhashave = "has" elif player.workerfemale == -1: player.workergenderdesc = "Trans/Intersex/Other" player.workerpronouncap = "They" player.workerpronounsmall = "they" player.workerpronounobjective = "them" player.workerpronounpossessive = "their" player.workerpronounpossessivecap = "Their" player.workerverb = "are" player.workersingular = "" player.workerhashave = "have" if player.workerquarterbirth == 1: player.workerquarterbirthdesc = "Between January and March" elif player.workerquarterbirth == 2: player.workerquarterbirthdesc = "Between April and June" elif player.workerquarterbirth == 3: player.workerquarterbirthdesc = "Between July and September" elif player.workerquarterbirth == 4: player.workerquarterbirthdesc = "Between October and December" if player.workerrank == 1 or player.workerrank == 2: player.workertophalf = True elif player.workerrank == 3 or player.workerrank == 4: player.workertophalf = False # determine type of feedback each manager receives player.signalroll = random.random() if player.signalroll <= Constants.prob_precise: player.signaltype = 3 player.signalprecise = True elif Constants.prob_precise+Constants.prob_vague >= player.signalroll > Constants.prob_precise: player.signaltype = 2 player.signalvague = True elif player.signalroll > Constants.prob_precise+Constants.prob_vague: player.signaltype = 1 player.signalnone = True print('treatment compfirst:', player.treatcompfirst) print('treatment gender:', player.treatgender) class Group(BaseGroup): pass class Player(BasePlayer): treatcompfirst = models.BooleanField() treatgender = models.BooleanField() # generate variables to store worker data workerID = models.StringField() workerfemale = models.IntegerField() workerquarterbirth = models.IntegerField() workerfavecolor = models.StringField() workerfavebeverage = models.StringField() workerrank = models.IntegerField() # generate descriptive versions of worker's variables below workergenderdesc = models.StringField() workerpronounsmall = models.StringField() workerverb = models.StringField() workersingular = models.StringField() workerhashave = models.StringField() workerpronouncap = models.StringField() workerpronounpossessive = models.StringField() workerpronounpossessivecap = models.StringField() workerpronounobjective = models.StringField() workerquarterbirthdesc = models.StringField() workertophalf = models.BooleanField() # create variables for determining which feedback type manager receives (3=Precise,2=Vague,1=None) signalroll = models.FloatField() signaltype = models.IntegerField() signalprecise = models.BooleanField(initial=False) signalvague = models.BooleanField(initial=False) signalnone = models.BooleanField(initial=False) # variables for feedback choice feedbacktype = models.IntegerField() # variables for prior beliefs workerprior1 = models.IntegerField() workerprior2 = models.IntegerField() workerprior3 = models.IntegerField() workerprior4 = models.IntegerField() # variables for posterior beliefs workerposterior1 = models.IntegerField() workerposterior2 = models.IntegerField() workerposterior3 = models.IntegerField() workerposterior4 = models.IntegerField() # ctrl questions mgr_ctrl_errors_count = models.IntegerField( initial=0 ) # question 1 # correct answer is False if treatcompfirst=1 and True if treatcompfirst=0 mgrctrl1 = models.BooleanField( label="The content of your feedback may have an impact on your worker's choice of payment.", widget=widgets.RadioSelect, choices=[ [True, "True"], [False, "False"], ] ) # question 2 # correct answer is True mgrctrl2 = models.BooleanField( label="Apart from the message you send, your worker does not receive any other feedback about their performance.", widget=widgets.RadioSelect, choices=[ [True, "True"], [False, "False"], ] ) def error_message(self, value): if self.treatcompfirst: correct_answers = { "mgrctrl1": False, "mgrctrl2": True, } else: correct_answers = { "mgrctrl1": True, "mgrctrl2": True, } list_answers = list(value.items())[0:] list_correct_answers = list(correct_answers.items()) list_mgr_ctrl_errors_count = [0] * len(correct_answers) if list_answers != list_correct_answers: self.mgr_ctrl_errors_count = self.mgr_ctrl_errors_count + 1 indices = list(range(len(list_correct_answers))) for i in range(len(indices)): if list_answers[i] != list_correct_answers[i]: indices[i] = i + 1 list_mgr_ctrl_errors_count[i] = list_mgr_ctrl_errors_count[i] + 1 else: indices[i] = None self.participant.vars['error_questions'] = indices return 'Please check your answers.' # attention check questions attncheck1 = models.IntegerField( blank=True, label="Please select the word 'Cat':", choices=[ [1, "Cat"], [2, "Dog"], [3, "Bird"], ] ) attncheck1success = models.BooleanField(initial=False) def attncheck1calc(self): if self.attncheck1 == 1: self.attncheck1success = True # print(self.attncheck1success) attncheck2 = models.IntegerField( blank=True, label="Which format of information did you receive?", choices=[ [3, "A: Worker's exact quartile rank."], [2, "B: Worker's quartile rank was in the top or bottom half."], [1, "C: Worker's quartile rank was any possible rank."] ] ) attncheck2success = models.BooleanField(initial=False) def attncheck2calc(self): if self.attncheck2 == self.signaltype: self.attncheck2success = True # print(self.attncheck2success) # final attention check questions about worker (paid) attncheckfemale = models.IntegerField( widget=widgets.RadioSelect, label="What is your Worker's gender?", choices=[ [0, 'Male'], [1, 'Female'], [-1, 'Trans/Intersex/Other'], [99, 'Not Displayed'], ] ) attncheckquarterbirth = models.IntegerField( widget=widgets.RadioSelect, label="In which month was your Worker born?", choices=[ [1, 'Between January and March'], [2, 'Between April and June'], [3, 'Between July and September'], [4, 'Between October and December'], [99, 'Not Displayed'], ] ) attncheckfavebeverage = models.StringField( widget=widgets.RadioSelect, label="What is your Worker’s favorite choice of hot beverage?", choices=[ 'Coffee', 'Tea', 'Hot chocolate', 'Not Displayed', ] ) attncheckfavecolor = models.StringField( widget=widgets.RadioSelect, label="What is your Worker’s favorite color?", choices=[ 'Red', 'Green', 'Blue', 'Purple', 'Not Displayed', ] ) attnchecktreatcompfirst = models.BooleanField( widget=widgets.RadioSelect, label="My Worker will receive my feedback:", choices=[ (True, 'AFTER they have made their payment choice for Part 2.'), (False, 'BEFORE they make their payment choice for Part 2'), ] ) attncheckdemoscore = models.IntegerField(initial=0) # compute attention check score def attncheckdemocalc(self): if self.treatgender: if self.attncheckfemale == self.workerfemale: self.attncheckdemoscore += 1 else: if self.attncheckfemale == 99: self.attncheckdemoscore += 1 if self.attncheckquarterbirth == self.workerquarterbirth: self.attncheckdemoscore += 1 if self.attncheckfavecolor == self.workerfavecolor: self.attncheckdemoscore += 1 if self.attncheckfavebeverage == self.workerfavebeverage: self.attncheckdemoscore += 1 if self.attnchecktreatcompfirst == self.treatcompfirst: self.attncheckdemoscore += 1 # print(self.attncheckdemoscore)