import math import random from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer ) authors = 'Sargis Karavardanyan and Grigor Karavardanyan' doc = """ This is a signaling game with Protesters vs Police. Protesters make the first move by choosing High or Low profile actions after which police respond to their action choice with repress or tolerate. """ def create_personality(label): return models.IntegerField( # blank = True, choices = [ [1, ""], [2, ""], [3, ""], [4, ""], [5, ""], ], label = label, widget = widgets.RadioSelectHorizontal, ) class Constants(BaseConstants): name_in_url = 'signaling' players_per_group = 2 num_rounds = 5 instructions_template = 'signaling/instructions.html' display_matrix_template = 'signaling/shared/display-matrix.html' important_notes_template = 'signaling/shared/important-notes.html' action_matrix_template = 'signaling/shared/action-matrix.html' # First row = high # Second row in matrix = low # |-------------|----------------| # | ANTIREGIME | NONANTIREGIME | # |-------------|----------------| # | x,y x,y | x,y x,y | # | x,y x,y | x,y x,y | # |-------------|----------------| payoffs = [ [{"x": 5, "y": 5}, {"x": 7, "y": 4}, {"x": 6, "y": 4}, {"x": 8, "y": 5}], [{"x": 3, "y": 4}, {"x": 4, "y": 3}, {"x": 4, "y": 3}, {"x": 7, "y": 5}] ] class Subsession(BaseSubsession): all_protesters_chose_high = models.BooleanField() def set_payoffs(self): # According to game definition we check to see if all # protesters have chosen 'High' as their decision, in # which case they all will be rewarded a higher amount. # Currently set to 3.00. all_protesters_chose_high = True for p in self.get_players(): if p.role() == 'Protester' and p.decision != 'High': all_protesters_chose_high = False self.all_protesters_chose_high = all_protesters_chose_high for g in self.get_groups(): p1 = g.get_player_by_role("Police") p2 = g.get_player_by_role("Protester") if p2.decision == "High": row = 1 else: row = 0 if p2.participant.vars["treatment"] == "antiregime": if p1.decision == "Repress": column = 0 else: column = 1 else: if p1.decision == "Repress": column = 2 else: column = 3 print( '=====================================================', '\npayout round is >>', g.session.vars["paying_round"], '\nround is >>', g.round_number, '\nrow >>', row, '\ncolumn >>', column, '\np1 decision >>', p1.decision, '\np2 decision >>', p2.decision, '\np1 payoff is >>', Constants.payoffs[row][column]["y"], '\np2 payoff is >>', Constants.payoffs[row][column]["x"], '\n=====================================================', ) p1.payoff = Constants.payoffs[row][column]["y"] if all_protesters_chose_high: if p1.decision == 'Repress': p2.payoff = Constants.payoffs[row][column]["x"] * 2 p2.everyone_chose_high_for_subsession = True else: p2.payoff = Constants.payoffs[row][column]["x"] else: p2.payoff = Constants.payoffs[row][column]["x"] print('payoffs are', p1.payoff, p2.payoff) # Here we fix the player pairs for the rest of the experiment def creating_session(self): print('>> in creating_session', self.round_number) # # We first fix the player roles by their IDs # self.group_randomly(fixed_id_in_group=True) if self.round_number == 1: paying_round = random.randint(1, Constants.num_rounds) self.session.vars['paying_round'] = paying_round num_demo_participants = len(self.get_players()) print(num_demo_participants, 'player(s) in this experiment') percentage_police = 0.5 percentage_nonantiregime = 0.4 total_police = math.ceil(num_demo_participants * percentage_police) total_nonantiregime = math.ceil(percentage_nonantiregime * (num_demo_participants - total_police)) print( 'total participants -', num_demo_participants, ', total police -', total_police, ', total nonantiregime -', total_nonantiregime, ', total antiregime -', num_demo_participants - total_nonantiregime - total_police ) counter = 0 for p in self.get_players(): if p.role() == 'Protester': counter += 1 if counter > total_nonantiregime: p.participant.vars['treatment'] = 'antiregime' else: p.participant.vars['treatment'] = 'nonantiregime' print('set player.treatment to', p.participant.vars['treatment']) else: self.group_like_round(1) class Group(BaseGroup): pass class Player(BasePlayer): treatment = models.StringField() everyone_chose_high_for_subsession = models.BooleanField() # Questionnaire q_q1 = models.IntegerField(min=0, max=10) q_q2 = models.IntegerField(min=0, max=10) q_q3 = models.IntegerField(min=0, max=10) q_q4 = models.IntegerField(min=0, max=10) q_q5 = models.IntegerField(min=0, max=10) q_q6 = models.IntegerField(min=0, max=10) # Personality Questions Survey ps_q1 = create_personality("I am not that good at figuring out complicated problems.") ps_q2 = create_personality("I am not very good at solving problems that require careful logical analysis.") ps_q3 = create_personality("I am not very analytical thinker.") ps_q4 = create_personality("Reasoning things out carefully is not one of my strong points.") ps_q5 = create_personality("I don't reason well under pressure.") ps_q6 = create_personality("I am much better at figuring things out logically than most people.") ps_q7 = create_personality("I have a logical mind.") ps_q8 = create_personality("I have no problem thinking things through carefully.") ps_q9 = create_personality("Using logic usually works well for me in figuring out problems in my life.") ps_q10 = create_personality("I usually have clear explainable reasons for my decisions.") ps_q11 = create_personality("I try to avoid situations that require thinking in depth about something.") ps_q12 = create_personality("I enjoy intellectual challenges.") ps_q13 = create_personality("I don't like to have to do a lot of thinking.") ps_q14 = create_personality("I enjoy solving problems that require hard thinking.") ps_q15 = create_personality("Thinking is not my ideal of an enjoyable activity.") ps_q16 = create_personality("I prefer complex problems to simple problems.") ps_q17 = create_personality("Thinking hard and for a long time about something gives me little satisfaction.") ps_q18 = create_personality("I enjoy thinking in abstract terms.") ps_q19 = create_personality("Knowing the answer without having to understand the reasoning behind it is good " "enough for me.") ps_q20 = create_personality("Learning new ways to think would be very appleaing to me.") age = models.IntegerField( widget=widgets.RadioSelect, label="What is your age?", choices=[ [1, "19 or younger"], [2, "20 - 23"], [3, "24 - 29"], [4, "30-39"], [5, "40 - 55"], [6, "Over 55"] ] ) gender = models.IntegerField( widget=widgets.RadioSelect, label="What is your gender?", choices=[ [1, "Male"], [2, "Female"], [3, "Diverse"] ] ) ethnicity = models.IntegerField( widget=widgets.RadioSelect, label="What is your ethnicity?", choices=[ [1, "American Indian or Alaska Native"], [2, "Asian"], [3, "Black or African American"], [4, "Native Hawaiian or Other Pacific Islander"], [5, "White"], [6, "Other (Please specify below)"], [7, "Prefer not to say"] ] ) ethnicity_other = models.StringField( label="Other ethnicity", blank=True ) GPA = models.FloatField( widget=widgets.RadioSelect, label="What is your age?", choices=[ [1, "2.00-2.25"], [2, "2.25 - 2.50"], [3, "2.50 - 2.75"], [4, "3.00 - 3.25"], [5, "3.25 - 3.50"], [6, "3.50 - 3.75"], [7, "3.75 - 4.00"] ] ) field_of_study = models.StringField( label="What is your field of study?" ) marital_status = models.IntegerField( widget=widgets.RadioSelect, label="What is your marital status?", choices=[ [1, "Not married"], [2, "Married"], [3, "Divorced"], [4, "Separated"], [5, "Widowed"], ] ) college_classification = models.IntegerField( widget=widgets.RadioSelect, label="What is your classification in college?", choices=[ [1, "Freshman/first-year"], [2, "Sophomore"], [3, "Junior"], [4, "Senior"], [5, "Graduate student"], [6, "Unclassified"] ] ) study_difficulty = models.IntegerField( widget=widgets.RadioSelect, label="How would you rate the overall difficulty of this study?", choices=[ [1, "Very difficult"], [2, "Difficult"], [3, "Neutral"], [4, "Easy"], [5, "Very easy"] ] ) name = models.StringField() major = models.StringField() year = models.StringField() decision = models.StringField( choices=['Low', 'High', 'Repress', 'Tolerate'], doc="""This player's decision""", widget=widgets.RadioSelect, ) # Defining the roles of each player/hunter def role(self): if self.id_in_group == 1: # H1 = Protester return 'Protester' if self.id_in_group == 2: # H2 = Police return 'Police' def other_player(self): return self.get_others_in_group()[0] def get_payoff_for_player(self, row, column, el): if self.id_in_group == 1: # protester if self.participant.vars["treatment"] == "nonantiregime": column += 2 else: # police if self.other_player().participant.vars["treatment"] == "nonantiregime": column += 2 if el == "x": el = "y" else: el = "x" return Constants.payoffs[row][column][el] def get_payoff_x1(self): return self.get_payoff_for_player(0, 0, "x") def get_payoff_y1(self): return self.get_payoff_for_player(0, 0, "y") def get_payoff_x2(self): return self.get_payoff_for_player(0, 1, "x") def get_payoff_y2(self): return self.get_payoff_for_player(0, 1, "y") def get_payoff_x3(self): return self.get_payoff_for_player(1, 0, "x") def get_payoff_y3(self): return self.get_payoff_for_player(1, 0, "y") def get_payoff_x4(self): return self.get_payoff_for_player(1, 1, "x") def get_payoff_y4(self): return self.get_payoff_for_player(1, 1, "y") # Lastly, we define the questionnaire items for completion by each participant # at the end of experiment