import random from otree.api import * c = cu doc = "This experiment tests the prevalence of reference dependent altruism, wherein individuals are more sensitive when making altruistic choices to changes in others' wellbeing compared to levels." POINTS_CUSTOM_NAME = '' # Set constants class C(BaseConstants): NAME_IN_URL = 'RDA' PLAYERS_PER_GROUP = 55 NUM_ROUNDS = 1 EXPERIMENTAL_PAY = 3 DONOR_BUDGET = 3 COMB = 6 class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): treatment_group = models.CharField(initial="") # control, treatment A, or treatment B random_price = models.FloatField(initial=0) # to compare with the bid to make it incentive compatible flip = models.FloatField(initial=0) # random number generator for coin flip coin_flip = models.CharField(initial="") coin_result = models.CharField() # coin flip text for player 1 coin_result_2 = models.CharField() # coili flip text for player 2 attention = models.FloatField(initial=0) # attention check indicator match_prob = models.FloatField(initial=0) # random number generator for matching to recipient bid1 = models.FloatField(label='Please enter an amount between $0 and $3.', max=3, min=0) # object of interest (player 1's WTP) # for spot checking the bid to make sure they understand it b1 = models.StringField(label=' ', widget=widgets.RadioSelectHorizontal, choices=[["A","A"],["B","B"]], initial="A") b1_level = models.FloatField(initial=0) b2 = models.StringField(label=' ', widget=widgets.RadioSelectHorizontal, choices=[["A","A"],["B","B"]], initial="A") b2_level = models.FloatField(initial=0) b3 = models.StringField(label=' ', widget=widgets.RadioSelectHorizontal, choices=[["A","A"],["B","B"]], initial="A") b3_level = models.FloatField(initial=0) b4 = models.StringField(label=' ', widget=widgets.RadioSelectHorizontal, choices=[["A","A"],["B","B"]], initial="A") b4_level = models.FloatField(initial=0) b5 = models.StringField(label=' ', widget=widgets.RadioSelectHorizontal, choices=[["A","A"],["B","B"]], initial="A") b5_level = models.FloatField(initial=0) b6 = models.StringField(label=' ', widget=widgets.RadioSelectHorizontal, choices=[["A","A"],["B","B"]], initial="A") b6_level = models.FloatField(initial=0) b7 = models.StringField(label=' ', widget=widgets.RadioSelectHorizontal, choices=[["A","A"],["B","B"]], initial="A") b7_level = models.FloatField(initial=0) b8 = models.StringField(label=' ', widget=widgets.RadioSelectHorizontal, choices=[["A","A"],["B","B"]], initial="A") b8_level = models.FloatField(initial=0) b9 = models.StringField(label=' ', widget=widgets.RadioSelectHorizontal, choices=[["A","A"],["B","B"]], initial="A") b9_level = models.FloatField(initial=0) b10 = models.StringField(label=' ', widget=widgets.RadioSelectHorizontal, choices=[["A","A"],["B","B"]], initial="A") error = models.LongStringField(initial="") error2 = models.LongStringField(initial="") b01 = models.StringField(label=' ', widget=widgets.RadioSelectHorizontal, choices=[["A","A"],["B","B"]], initial="A") b01_level = models.FloatField(initial=3) b02 = models.StringField(label=' ', widget=widgets.RadioSelectHorizontal, choices=[["A","A"],["B","B"]], initial="A") b02_level = models.FloatField(initial=3.5) b03 = models.StringField(label=' ', widget=widgets.RadioSelectHorizontal, choices=[["A","A"],["B","B"]], initial="A") b03_level = models.FloatField(initial=4) b04 = models.StringField(label=' ', widget=widgets.RadioSelectHorizontal, choices=[["A","A"],["B","B"]], initial="A") b04_level = models.FloatField(initial=4.5) b05 = models.StringField(label=' ', widget=widgets.RadioSelectHorizontal, choices=[["A","A"],["B","B"]], initial="A") b05_level = models.FloatField(initial=5) b06 = models.StringField(label=' ', widget=widgets.RadioSelectHorizontal, choices=[["A","A"],["B","B"]], initial="A") b06_level = models.FloatField(initial=5.5) error0 = models.LongStringField(initial="") b07 = models.StringField(label=' ', widget=widgets.RadioSelectHorizontal, choices=[["A","A"],["B","B"]], initial="A") sub1 = models.FloatField(initial=0) sub2 = models.FloatField(initial=0) sub3 = models.FloatField(initial=0) sub4 = models.FloatField(initial=0) sub5 = models.FloatField(initial=0) sub6 = models.FloatField(initial=0) sub7 = models.FloatField(initial=0) sub8 = models.FloatField(initial=0) sub9 = models.FloatField(initial=0) sub01 = models.FloatField(initial=3) sub02 = models.FloatField(initial=2.5) sub03 = models.FloatField(initial=2) sub04 = models.FloatField(initial=1.5) sub05 = models.FloatField(initial=1) sub06 = models.FloatField(initial=.5) p1_payoff = models.FloatField(initial=6) p2_payoff = models.FloatField(initial=3) # prolific ID entries prolific_id = models.StringField(label='Please enter your Prolific ID', initial = 0) prolific_id2 = models.StringField(label='Please enter your Prolific ID', initial = 0) # answers to policy questions char1 = models.FloatField(label='American Red Cross: From small house fires to multi-state natural disasters, the American Red Cross goes wherever we’re needed, so people can have clean water, safe shelter and hot meals when they need them most.', max=100, min=0, initial=0) char2 = models.FloatField(label='HeathWell Foundation: The HealthWell Foundation is a leading independent non-profit dedicated to improving access to health care for America’s underinsured. When health insurance is not enough, we fill the gap by assisting with copays, premiums, deductibles and out-of-pocket expenses.', max=100, min=0, initial=0) char3 = models.FloatField(label='United Way: United Way brings people together to build strong, resilient and equitable communities. Through United Way, communities tackle tough challenges and work with private, public, and nonprofit partners to boost education, economic mobility, and health resources.', max=100, min=0, initial=0) char4 = models.FloatField(label='Operation USA: Operation USA supports health and education programs in order to help children and families recover and thrive in the wake of disasters, disease, and violence.', max=100, min=0, initial=0) char5 = models.FloatField(label='Second Harvest: Second Harvest is committed to doing whatever it takes to end hunger in our community. That means distributing nutritious food to neighborhoods around the nation, leveraging every available food resource, and collaborating with organizations and people who share our belief that hunger is unacceptable.', max=100, min=0, initial=0) char6 = models.FloatField(label='Feeding America Disaster Response Fund: When disaster strikes, Feeding America is on the ground and ready to provide food assistance and emergency supplies. We are ready to help neighbors who suddenly need extra support after a disaster.', max=100, min=0, initial=0) char7 = models.FloatField(label='Habitat for Humanity: Habitat works together with families, local communities, volunteers and partners so that more people are able to live in affordable and safe homes.', max=100, min=0, initial=0) char8 = models.FloatField(label='Direct Relief: When disasters strike, Direct Relief responds fast, effectively, and efficiently to get medical resources where they need to be to save lives.', max=100, min=0, initial=0) char9 = models.FloatField(label='America Donates: America Donates is a charitable organization that does not exist and is included here as attention check. Please enter 47, which will not affect your total $100 budget.', max=100, min=0, initial=0) total_donation = models.FloatField(initial=0) gender = models.StringField(label='How would you describe your gender?', widget=widgets.RadioSelect, \ choices=[["Non-binary","Non-binary"], ["Man","Man"], ["Woman", "Woman"], ["Transgender man","Transgender man"], ["Transgender woman", "Transgender woman"], ["Other", "Other"], ["Prefer not to answer", "Prefer not to answer"]], initial="Prefer not to answer") age = models.StringField(label='What is your age?', widget=widgets.RadioSelect, \ choices=[["Under 18","Under 18"], ["18-24","18-24"], ["25-34", "25-34"], ["35-44","35-44"], ["45-54", "45-54"], ["55-64", "55-64"], ["65+", "65+"], ["Prefer not to answer", "Prefer not to answer"]], initial="Prefer not to answer") ethnicity = models.StringField(label='Which race or ethnicity best describes you? (Please choose only one.)', widget=widgets.RadioSelect, \ choices=[["Asian/Pacific Islander","Asian/Pacific Islander"], ["Black or African American", "Black or African American"], ["Hispanic","Hispanic"], ["Native American","Native American"], ["White/Caucasian", "White/Caucasian"], ["Multiple", "Multiple"], ["Other", "Other"], ["Prefer not to answer", "Prefer not to answer"]], initial="Prefer not to answer") education = models.StringField(label='What is the highest level of education you have achieved?', widget=widgets.RadioSelect, \ choices=[["Master's degree or above","Master's degree or above"], ["Bachelor's degree", "Bachelor's degree"], ["Associate's degree","Associate's degree"], ["High school","High school"], ["Other", "Other"], ["Prefer not to answer", "Prefer not to answer"]], initial="Prefer not to answer") marital = models.StringField(label='What is your marital status?', widget=widgets.RadioSelect, \ choices=[["Married","Married"], ["Divorced", "Divorced"], ["Separated","Separated"], ["Single","Single"], ["Other", "Other"], ["Prefer not to answer", "Prefer not to answer"]], initial="Prefer not to answer") employment = models.StringField(label='What is your employment status?', widget=widgets.RadioSelect, \ choices=[["Full-time","Full-time"], ["Part-time", "Part-time"], ["Contract/temporary","Contract/temporary"], ["Unemployed","Unemployed"], ["Unable to work","Unable to work"], ["Other", "Other"], ["Prefer not to answer", "Prefer not to answer"]], initial="Prefer not to answer") income = models.StringField(label='What is the level of your annual household income?', widget=widgets.RadioSelect, \ choices=[["Less than $25,000","Less than $25,000"], ["$25,000-$50,000", "$25,000-$50,000"], ["$50,000-$100,000","$50,000-100,000"], ["100,000-$200,000","$100,000-$200,000"], ["More than $200,000", "More than $200,000"], ["Prefer not to answer", "Prefer not to answer"]], initial="Prefer not to answer") politics = models.StringField(label='How would you describe your political viewpoint?', widget=widgets.RadioSelect, \ choices=[["Very conservative","Very conservative"], ["Slightly conservative", "Slightly conservative"], ["Neutral/neither conservative nor liberal","Neutral/neither conservative nor liberal"], ["Slightly liberal","Slightly liberal"], ["Very liberal", "Very liberal"], ["Prefer not to answer", "Prefer not to answer"]], initial="Prefer not to answer") # answers to feedback questions Donor1 = models.LongStringField(label="How did you approach your decision of how much to offer for your partner to also receive the bonus payment?", initial="__") General1 = models.LongStringField(label="Was anything confusing during the experiment?", initial="__") General2 = models.LongStringField(label="What do you think the experiment was designed to assess?", initial="__") General3 = models.LongStringField(label="Do you have any feedback for the design of this study?", initial="__") General4 = models.LongStringField(label="Do you have any final questions, comments, or suggestions?", initial="__") def get_form_fields_a(): # randomize the order of the policy questions topics = ['char1', 'char2', 'char3', 'char4', 'char5', 'char6', 'char7', 'char8', 'char9'] random.shuffle(topics) return topics def get_form_fields3(): # randomize the order of the demographic questions qs = ['gender', 'age', 'ethnicity', 'education', 'marital', 'employment', 'income', 'politics'] random.shuffle(qs) return qs class Introduction(Page): form_model = 'player' form_fields = ['prolific_id'] # ask for player's prolific ID # assign treatment groups in even proportion def before_next_page(self, timeout_happened): if self.id_in_subsession <= 15: self.treatment_group = 'control' if self.id_in_subsession > 15 and self.group.id_in_subsession <= 35: self.treatment_group = 'treatmentA' if self.id_in_subsession > 35: self.treatment_group = 'treatmentB' class Video(Page): form_model = 'player' form_fields = ['prolific_id2'] # ask for player's prolific ID # do coin flip def before_next_page(self, timeout_happened): if self.treatment_group != "control": self.flip = random.random() if self.flip <=1/2: self.coin_flip = "heads" self.coin_result = "your partner will receive the additional $3.00 if your experiment is (randomly) selected to determine your partner's payoff" self.coin_result_2 = "you will receive the additional $3.00" self.bid1 = 0 if self.flip > 1/2: self.coin_flip = "tails" self.coin_result = "your partner will not receive the additional $3.00" self.coin_result_2 = "you will not receive the additional $3.00 at this time" self.match_prob = random.random() # decide whether this actually affects a recipient (one in four) class P1C1(Page): form_model = 'player' @staticmethod def is_displayed(player: Player): return player.treatment_group == "control" # only display if P1 control class P1T1(Page): form_model = 'player' @staticmethod def is_displayed(player: Player): return player.treatment_group == "treatmentA" # only display if P1 treatment A class P1T2(Page): form_model = 'player' @staticmethod def is_displayed(player: Player): return player.treatment_group == "treatmentB" # only display if P1 treatment B class CF(Page): form_model = 'player' @staticmethod def is_displayed(player: Player): return player.treatment_group != "control" # only display if P1 treatment class P1C2(Page): form_model = 'player' form_fields = ['b01', 'b02', 'b03', 'b04', 'b05', 'b07', 'b06'] # elicit preferences at $0.50 increments between $0.50 and $3 @staticmethod def vars_for_template(player: Player): b01_fields = ['b01'] b02_fields = ['b02'] b03_fields = ['b03'] b04_fields = ['b04'] b05_fields = ['b05'] b06_fields = ['b06'] b07_fields = ['b07'] return dict(b01_fields=b01_fields,b02_fields=b02_fields,b03_fields=b03_fields,b04_fields=b04_fields,\ b05_fields=b05_fields, b06_fields=b06_fields, b07_fields=b07_fields) # based on bid, set up understanding check def before_next_page(self, timeout_happened): self.error0="" if self.b01 == "B" and self.b02 == "A" and self.b03 == "A" and self.b04 == "A" and self.b05 == "A" and self.b06 == "A": self.bid1 = 3.50 elif self.b01 == "B" and self.b02 == "B" and self.b03 == "A" and self.b04 == "A" and self.b05 == "A" and self.b06 == "A": self.bid1 = 4 elif self.b01 == "B" and self.b02 == "B" and self.b03 == "B" and self.b04 == "A" and self.b05 == "A" and self.b06 == "A": self.bid1 = 4.50 elif self.b01 == "B" and self.b02 == "B" and self.b03 == "B" and self.b04 == "B" and self.b05 == "A" and self.b06 == "A": self.bid1 = 5 elif self.b01 == "B" and self.b02 == "B" and self.b03 == "B" and self.b04 == "B" and self.b05 == "B" and self.b06 == "A": self.bid1 = 5.50 elif self.b01 == "B" and self.b02 == "B" and self.b03 == "B" and self.b04 == "B" and self.b05 == "B" and self.b06 == "B": self.bid1 = 6 elif self.b01 == "A" and self.b02 == "A" and self.b03 == "A" and self.b04 == "A" and self.b05 == "A" and self.b06 == "A": self.bid1 = 3 else: self.error0 = 'Your answers on the previous page were inconsistent with each other. Please revise your offer and/or revise your multiple choice answers on the next page.' self.bid1 = 6 self.b1_level = max(C.EXPERIMENTAL_PAY,self.bid1 - 1) self.b2_level = max(C.EXPERIMENTAL_PAY,self.bid1 - .75) self.b3_level = max(C.EXPERIMENTAL_PAY,self.bid1 - .5) self.b4_level = max(C.EXPERIMENTAL_PAY,self.bid1 - .25) self.b5_level = max(C.EXPERIMENTAL_PAY,self.bid1) self.b6_level = min(C.EXPERIMENTAL_PAY + C.DONOR_BUDGET,self.bid1 + .25) self.b7_level = min(C.EXPERIMENTAL_PAY + C.DONOR_BUDGET,self.bid1 + .5 ) self.b8_level = min(C.EXPERIMENTAL_PAY + C.DONOR_BUDGET,self.bid1 + .75) self.b9_level = min(C.EXPERIMENTAL_PAY + C.DONOR_BUDGET,self.bid1 + 1) self.sub1 = max(0,C.EXPERIMENTAL_PAY + C.DONOR_BUDGET-self.b1_level) self.sub2 = max(0,C.EXPERIMENTAL_PAY + C.DONOR_BUDGET-self.b2_level) self.sub3 = max(0,C.EXPERIMENTAL_PAY + C.DONOR_BUDGET-self.b3_level) self.sub4 = max(0,C.EXPERIMENTAL_PAY + C.DONOR_BUDGET-self.b4_level) self.sub5 = max(0,C.EXPERIMENTAL_PAY + C.DONOR_BUDGET-self.b5_level) self.sub6 = max(0,C.EXPERIMENTAL_PAY + C.DONOR_BUDGET-self.b6_level) self.sub7 = max(0,C.EXPERIMENTAL_PAY + C.DONOR_BUDGET-self.b7_level) self.sub8 = max(0,C.EXPERIMENTAL_PAY + C.DONOR_BUDGET-self.b8_level) self.sub9 = max(0,C.EXPERIMENTAL_PAY + C.DONOR_BUDGET-self.b9_level) self.bid1 = -999999999 @staticmethod def is_displayed(player: Player): return player.coin_flip!="heads" or player.treatment_group == "control" # only display if P1 control or treatment where the coin flip wasn't heads class PriceCheck(Page): form_model = 'player' form_fields = ['b01', 'b02', 'b03', 'b04', 'b05', 'b06'] # elicit preferences at $0.50 increments between $0 and $3 @staticmethod def vars_for_template(player: Player): b01_fields = ['b01'] b02_fields = ['b02'] b03_fields = ['b03'] b04_fields = ['b04'] b05_fields = ['b05'] b06_fields = ['b06'] return dict(b01_fields=b01_fields,b02_fields=b02_fields,b03_fields=b03_fields,b04_fields=b04_fields,\ b05_fields=b05_fields, b06_fields=b06_fields) # based on bid, set up understanding check def before_next_page(self, timeout_happened): self.error0="" if self.b01 == "B" and self.b02 == "A" and self.b03 == "A" and self.b04 == "A" and self.b05 == "A" and self.b06 == "A": self.bid1 = 3.5 elif self.b01 == "B" and self.b02 == "B" and self.b03 == "A" and self.b04 == "A" and self.b05 == "A" and self.b06 == "A": self.bid1 = 4 elif self.b01 == "B" and self.b02 == "B" and self.b03 == "B" and self.b04 == "A" and self.b05 == "A" and self.b06 == "A": self.bid1 = 4.5 elif self.b01 == "B" and self.b02 == "B" and self.b03 == "B" and self.b04 == "B" and self.b05 == "A" and self.b06 == "A": self.bid1 = 5 elif self.b01 == "B" and self.b02 == "B" and self.b03 == "B" and self.b04 == "B" and self.b05 == "B" and self.b06 == "A": self.bid1 = 5.5 elif self.b01 == "B" and self.b02 == "B" and self.b03 == "B" and self.b04 == "B" and self.b05 == "B" and self.b06 == "B": self.bid1 = 6 elif self.b01 == "A" and self.b02 == "A" and self.b03 == "A" and self.b04 == "A" and self.b05 == "A" and self.b06 == "A": self.bid1 = 3 else: self.error0 = 'Your answers on the previous page were inconsistent with each other. Please revise your choices.' self.bid1 = 6 self.b1_level = max(C.EXPERIMENTAL_PAY,self.bid1 - 1) self.b2_level = max(C.EXPERIMENTAL_PAY,self.bid1 - .75) self.b3_level = max(C.EXPERIMENTAL_PAY,self.bid1 - .5) self.b4_level = max(C.EXPERIMENTAL_PAY,self.bid1 - .25) self.b5_level = max(C.EXPERIMENTAL_PAY,self.bid1) self.b6_level = min(C.EXPERIMENTAL_PAY + C.DONOR_BUDGET,self.bid1 + .25) self.b7_level = min(C.EXPERIMENTAL_PAY + C.DONOR_BUDGET,self.bid1 + .5 ) self.b8_level = min(C.EXPERIMENTAL_PAY + C.DONOR_BUDGET,self.bid1 + .75) self.b9_level = min(C.EXPERIMENTAL_PAY + C.DONOR_BUDGET,self.bid1 + 1) self.sub1 = max(0,C.EXPERIMENTAL_PAY + C.DONOR_BUDGET-self.b1_level) self.sub2 = max(0,C.EXPERIMENTAL_PAY + C.DONOR_BUDGET-self.b2_level) self.sub3 = max(0,C.EXPERIMENTAL_PAY + C.DONOR_BUDGET-self.b3_level) self.sub4 = max(0,C.EXPERIMENTAL_PAY + C.DONOR_BUDGET-self.b4_level) self.sub5 = max(0,C.EXPERIMENTAL_PAY + C.DONOR_BUDGET-self.b5_level) self.sub6 = max(0,C.EXPERIMENTAL_PAY + C.DONOR_BUDGET-self.b6_level) self.sub7 = max(0,C.EXPERIMENTAL_PAY + C.DONOR_BUDGET-self.b7_level) self.sub8 = max(0,C.EXPERIMENTAL_PAY + C.DONOR_BUDGET-self.b8_level) self.sub9 = max(0,C.EXPERIMENTAL_PAY + C.DONOR_BUDGET-self.b9_level) self.bid1 = -999999999 @staticmethod def is_displayed(player: Player): return player.error0 != "" and (player.coin_flip!="heads" or player.treatment_group == "control") # only display if an error was made by P1 control or treatment where the coin flip wasn't heads class PriceList(Page): form_model = 'player' form_fields = ['b1', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7', 'b8', 'b9', 'b10'] @staticmethod def vars_for_template(player: Player): b1_fields = ['b1'] b2_fields = ['b2'] b3_fields = ['b3'] b4_fields = ['b4'] b5_fields = ['b5'] b6_fields = ['b6'] b7_fields = ['b7'] b8_fields = ['b8'] b9_fields = ['b9'] b10_fields = ['b10'] return dict(b1_fields=b1_fields,b2_fields=b2_fields,b3_fields=b3_fields,b4_fields=b4_fields,\ b5_fields=b5_fields,b6_fields=b6_fields,b7_fields=b7_fields,b8_fields=b8_fields,\ b9_fields=b9_fields, b10_fields=b10_fields) # set up text if participant indicates misunderstanding def before_next_page(self, timeout_happened): if self.b1 == "A" and self.b2 == "A" and self.b3 == "A" and self.b4 == "A" and self.b5 == "A" and self.b6 == "A" and self.b7 == "A" and self.b8 == "A" and self.b9 == "A": self.bid1 = self.b1_level elif self.b1 == "B" and self.b2 == "A" and self.b3 == "A" and self.b4 == "A" and self.b5 == "A" and self.b6 == "A" and self.b7 == "A" and self.b8 == "A" and self.b9 == "A": self.bid1 = self.b2_level elif self.b1 == "B" and self.b2 == "B" and self.b3 == "A" and self.b4 == "A" and self.b5 == "A" and self.b6 == "A" and self.b7 == "A" and self.b8 == "A" and self.b9 == "A": self.bid1 = self.b3_level elif self.b1 == "B" and self.b2 == "B" and self.b3 == "B" and self.b4 == "A" and self.b5 == "A" and self.b6 == "A" and self.b7 == "A" and self.b8 == "A" and self.b9 == "A": self.bid1 = self.b4_level elif self.b1 == "B" and self.b2 == "B" and self.b3 == "B" and self.b4 == "B" and self.b5 == "A" and self.b6 == "A" and self.b7 == "A" and self.b8 == "A" and self.b9 == "A": self.bid1 = self.b5_level elif self.b1 == "B" and self.b2 == "B" and self.b3 == "B" and self.b4 == "B" and self.b5 == "B" and self.b6 == "A" and self.b7 == "A" and self.b8 == "A" and self.b9 == "A": self.bid1 = self.b6_level elif self.b1 == "B" and self.b2 == "B" and self.b3 == "B" and self.b4 == "B" and self.b5 == "B" and self.b6 == "B" and self.b7 == "A" and self.b8 == "A" and self.b9 == "A": self.bid1 = self.b7_level elif self.b1 == "B" and self.b2 == "B" and self.b3 == "B" and self.b4 == "B" and self.b5 == "B" and self.b6 == "B" and self.b7 == "B" and self.b8 == "A" and self.b9 == "A": self.bid1 = self.b8_level elif self.b1 == "B" and self.b2 == "B" and self.b3 == "B" and self.b4 == "B" and self.b5 == "B" and self.b6 == "B" and self.b7 == "B" and self.b8 == "B" and self.b9 == "A": self.bid1 = self.b9_level elif self.b1 == "B" and self.b2 == "B" and self.b3 == "B" and self.b4 == "B" and self.b5 == "B" and self.b6 == "B" and self.b7 == "B" and self.b8 == "B" and self.b9 == "B": self.bid1 = 6 else: self.error = 'Your answers on the previous page were inconsistent with each other. Please revise your choices.' self.bid1 = 6 def is_displayed(player: Player): return (player.coin_flip!="heads" or player.treatment_group == "control") # only display if P1 control or treatment where the coin flip wasn't heads # repeat bid check but only display if an error was made in last bid check class PriceList2(Page): form_model = 'player' form_fields = ['b1', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7', 'b8', 'b9'] # set up text if participant indicates misunderstanding def before_next_page(self, timeout_happened): self.error = "" if self.b1 == "A" and self.b2 == "A" and self.b3 == "A" and self.b4 == "A" and self.b5 == "A" and self.b6 == "A" and self.b7 == "A" and self.b8 == "A" and self.b9 == "A": self.bid1 = self.b1_level elif self.b1 == "B" and self.b2 == "A" and self.b3 == "A" and self.b4 == "A" and self.b5 == "A" and self.b6 == "A" and self.b7 == "A" and self.b8 == "A" and self.b9 == "A": self.bid1 = self.b2_level elif self.b1 == "B" and self.b2 == "B" and self.b3 == "A" and self.b4 == "A" and self.b5 == "A" and self.b6 == "A" and self.b7 == "A" and self.b8 == "A" and self.b9 == "A": self.bid1 = self.b3_level elif self.b1 == "B" and self.b2 == "B" and self.b3 == "B" and self.b4 == "A" and self.b5 == "A" and self.b6 == "A" and self.b7 == "A" and self.b8 == "A" and self.b9 == "A": self.bid1 = self.b4_level elif self.b1 == "B" and self.b2 == "B" and self.b3 == "B" and self.b4 == "B" and self.b5 == "A" and self.b6 == "A" and self.b7 == "A" and self.b8 == "A" and self.b9 == "A": self.bid1 = self.b5_level elif self.b1 == "B" and self.b2 == "B" and self.b3 == "B" and self.b4 == "B" and self.b5 == "B" and self.b6 == "A" and self.b7 == "A" and self.b8 == "A" and self.b9 == "A": self.bid1 = self.b6_level elif self.b1 == "B" and self.b2 == "B" and self.b3 == "B" and self.b4 == "B" and self.b5 == "B" and self.b6 == "B" and self.b7 == "A" and self.b8 == "A" and self.b9 == "A": self.bid1 = self.b7_level elif self.b1 == "B" and self.b2 == "B" and self.b3 == "B" and self.b4 == "B" and self.b5 == "B" and self.b6 == "B" and self.b7 == "B" and self.b8 == "A" and self.b9 == "A": self.bid1 = self.b8_level elif self.b1 == "B" and self.b2 == "B" and self.b3 == "B" and self.b4 == "B" and self.b5 == "B" and self.b6 == "B" and self.b7 == "B" and self.b8 == "B" and self.b9 == "A": self.bid1 = self.b9_level elif self.b1 == "B" and self.b2 == "B" and self.b3 == "B" and self.b4 == "B" and self.b5 == "B" and self.b6 == "B" and self.b7 == "B" and self.b8 == "B" and self.b9 == "B": self.bid1 = 6 else: self.error = 'Your answers on the previous page were inconsistent with each other. Please revise your choices.' self.bid1 = 6 @staticmethod def vars_for_template(player: Player): b1_fields = ['b1'] b2_fields = ['b2'] b3_fields = ['b3'] b4_fields = ['b4'] b5_fields = ['b5'] b6_fields = ['b6'] b7_fields = ['b7'] b8_fields = ['b8'] b9_fields = ['b9'] return dict(b1_fields=b1_fields,b2_fields=b2_fields,b3_fields=b3_fields,b4_fields=b4_fields,\ b5_fields=b5_fields,b6_fields=b6_fields,b7_fields=b7_fields,b8_fields=b8_fields,\ b9_fields=b9_fields) @staticmethod def is_displayed(player: Player): return (player.coin_flip!="heads" or player.treatment_group == "control") and player.error!= "" # stall page to calculate payoffs class Payoff_Temp(Page): form_model = 'player' def before_next_page(self, timeout_happened): self.bid1 = max(0,C.EXPERIMENTAL_PAY + C.DONOR_BUDGET - self.bid1) if self.match_prob > .25 and (self.coin_flip != "heads" or self.treatment_group == "control"): self.p1_payoff = C.EXPERIMENTAL_PAY + C.DONOR_BUDGET self.p2_payoff = C.EXPERIMENTAL_PAY if self.match_prob <= 0.25 \ and (self.coin_flip != "heads" or self.treatment_group == "control")\ and (self.b1 == "A" or self.b1 == "B")\ and (self.b2 == "A" or self.b2 == "B") and (self.b3 == "A" or self.b3 == "B")\ and (self.b4 == "A" or self.b4 == "B") and (self.b5 == "A" or self.b5 == "B")\ and (self.b6 == "A" or self.b6 == "B") and (self.b7 == "A" or self.b7 == "B")\ and (self.b8 == "A" or self.b8 == "B") and (self.b9 == "A" or self.b9 == "B"): # calculate only once (for player 1 who goes first) self.random_price = random.choice(range(1, 9)) # random pick a row for incentive compatibility # if indicated willing to pay for relevant row --> pay bid for player 2 to get of add'l compensation if self.bid1 != -999999999 and self.random_price == 1 and self.b1 == "A" and (self.coin_flip != "heads" or self.treatment_group == "control"): self.p1_payoff = self.b1_level self.p2_payoff = C.EXPERIMENTAL_PAY + C.DONOR_BUDGET if self.bid1 != -999999999 and self.random_price == 2 and self.b2 == "A" and (self.coin_flip != "heads" or self.treatment_group == "control"): self.p1_payoff = self.b2_level self.p2_payoff = C.EXPERIMENTAL_PAY + C.DONOR_BUDGET if self.bid1 != -999999999 and self.random_price == 3 and self.b3 == "A" and (self.coin_flip != "heads" or self.treatment_group == "control"): self.p1_payoff = self.b3_level self.p2_payoff = C.EXPERIMENTAL_PAY + C.DONOR_BUDGET if self.bid1 != -999999999 and self.random_price == 4 and self.b4 == "A" and (self.coin_flip != "heads" or self.treatment_group == "control"): self.p1_payoff = self.b4_level self.p2_payoff = C.EXPERIMENTAL_PAY + C.DONOR_BUDGET if self.bid1 != -999999999 and self.random_price == 5 and self.b5 == "A" and (self.coin_flip != "heads" or self.treatment_group == "control"): self.p1_payoff = self.b5_level self.p2_payoff = C.EXPERIMENTAL_PAY + C.DONOR_BUDGET if self.bid1 != -999999999 and self.random_price == 6 and self.b6 == "A" and (self.coin_flip != "heads" or self.treatment_group == "control"): self.p1_payoff = self.b6_level self.p2_payoff = C.EXPERIMENTAL_PAY + C.DONOR_BUDGET if self.bid1 != -999999999 and self.random_price == 7 and self.b7 == "A" and (self.coin_flip != "heads" or self.treatment_group == "control"): self.p1_payoff = self.b7_level self.p2_payoff = C.EXPERIMENTAL_PAY + C.DONOR_BUDGET if self.bid1 != -999999999 and self.random_price == 8 and self.b8 == "A" and (self.coin_flip != "heads" or self.treatment_group == "control"): self.p1_payoff = self.b8_level self.p2_payoff = C.EXPERIMENTAL_PAY + C.DONOR_BUDGET if self.bid1 != -999999999 and self.random_price == 9 and self.b9 == "A" and (self.coin_flip != "heads" or self.treatment_group == "control"): self.p1_payoff = self.b9_level self.p2_payoff = C.EXPERIMENTAL_PAY + C.DONOR_BUDGET # if price greater than bid --> everyone keeps what they had if self.bid1 != -999999999 and ((self.random_price == 1 and self.b1 == "B") or \ (self.random_price == 2 and self.b2 == "B") or \ (self.random_price == 3 and self.b3 == "B") or \ (self.random_price == 4 and self.b4 == "B") or \ (self.random_price == 5 and self.b5 == "B") or \ (self.random_price == 6 and self.b6 == "B") or \ (self.random_price == 7 and self.b7 == "B") or \ (self.random_price == 8 and self.b8 == "B") or \ (self.random_price == 9 and self.b9 == "B")) \ and (self.coin_flip != "heads" or self.treatment_group == "control"): self.p1_payoff = C.EXPERIMENTAL_PAY + C.DONOR_BUDGET self.p2_payoff = C.EXPERIMENTAL_PAY # if treatment and coin flip was heads --> everyone gets bonus payment if self.coin_flip == "heads" and self.treatment_group != "control": self.p1_payoff = C.EXPERIMENTAL_PAY + C.DONOR_BUDGET self.p2_payoff = C.EXPERIMENTAL_PAY + C.DONOR_BUDGET if (self.coin_flip != "heads" or self.treatment_group == "control") and self.b07 == "A" and self.b10=="B" and self.char9 == 47: # attention checks self.attention = 1 # if an issue with timeout or dropout and no payoffs set, everyone gets baseline pay if self.bid1 == -999999999: self.p1_payoff = C.EXPERIMENTAL_PAY self.p2_payoff = C.EXPERIMENTAL_PAY class Results(Page): form_model = 'player' @staticmethod def is_displayed(player: Player): return ((player.coin_flip!="heads" or player.treatment_group == "control") and player.bid1 != -999999999) or player.match_prob > 0.25 class Results_Alt(Page): form_model = 'player' @staticmethod def is_displayed(player: Player): return player.coin_flip=="heads" and player.treatment_group != "control" and player.match_prob <= 0.25 # payoff formatting for groups where coin flip made the decision and donor played all the way through class Policy1(Page): form_model = 'player' form_fields = get_form_fields_a() @staticmethod def vars_for_template(player: Player): char1_fields = ['char1'] char2_fields = ['char2'] char3_fields = ['char3'] char4_fields = ['char4'] char5_fields = ['char5'] char6_fields = ['char6'] char7_fields = ['char7'] char8_fields = ['char8'] char9_fields = ['char9'] return dict(char1_fields=char1_fields,char2_fields=char2_fields,char3_fields=char3_fields,char4_fields=char4_fields,\ char5_fields=char5_fields,char6_fields=char6_fields,char7_fields=char7_fields,char8_fields=char8_fields,\ char9_fields=char9_fields) # set up text if participant indicates misunderstanding def before_next_page(self, timeout_happened): self.error2 = "" self.total_donation = self.char1 + self.char2 + self.char3 + self.char4 + self.char5 + self.char6 + self.char7 + self.char8 if self.char1 + self.char2 + self.char3 + self.char4 + self.char5 + self.char6 + self.char7 + self.char8 != 100: self.error2 = 'Your allocations on the previous page did not sum to $100. Please revise your choices.' # repeat allocation only if error made in previous allocation class Policy2(Page): form_model = 'player' form_fields = ['char1', 'char2', 'char3', 'char4', 'char5', 'char6', 'char7', 'char8'] def before_next_page(self, timeout_happened): self.error2 = "" self.total_donation = self.char1 + self.char2 + self.char3 + self.char4 + self.char5 + self.char6 + self.char7 + self.char8 if self.char1 + self.char2 + self.char3 + self.char4 + self.char5 + self.char6 + self.char7 + self.char8 != 100: self.error2 = 'Your allocations on the previous page did not sum to $100. Please revise your choices.' @staticmethod def vars_for_template(player: Player): char1_fields = ['char1'] char2_fields = ['char2'] char3_fields = ['char3'] char4_fields = ['char4'] char5_fields = ['char5'] char6_fields = ['char6'] char7_fields = ['char7'] char8_fields = ['char8'] return dict(char1_fields=char1_fields,char2_fields=char2_fields,char3_fields=char3_fields,char4_fields=char4_fields,\ char5_fields=char5_fields,char6_fields=char6_fields,char7_fields=char7_fields,char8_fields=char8_fields) @staticmethod def is_displayed(player: Player): return player.error2!= "" class Demographics(Page): form_model = 'player' form_fields = get_form_fields3() class Feedback1(Page): form_model = 'player' form_fields = ['Donor1'] @staticmethod def is_displayed(player: Player): return (player.coin_flip!="heads" or player.treatment_group == "control") # display only if made a bid class Feedback2(Page): form_model = 'player' form_fields = ['General1', 'General2', 'General3', 'General4'] class LP(Page): pass page_sequence = [Introduction, Video, P1C1, P1T1, P1T2, CF, P1C2, PriceList, Policy1, Payoff_Temp, Results, Results_Alt, Demographics, Feedback1, Feedback2, LP]