from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range, ) import random author = 'Dr. Testori' doc = """ This is a 10-rounds 3-options Common Pool Resources Game with 4 players - Prolific """ def YesNo_field(label): return models.IntegerField( choices=[ [1, 'Yes'], [2, 'No'], ], label=label, widget=widgets.RadioSelectHorizontal, ) def agree(label): return models.IntegerField( choices=[ [1, ''], [2, ''], [3, ''], [4, ''], [5, ''], [6, ''], [7, ''], ], label=label, widget=widgets.RadioSelect, ) class Constants(BaseConstants): name_in_url = 'decision_game' players_per_group = 4 num_rounds = 10 sustainable = 0.05 non_sustainable = 0.11 high_incentives = 4 / 3 showing_up_fee = 2.5 decisions_explanation_low = 'CPR/decisions_explanation_low.html' decisions_explanation_high = 'CPR/decisions_explanation_high.html' # """Environment amount""" environment = 100 growth_rate = 1.3 # """Duration and compensation parameters""" min = 5.5 max = 11 avg = 6.5 time = 45 payoff_min = 5.5 payoff_max = 11 class Subsession(BaseSubsession): def creating_session(self): if self.round_number == 1: for g in self.get_groups(): p1 = g.get_player_by_id(1) p1.participant.vars['grp_treat'] = random.choice( ['Intergen-high', 'No-Intergen-high', 'Intergen-low', 'No-Intergen-low']) for g in self.get_groups(): p1 = g.get_player_by_id(1) g.grp_treat = p1.participant.vars['grp_treat'] class Group(BaseGroup): grp_treat = models.StringField() total_extraction = models.CurrencyField() environment = models.FloatField() previous_env = models.FloatField() otherpart = models.FloatField() dead = models.IntegerField(initial=0) act = models.IntegerField() def active(self): if self.id_in_subsession == 1: self.act = 1 if self.id_in_subsession == 2: self.act = 2 return self.act def my_page_timeout_seconds(self): self.otherpart = len([p for p in self.subsession.get_players() if p.stamp > 0]) return self.otherpart def set_payoffs(self): players = self.get_players() if self.id_in_subsession == 1: if self.dead == 0: # Define the environment if self.round_number == 1: self.previous_env = Constants.environment extractions = [p.extraction * Constants.environment for p in players] self.total_extraction = round(sum(extractions), 2) self.environment = round(Constants.growth_rate * (Constants.environment - self.total_extraction), 2) else: self.previous_env = self.in_round(self.round_number - 1).environment extractions = [p.extraction * self.previous_env for p in players] self.total_extraction = round(sum(extractions), 2) self.environment = round(Constants.growth_rate * ( self.in_round(self.round_number - 1).environment - self.total_extraction), 2) self.environment = round(self.environment, 2) # Define the conversion from extraction to payoff at each round if self.grp_treat == 'Intergen-high' or self.grp_treat == 'No-Intergen-high': for p in self.get_players(): if p.extraction == Constants.sustainable: p.rounds_payoff = round( ((p.extraction * self.previous_env) * Constants.high_incentives) / 10, 2) else: p.rounds_payoff = round((p.extraction * self.previous_env) / 10, 2) else: for p in self.get_players(): p.rounds_payoff = round((p.extraction * self.previous_env) / 10, 2) # Final payoff calculation if self.round_number == 10: for p in self.get_players(): p.cumulative_payoff = sum([p.rounds_payoff for p in p.in_all_rounds()]) p.payoff = p.cumulative_payoff + p.waiting_time() + Constants.showing_up_fee if p.payoff >= p.max: p.payoff = round(p.max - Constants.showing_up_fee, 2) p.participant.payoff = round(p.max - Constants.showing_up_fee, 2) elif p.payoff < p.min: p.payoff = round(p.min - Constants.showing_up_fee, 2) p.participant.payoff = round(p.min - Constants.showing_up_fee, 2) elif p.payoff < p.max: p.participant.payoff = round(p.payoff - Constants.showing_up_fee, 2) else: for p in self.get_players(): p.payoff = p.waiting_time() + Constants.showing_up_fee p.participant.payoff = p.waiting_time() # Final payoff for people in the screen-out elif self.id_in_subsession > 1: for p in self.get_players(): p.payoff = 0 p.participant.payoff = 0 def completion_code(self): for p in self.get_players(): p.random_n = round(random.random() * 100) return p.random_n class Player(BasePlayer): firstwaiting_time_start = models.IntegerField() timewaiting_end = models.IntegerField() moneytime = models.FloatField() stamp = models.IntegerField(initial=0) max = models.FloatField(initial=11) min = models.FloatField(initial=5.5) random_n = models.FloatField() passive = models.IntegerField(initial=0) rounds_payoff = models.CurrencyField() active = models.IntegerField(initial=1) cumulative_payoff = models.CurrencyField() prolific_id = models.StringField(default=str("")) extraction = models.FloatField( choices=[ [Constants.sustainable, 'Option A: extract 5% of the resources from the pool'], [Constants.non_sustainable, 'Option B: extract 11% of the resources from the pool'], [0, 'Option C: extract 0% of the resources from the pool']], label="You can choose one of the following options", widget=widgets.RadioSelect, ) consent = models.IntegerField( choices=[ [1, 'Yes, I do'], ], ) comment = models.LongStringField(blank=True) contact = models.IntegerField( choices=[ [1, 'Yes'], [2, 'No'], ], widget=widgets.RadioSelect, ) def waiting_time(self): self.moneytime = round(((self.in_round(1).timewaiting_end - self.in_round(1).firstwaiting_time_start) / 500), 2) return self.moneytime test_growth_rate = models.IntegerField( choices=[ [1, 'Resources current round - total extraction'], [2, '(Resources current round - total extraction)*1.3'], [3, '(Resources current round - total extraction)*2'], ], label='A) The resources for next round are calculated as follows:', widget=widgets.RadioSelect, ) test_conversion_rate = models.IntegerField( choices=[ [1, '10 units = $ 1'], [2, '20 units = $ 1'], [3, '1 unit = $ 1'], ], label='B) The conversion rate of the study is:', widget=widgets.RadioSelect, ) test_options_available = models.IntegerField( choices=[ [1, 'Extract 0% or 5% or 10% of the resources from the pool'], [2, 'Extract 1% or 5% or 11% of the resources from the pool'], [3, 'Extract 0% or 5% or 11% of the resources from the pool'], [4, 'Extract 10% or 5% of the resources from the pool'], ], label='C) The possible options of extractions from the pool are:', widget=widgets.RadioSelect, ) test_earnings_high = models.IntegerField( choices=[ [1, 'Extracted resources / 10'], [2, 'Extracted resources / 10 + premium'], [3, 'Extracted resources / 10 - premium'], ], label='E) If you choose option A (Extract 5% of the resources from the pool), you will earn:', widget=widgets.RadioSelect, ) test_threshold = models.IntegerField( choices=[ [1, '10 units'], [2, '100 units'], [3, '20 units'], ], label='D) The threshold of resources for the next group to start the game is:', widget=widgets.RadioSelect, ) test_growth_rate2 = models.IntegerField( choices=[ [1, 'Resources current round - total extraction'], [2, '(Resources current round - total extraction)*1.3'], [3, '(Resources current round - total extraction)*2'], ], label='A) The resources for next round are calculated as follows:', widget=widgets.RadioSelect, ) test_conversion_rate2 = models.IntegerField( choices=[ [1, '10 units = $ 1'], [2, '20 units = $ 1'], [3, '1 unit = $ 1'], ], label='B) The conversion rate of the study is:', widget=widgets.RadioSelect, ) test_options_available2 = models.IntegerField( choices=[ [1, 'Extract 0% or 5% or 10% of the resources from the pool'], [2, 'Extract 1% or 5% or 11% of the resources from the pool'], [3, 'Extract 0% or 5% or 11% of the resources from the pool'], [4, 'Extract 10% or 5% of the resources from the pool'], ], label='C) The possible options of extractions from the pool are:', widget=widgets.RadioSelect, ) test_earnings_high2 = models.IntegerField( choices=[ [1, 'Extracted resources / 10'], [2, 'Extracted resources / 10 + premium'], [3, 'Extracted resources / 10 - premium'], ], label='E) If you choose option A (Extract 5% of the resources from the pool), you will earn:', widget=widgets.RadioSelect, ) test_threshold2 = models.IntegerField( choices=[ [1, '10 units'], [2, '100 units'], [3, '20 units'], ], label='D) The threshold of resources for the next group to start the game is:', widget=widgets.RadioSelect, ) liberal = models.IntegerField( choices=[ [1, 'Extremely liberal'], [2, 'Liberal'], [3, 'Slightly liberal'], [4, 'Moderate'], [5, 'Slightly conservative'], [6, 'Conservative'], [7, 'Extremely conservative'], ], label='Below you can see a seven-point scale on which the political views that people might hold are arranged ' 'from extremely liberal to extremely conservative. Where would you place yourself ' 'on this scale?', widget=widgets.RadioSelect, ) political_orientation = models.IntegerField( choices=[ [1, 'Democrat'], [2, 'Independent, near democrat'], [3, 'Independent'], [4, 'Independent, near republican'], [5, 'Republican'], [6, 'Other party'], ], label='Generally speaking, do you usually think of yourself as a Republican, Democrat, Independent, ' 'or something else?', widget=widgets.RadioSelect, ) trust_scientists = models.IntegerField( choices=[ [1, '0, No trust at all in scientists'], [2, '1'], [3, '2'], [4, '3'], [5, '4'], [6, '5'], [7, '6'], [8, '7'], [9, '8'], [10, '9'], [11, '10, Complete trust in scientists'], ], label='Please indicate on a scale from 0 to 10 how much you personally trust scientists, where 0 ' 'means you do not trust them at all at all and 10 means you have complete trust.', widget=widgets.RadioSelect, ) environment_worry = models.IntegerField( choices=[ [1, 'Not at all worried'], [2, 'Not very worried'], [3, 'Somewhat worried'], [4, 'Very worried'], [5, 'Extremely worried'], ], label='How worried are you about climate change?', widget=widgets.RadioSelect, ) environment_responsibility = models.IntegerField( choices=[ [1, '0, No at all'], [2, '1'], [3, '2'], [4, '3'], [5, '4'], [6, '5'], [7, '6'], [8, '7'], [9, '8'], [10, '9'], [11, 'A great deal'], ], label='Please indicate on a scale from 0 to 10 to what extent do you feel a personal responsibility to try to ' 'reduce climate change?', widget=widgets.RadioSelect, ) environment_natural_process = models.IntegerField( choices=[ [1, 'Entirely by natural processes'], [2, 'Mainly by natural processes'], [3, 'About equally by natural processes and human activity'], [4, 'Mainly by human activity'], [5, 'Entirely by human activity'], [6, 'I don`t think climate change is happening'], ], label='Do you think that climate change is caused by natural processes, human activity, or both?', widget=widgets.RadioSelect, ) gender = models.IntegerField(choices=[ [1, 'Male'], [2, 'Female'], [3, 'Other'], ], label='What is your gender? ', widget=widgets.RadioSelect, ) age = models.IntegerField( min=18, max=90, label='What is your age? ', ) ethnic_min = models.IntegerField(choices=[ [1, 'White'], [2, 'Black'], [3, 'Hispanic or Latino/Latina'], [4, 'Asian'], [5, 'Other'], ], label="What do you consider your ethnic group?", widget=widgets.RadioSelect, ) education = models.IntegerField(choices=[ [1, 'Less than high school (Grade 11 or less) '], [2, 'High School Diploma (including GED) '], [3, 'Some college '], [4, 'Associate degree (2 years) or specialized technical training '], [5, 'Bachelor`s degree '], [6, 'Some graduate training '], [7, 'Graduate/professional degree or higher '], ], label="What is the highest grade of school or year of college you have completed?", widget=widgets.RadioSelect, ) prole = models.IntegerField(min=0, max=10, label="How many children do you have?")