from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range, ) from time import time import datetime import pytz author = 'Eva Vriens' doc = """ Norm questions, final payoff, and questionnaire """ def make_item(label): return models.IntegerField( choices=[[1, ''], [2, ''], [3, ''], [4, ''], [5, ''], [6, '']], label=label, widget=widgets.RadioSelectHorizontal, blank=True ) class Constants(BaseConstants): name_in_url = 'payoff' players_per_group = None num_rounds = 1 allowed_timeouts = 3 rounds_paid = 4 # For testing test = False inc_norms = True inc_risksvo = True # Incentivization norm questions norm_inc = 1 appr_inc = 0.5 # Punishment punish_r = 3 # Punishment costs 3 points for receiver punish_s = 1 # Punishment costs 1 point for sender # Norm questions sn_pnb = 't5_payoff/sn_pnb.html' sn_ee = 't5_payoff/sn_ee.html' sn_ne = 't5_payoff/sn_ne.html' sn_hnb = 't5_payoff/sn_hnb.html' ap_beh = 't5_payoff/ap_beh.html' ap_pun = 't5_payoff/ap_pun.html' class Subsession(BaseSubsession): num_active = models.IntegerField() value = models.IntegerField() cost = models.IntegerField() showup = models.FloatField() endowment = models.IntegerField() reputation = models.BooleanField() last_round = models.IntegerField() def creating_session(self): # Cost and value self.endowment = 3 self.showup = 5 if self.session.config['vc_ratio'] == 'high': # ratio = 1/2 self.value = 6 self.cost = 12 else: # ratio = 1/4 self.value = 2 self.cost = 8 self.reputation = self.session.config['reputation'] self.last_round = Constants.num_rounds def create_groups(self): attackers = [p for p in self.get_players() if p.participant.vars['role'] == 'attacker' and not p.participant.vars['inactive']] defenders = [p for p in self.get_players() if p.participant.vars['role'] == 'defender' and not p.participant.vars['inactive']] inactive = [p for p in self.get_players() if p.participant.vars['inactive']] group_matrix = [attackers, defenders, inactive] print(group_matrix) self.set_group_matrix(group_matrix) class Group(BaseGroup): def norm_calculations(self): print('Calculation norm incentives') for p in self.get_players(): if p.ee is None: p.ee = -99 if p.ne is None: p.ne = -99 if p.pnb is None: p.pnb = -99 # if p.beh_u is None: # p.beh_u = -99 # if p.beh_d is None: # p.beh_d = -99 if p.pun_u is None: p.pun_u = -99 if p.pun_d is None: p.pun_d = -99 pvars = p.participant.vars print('PVARS CHOICE_DL = ', p.participant.vars['choice_dl']) if pvars.get('role') == 'defender' and not pvars.get('inactive'): # ----- LAST ROUND ----- # # Empirical expectations num_down = len([q for q in p.get_others_in_group() if q.participant.vars['choice_dl'] == 1 and q.participant.vars['role'] == 'defender' and not q.participant.vars['inactive']]) num_defs = len([q for q in p.get_others_in_group() if q.participant.vars['role'] == 'defender' and q.participant.vars['choice_dl'] < 2 and not q.participant.vars['inactive']]) print('Num that played down = {} and num active defenders = {}'.format(num_down, num_defs)) print('List of players that played down = ', [q for q in p.get_others_in_group() if q.participant.vars['choice_dl'] == 1 and q.participant.vars['role'] == 'defender' and not q.participant.vars['inactive']]) p.ee_percdownl = round(num_down / num_defs * 100) if p.ee >= 0: p.ee_payoffl = round((100 - abs(p.ee - p.ee_percdownl)) / 100, 2) else: print('Player did not make decision in time so ee payoff = 0') p.ee_payoffl = 0 print('%D = {}, EE = {}, EE payoff = {}'.format(p.ee_percdownl, p.ee, p.ee_payoffl)) # Normative expectations num_down = len([q for q in p.get_others_in_group() if q.pnb == 1 and q.participant.vars['role'] == 'defender' and not q.participant.vars['inactive']]) p.ne_percdownl = round(num_down / num_defs * 100) if p.ne >= 0: p.ne_payoffl = round((100 - abs(p.ne - p.ne_percdownl)) / 100, 2) else: print('Player did not make decision in time so ne payoff = 0') p.ne_payoffl = 0 print('%D = {}, NE = {}, NE payoff = {}'.format(p.ne_percdownl, p.ne, p.ne_payoffl)) # Appropriateness choosing up # ans_up = [q.beh_u for q in p.get_others_in_group() if # q.beh_u > 0 and q.participant.vars['role'] == 'defender' and not q.participant.vars['inactive']] # p.mode_bul = max(set(ans_up), key=ans_up.count) if ans_up else 0 # p.payoff_bul = Constants.appr_inc if p.beh_u == p.mode_bul else 0 # print('List of answers bup = ', ans_up) # print('Mode bup = {}, guess = {}, payoff = {}'.format(p.mode_bul, p.beh_u, p.payoff_bul)) # Appropriateness choosing down # ans_down = [q.beh_d for q in p.get_others_in_group() if # q.beh_d > 0 and q.participant.vars['role'] == 'defender' and not q.participant.vars['inactive']] # p.mode_bdl = max(set(ans_down), key=ans_down.count) if ans_down else 0 # p.payoff_bdl = Constants.appr_inc if p.beh_d == p.mode_bdl else 0 # print('List of answers bup = ', ans_down) # print('Mode bdown = {}, guess = {}, payoff = {}'.format(p.mode_bdl, p.beh_d, p.payoff_bdl)) # Appropriateness punishing if up ans_up = [q.pun_u for q in p.get_others_in_group() if q.pun_u > 0 and q.participant.vars['role'] == 'defender' and not q.participant.vars['inactive']] p.mode_pul = max(set(ans_up), key=ans_up.count) if ans_up else 0 p.payoff_pul = Constants.appr_inc if p.pun_u == p.mode_pul else 0 print('List of answers bup = ', ans_up) print('Mode pup = {}, guess = {}, payoff = {}'.format(p.mode_pul, p.pun_u, p.payoff_pul)) # Appropriateness punishing if down ans_down = [q.pun_d for q in p.get_others_in_group() if q.pun_d > 0 and q.participant.vars['role'] == 'defender' and not q.participant.vars['inactive']] p.mode_pdl = max(set(ans_down), key=ans_down.count) if ans_down else 0 p.payoff_pdl = Constants.appr_inc if p.pun_d == p.mode_pdl else 0 print('List of answers bup = ', ans_down) print('Mode pdown = {}, guess = {}, payoff = {}'.format(p.mode_pdl, p.pun_d, p.payoff_pdl)) def final_payoff(self): for p in self.get_players(): pvars = p.participant.vars task123 = 0 if pvars['risk']: task123 += pvars.get('risk_payoff') if pvars['norm']: task123 += pvars.get('norm_payoff') if pvars['svo']: task123 += pvars.get('payoff_svo') pvars['task123'] = task123 print('points in tasks123 are {} and EUR {}'.format(task123, float(0.01*task123))) # Payoff including norm questions if pvars.get('role') == 'defender' and not pvars.get('inactive'): if Constants.inc_norms: nq_round1 = pvars.get('ee_payoff1') + pvars.get('ne_payoff1') + pvars.get('payoff_pu1') + pvars.get('payoff_pd1') # + pvars.get('payoff_bu1') + pvars.get('payoff_bd1') nq_roundl = p.ee_payoffl + p.ne_payoffl + p.payoff_pul + p.payoff_pdl # + p.payoff_bul + p.payoff_bdl p.norm_payoff = float("{:.2f}".format(nq_round1 + nq_roundl)) if p.norm_payoff < 0: p.norm_payoff = 0 else: p.norm_payoff = 3 p.total_payoff = float("{:.6f}".format(pvars.get('total_payoff') + 0.25*p.norm_payoff + 0.01*pvars.get('task123'))) #float("{:.2f}".format(pvars.get('total_payoff') + 0.25*p.norm_payoff + 0.01*pvars.get('task123'))) print('total payoff = ', p.total_payoff) else: p.total_payoff = float("{:.6f}".format(pvars.get('total_payoff') + 0.01*pvars.get('task123'))) print('total payoff = ', p.total_payoff) class Player(BasePlayer): # Beliefs pnb = models.IntegerField( choices=[ [0, 'Don\'t Resist'], # 'Acquiesce'], [1, 'Resist'], # 'Resist'], ], widget=widgets.RadioSelect, label="", initial=-99 ) hnb = models.IntegerField( choices=[ [0, 'Don\'t Resist'], # 'Acquiesce'], [1, 'Resist'], # 'Resist'], ], widget=widgets.RadioSelect, label="", initial=-99 ) ee = models.IntegerField(min=0, max=100, label="") # ,initial=-99) ne = models.IntegerField(min=0, max=100, label="") # ,initial=-99) # Appropriateness # beh_u = models.IntegerField( # choices=[ # [1, 'Very socially inappropriate'], # [2, 'Somewhat socially inappropriate'], # [3, 'Somewhat socially appropriate'], # [4, 'Very socially appropriate'] # ], # widget=widgets.RadioSelect, # label="", # initial=-99 # ) # beh_d = models.IntegerField( # choices=[ # [1, 'Very socially inappropriate'], # [2, 'Somewhat socially inappropriate'], # [3, 'Somewhat socially appropriate'], # [4, 'Very socially appropriate'] # ], # widget=widgets.RadioSelect, # label="", # initial=-99 # ) pun_u = models.IntegerField( choices=[ [1, 'Very socially inappropriate'], [2, 'Somewhat socially inappropriate'], [3, 'Somewhat socially appropriate'], [4, 'Very socially appropriate'] ], widget=widgets.RadioSelect, label="", initial=-99 ) pun_d = models.IntegerField( choices=[ [1, 'Very socially inappropriate'], [2, 'Somewhat socially inappropriate'], [3, 'Somewhat socially appropriate'], [4, 'Very socially appropriate'] ], widget=widgets.RadioSelect, label="", initial=-99 ) # Norm calculations ee_percdownl = models.IntegerField() ee_payoffl = models.FloatField() ne_percdownl = models.IntegerField() ne_payoffl = models.FloatField() # mode_bul = models.IntegerField() # payoff_bul = models.FloatField() # mode_bdl = models.IntegerField() # payoff_bdl = models.FloatField() mode_pul = models.IntegerField() payoff_pul = models.FloatField() mode_pdl = models.IntegerField() payoff_pdl = models.FloatField() norm_payoff = models.FloatField() total_payoff = models.FloatField() # Questionnaire age = models.PositiveIntegerField( verbose_name="What is your age?", min=16, max=100, ) gender = models.PositiveIntegerField( verbose_name="What gender do you identify as?", choices=[ [0, "Male"], [1, "Female"], [2, "Other"], ] ) educ = models.IntegerField( verbose_name="What is your highest level of education?", choices=[ [1, 'No degree'], [2, 'Elementary school'], [3, 'High school'], [4, 'Undergraduate degree (bachelor)'], [5, 'Graduate degree (master/PhD)'], [6, 'Other'] ] ) student = models.PositiveIntegerField( verbose_name="Are you currently a student?", choices=[ [0, "No"], [1, "Yes"], ] ) left_right = models.IntegerField( verbose_name="Where do you place yourself on a political spectrum from left to right wing?", choices=[ [1, ""], [2, ""], [3, ""], [4, ""], [5, ""], [6, ""], [7, ""], ], widget=widgets.RadioSelectHorizontal ) experience = models.PositiveIntegerField( verbose_name="How many other experiments of this kind have you participated in?", min=0, max=100, ) purpose = models.StringField( blank=True, verbose_name="What do you think is the purpose of this study?", ) unclear = models.StringField( blank=True, verbose_name="Where there any parts of this study unclear to you? If so, which?", ) didntwork = models.StringField( blank=True, verbose_name="Was there any part of this study that didn't work properly? If so, which?", ) macr1 = make_item('Whether or not someone acted to protect their family.') macr2 = make_item('Whether or not someone helped a member of their family.') macr3 = make_item('Whether or not someone’s action showed love for their family.') macr4 = make_item('Whether or not someone acted in a way that helped their community.') macr5 = make_item('Whether or not someone helped a member of their community.') macr6 = make_item('Whether or not someone worked to unite a community.') macr7 = make_item('Whether or not someone did what they had agreed to do.') macr8 = make_item('Whether or not someone kept their promise.') macr9 = make_item('Whether or not someone proved that they could be trusted.') macr10 = make_item('Whether or not someone acted heroically.') macr11 = make_item('Whether or not someone showed courage in the face of adversity.') macr12 = make_item('Whether or not someone was brave.') macr13 = make_item('Whether or not someone deferred to those in authority.') macr14 = make_item('Whether or not someone disobeyed orders.') macr15 = make_item('Whether or not someone showed respect for authority.') macr16 = make_item('Whether or not someone kept the best part for themselves.') macr17 = make_item('Whether or not someone showed favouritism.') macr18 = make_item('Whether or not someone took more than others.') macr19 = make_item('Whether or not someone vandalised another person’s property.') macr20 = make_item('Whether or not someone kept something that didn’t belong to them.') macr21 = make_item('Whether or not someone’s property was damaged.') macj1 = make_item('People should be willing to do anything to help a member of their family.') macj2 = make_item('You should always be loyal to your family.') macj3 = make_item('You should always put the interests of your family first.') macj4 = make_item('People have an obligation to help members of their community.') macj5 = make_item('It’s important for individuals to play an active role in their communities.') macj6 = make_item('You should try to be a useful member of society.') macj7 = make_item('You have an obligation to help those who have helped you.') macj8 = make_item('You should always make amends for the things you have done wrong.') macj9 = make_item('You should always return a favour if you can.') macj10 = make_item('Courage in the face of adversity is the most admirable trait.') macj11 = make_item('Society should do more to honour its heroes.') macj12 = make_item('To be willing to lay down your life for your country is the height of bravery.') macj13 = make_item('People should always defer to their superiors.') macj14 = make_item('Society would be better if people were more obedient to authority.') macj15 = make_item('You should respect people who are older than you.') macj16 = make_item('Everyone should be treated the same.') macj17 = make_item('Everyone\'s rights are equally important.') macj18 = make_item('The current levels of inequality in society are unfair.') macj19 = make_item('It’s acceptable to steal food if you are starving.') macj20 = make_item('It’s ok to keep valuable items that you find, rather than try to locate the rightful owner. ') macj21 = make_item('Sometimes you are entitled to take things you need from other people.') def timeout_norms(self): timeout = (self.participant.vars['end_time'] - datetime.datetime.now(tz=pytz.utc)).total_seconds() return timeout