from otree.api import * import itertools import random doc = """ Public Learning """ class C(BaseConstants): NAME_IN_URL = 'beliefelicitation' PLAYERS_PER_GROUP = None NUM_ROUNDS = 5 PATHA = [[89,86,89,92,98,95,92],[102,105,108,114,117,114,111],[105,102,99,102,105,111,105],[84,90,96,93,90,87,81],[112,109,115,112,118,121,124],[94,97,100,106,112,106,100]] PATHB = [[89,86,89,92,98,95,92],[102,105,108,114,117,114,111],[105,102,99,102,105,111,105],[84,90,96,93,90,87,81],[112,109,115,112,118,121,124],[94,97,100,106,112,106,100]] PATHC = [[89,86,89,92,98,95,92],[102,105,108,114,117,114,111],[105,102,99,102,105,111,105],[84,90,96,93,90,87,81],[112,109,115,112,118,121,124],[94,97,100,106,112,106,100]] PATHD = [[89,86,89,92,98,95,92],[102,105,108,114,117,114,111],[105,102,99,102,105,111,105],[84,90,96,93,90,87,81],[112,109,115,112,118,121,124],[94,97,100,106,112,106,100]] class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): treatment = models.StringField() treatment2 = models.StringField() A = models.IntegerField( label="Likelihood that stock A is in the good state:", min=1, max=100, ) B = models.IntegerField( label="Likelihood that stock B is in the good state:", min=1, max=100, ) C = models.IntegerField( label="Likelihood that stock C is in the good state:", min=1, max=100, ) D = models.IntegerField( label="Likelihood that stock D is in the good state:", min=1, max=100, ) GoodA = models.StringField( label="State of Stock A?", choices=[["Good", "Good"], ["Bad", "Bad"]], widget=widgets.RadioSelectHorizontal, ) GoodB = models.StringField( label="State of Stock B?", choices=[["Good", "Good"], ["Bad", "Bad"]], widget=widgets.RadioSelectHorizontal, ) GoodC = models.StringField( label="State of Stock C?", choices=[["Good", "Good"], ["Bad", "Bad"]], widget=widgets.RadioSelectHorizontal, ) GoodD = models.StringField( label="State of Stock D?", choices=[["Good", "Good"], ["Bad", "Bad"]], widget=widgets.RadioSelectHorizontal, ) Best = models.StringField( label="Choose the best stock:", choices=[["Stock A","Stock A"],["Stock B","Stock B"],["Stock C","Stock C"]], widget=widgets.RadioSelectHorizontal, ) InitialBest = models.StringField( choices=[["Stock A","Stock A"],["Stock B","Stock B"],["Stock C","Stock C"]], widget=widgets.RadioSelectHorizontal, ) InitialBelieveA = models.IntegerField(initial=50) InitialBelieveB = models.IntegerField(initial=50) InitialBelieveC = models.IntegerField(initial=50) InitialBelieveD = models.IntegerField(initial=50) PrevA = models.IntegerField() PrevB = models.IntegerField() PrevC = models.IntegerField() PrevD = models.IntegerField() PrevGoodA = models.StringField( choices=[[1, "Good"],[0, "Bad"]], ) PrevGoodB = models.StringField( choices=[[1, "Good"],[0, "Bad"]] ) PrevGoodC = models.StringField( choices=[[1, "Good"],[0, "Bad"]] ) PrevGoodD = models.StringField( choices=[[1, "Good"],[0, "Bad"]] ) Bonus = models.IntegerField( initial=0, ) Bonus0 = models.IntegerField() Bonus1 = models.IntegerField() Bonus2 = models.IntegerField() Bonus3 = models.IntegerField() Bonus4 = models.IntegerField() Bonus5 = models.IntegerField() # Variables for Bayes probabilities ThreeGood = models.FloatField(initial=0.35) ThreeBad = models.FloatField(initial=0.25) SixGood = models.FloatField(initial=0.25) SixBad = models.FloatField(initial=0.15) MinusThreeGood = models.FloatField(initial=0.25) MinusThreeBad = models.FloatField(initial=0.35) MinusSixGood = models.FloatField(initial=0.15) MinusSixBad = models.FloatField(initial=0.25) PriorGoodA = models.FloatField() PriorGoodB = models.FloatField() PriorGoodC = models.FloatField() PriorGoodD = models.FloatField() PriceChangeA = models.FloatField() PriceChangeB = models.FloatField() PriceChangeC = models.FloatField() PriceChangeD = models.FloatField() pathA = models.IntegerField() pathB = models.IntegerField() pathC = models.IntegerField() pathD = models.IntegerField() newinfo = models.IntegerField( label = "How did the previous participant incorporate new information in their choice?", widget = widgets.RadioSelectHorizontal, choices = [[1, "1 (very bad)"], [2, "2"], [3, "3"], [4, "4"],[5, "5 (very good)"]], blank=True ) performance = models.IntegerField( label = "How do you rate the overall performance of the previous participant in choosing the best stock?", widget = widgets.RadioSelectHorizontal, choices = [[1, "1 (very badly)"], [2, "2"], [3, "3"], [4, "4"],[5, "5 (very well)"]], blank=True ) badperformance = models.IntegerField( label = "Why do you think they did incorporate new information badly?", choices = [[1, "They rather changed their choice."], [2, "They rather sticked with their choice."]], blank = True, ) goodperformance = models.IntegerField( label = "Why do you think they did incorporate new information well?", choices = [[1, "They rather changed their choice."], [2, "They rather sticked with their choice."]], blank = True, ) # FUNCTIONS def creating_session(subsession): #draw = itertools.cycle(["black", "black"]) draw = itertools.cycle(["private", "public"]) for player in subsession.get_players(): player.treatment2 = next(draw) player.treatment = "black" def get_partner(player: Player): partner_id = player.id_in_group - 1 partner = player.get_others_in_group()[partner_id - 1] return partner # PAGES class Start(Page): form_model = "player" @staticmethod def is_displayed(player): participant = player.participant player.pathA = participant.pathA player.pathB = participant.pathB player.pathC = participant.pathC player.pathD = participant.pathD if player.round_number==1: player.Bonus0 = random.randint(1,3) player.Bonus1 = random.randint(1,3) player.Bonus2 = random.randint(1,3) player.Bonus3 = random.randint(1,3) player.Bonus4 = random.randint(1,3) player.Bonus5 = random.randint(1,3) else: prev_player = player.in_round(player.round_number - 1) player.Bonus0 = prev_player.Bonus0 player.Bonus1 = prev_player.Bonus1 player.Bonus2 = prev_player.Bonus2 player.Bonus3 = prev_player.Bonus3 player.Bonus4 = prev_player.Bonus4 player.Bonus5 = prev_player.Bonus5 return player.round_number == 1 class PreviousParticipant(Page): form_model = "player" @staticmethod def is_displayed(player): return player.round_number==5 and player.id_in_group>1 class PriceDevelopments_Alt(Page): form_model = 'player' @staticmethod def vars_for_template(player: Player): partner = get_partner(player) # Include partner's decisions for all rounds in a dictionary #partner_estimates = { #f'Round{round_num}': { #'DecisionA': partner.in_round(round_num).field_maybe_none("GoodA"), #'DecisionB': partner.in_round(round_num).field_maybe_none("GoodB"), #'DecisionC': partner.in_round(round_num).field_maybe_none("GoodC"), #'DecisionD': partner.in_round(round_num).field_maybe_none("GoodD"), #} for round_num in range(1, player.round_number) # Gather decisions for all rounds played #} # Include partner's decisions for all rounds in a dictionary partner_estimates = { f'Round{round_num}': { 'Selection': partner.in_round(round_num).field_maybe_none("Best"), } for round_num in range(1, player.round_number) # Gather decisions for all rounds played } return dict( partner=partner, partner_estimates=partner_estimates, round=player.round_number-1, prevA=player.field_maybe_none('PrevA'), prevB=player.field_maybe_none('PrevB'), prevC=player.field_maybe_none('PrevC'), ) def get_form_fields(self): if self.round_number<5: #form_fields = [ #"GoodA", "A", "GoodB", "B", "GoodC", "C", "GoodD", "D", #] form_fields = [ "Best", "A", "B", "C", ] else: form_fields = ["performance","newinfo", "badperformance", "goodperformance"] return form_fields @staticmethod def js_vars(player): if player.round_number == 5: # Display graph for another player (player with an id one less than the current player) partner = get_partner(player) participant = partner.participant partner_pathA = participant.pathA partner_pathB = participant.pathB partner_pathC = participant.pathC partner_pathD = participant.pathD #partner_round1 = partner.in_round(1) return dict( changesA=C.PATHA[partner_pathA - 1], changesB=C.PATHB[partner_pathB - 1], changesC=C.PATHC[partner_pathC - 1], changesD=C.PATHD[partner_pathD - 1], round_number=player.round_number-1, InitialBelieveA=player.InitialBelieveA, InitialBelieveB=player.InitialBelieveB, InitialBelieveC=player.InitialBelieveC, ) else: # Display the current player's graph for rounds other than 5 return dict( changesA=C.PATHA[player.pathA - 1], changesB=C.PATHB[player.pathB - 1], changesC=C.PATHC[player.pathC - 1], changesD=C.PATHD[player.pathD - 1], round_number=player.round_number, InitialBelieveA=player.InitialBelieveA, InitialBelieveB=player.InitialBelieveB, InitialBelieveC=player.InitialBelieveC, ) @staticmethod def is_displayed(player): if player.round_number > 1: prev_player = player.in_round(player.round_number - 1) #player.PrevGoodA = prev_player.GoodA #player.PrevGoodB = prev_player.GoodB #player.PrevGoodC = prev_player.GoodC #player.PrevGoodD = prev_player.GoodD player.PrevA = prev_player.A player.PrevB = prev_player.B player.PrevC = prev_player.C if player.round_number == 2: prev_player = player.in_round(player.round_number - 1) player.InitialBelieveA = prev_player.A player.InitialBelieveB = prev_player.B player.InitialBelieveC = prev_player.C player.InitialBest = prev_player.Best if player.round_number > 2: prev_player = player.in_round(player.round_number - 1) player.InitialBelieveA = prev_player.InitialBelieveA player.InitialBelieveB = prev_player.InitialBelieveB player.InitialBelieveC = prev_player.InitialBelieveC player.InitialBest = prev_player.InitialBest # Bayes Stock A if player.round_number == 1: player.PriorGoodA = 0.5 x = C.PATHA[player.pathA - 1] price_changesA = [x[i] - x[i - 1] for i in range(1, 4)] # Calculate price changes from -3 to -2, from -2 to -1, from -1 to 0 for price_changeA in price_changesA: if price_changeA == -6: numeratorA = player.MinusSixGood * player.PriorGoodA denominatorA = player.MinusSixGood * player.PriorGoodA + player.MinusSixBad * (1 - player.PriorGoodA) elif price_changeA == -3: numeratorA = player.MinusThreeGood * player.PriorGoodA denominatorA = player.MinusThreeGood * player.PriorGoodA + player.MinusThreeBad * (1 - player.PriorGoodA) elif price_changeA == 3: numeratorA = player.ThreeGood * player.PriorGoodA denominatorA = player.ThreeGood * player.PriorGoodA + player.ThreeBad * (1 - player.PriorGoodA) elif price_changeA == 6: numeratorA = player.SixGood * player.PriorGoodA denominatorA = player.SixGood * player.PriorGoodA + player.SixBad * (1 - player.PriorGoodA) player.PriorGoodA = numeratorA / denominatorA if player.round_number > 1 and player.round_number < 5: prev_player = player.in_round(player.round_number - 1) player.PriorGoodA = prev_player.PriorGoodA x = C.PATHA[player.pathA - 1] z = player.round_number CurrentPriceA = x[z+2] player.PriceChangeA = CurrentPriceA - x[z+1] if player.PriceChangeA == -6: numeratorA = player.MinusSixGood*player.PriorGoodA denominatorA = player.MinusSixGood*player.PriorGoodA+player.MinusSixBad*(1-player.PriorGoodA) elif player.PriceChangeA == -3: numeratorA = player.MinusThreeGood*player.PriorGoodA denominatorA = player.MinusThreeGood*player.PriorGoodA+player.MinusThreeBad*(1-player.PriorGoodA) elif player.PriceChangeA == 3: numeratorA = player.ThreeGood * player.PriorGoodA denominatorA = player.ThreeGood * player.PriorGoodA + player.ThreeBad * (1 - player.PriorGoodA) elif player.PriceChangeA == 6: numeratorA = player.SixGood * player.PriorGoodA denominatorA = player.SixGood * player.PriorGoodA + player.SixBad * (1 - player.PriorGoodA) player.PriorGoodA = numeratorA/denominatorA # Bayes Stock B if player.round_number == 1: player.PriorGoodB = 0.5 x = C.PATHB[player.pathB - 1] price_changesB = [x[i] - x[i - 1] for i in range(1, 4)] # Calculate price changes from -3 to -2, from -2 to -1, from -1 to 0 for price_changeB in price_changesB: if price_changeB == -6: numeratorB = player.MinusSixGood * player.PriorGoodB denominatorB = player.MinusSixGood * player.PriorGoodB + player.MinusSixBad * ( 1 - player.PriorGoodB) elif price_changeB == -3: numeratorB = player.MinusThreeGood * player.PriorGoodB denominatorB = player.MinusThreeGood * player.PriorGoodB + player.MinusThreeBad * ( 1 - player.PriorGoodB) elif price_changeB == 3: numeratorB = player.ThreeGood * player.PriorGoodB denominatorB = player.ThreeGood * player.PriorGoodB + player.ThreeBad * (1 - player.PriorGoodB) elif price_changeB == 6: numeratorB = player.SixGood * player.PriorGoodB denominatorB = player.SixGood * player.PriorGoodB + player.SixBad * (1 - player.PriorGoodB) player.PriorGoodB = numeratorB / denominatorB if player.round_number > 1 and player.round_number < 5: prev_player = player.in_round(player.round_number - 1) player.PriorGoodB = prev_player.PriorGoodB x = C.PATHB[player.pathB - 1] z = player.round_number CurrentPriceB = x[z + 2] player.PriceChangeB = CurrentPriceB - x[z + 1] if player.PriceChangeB == -6: numeratorB = player.MinusSixGood * player.PriorGoodB denominatorB = player.MinusSixGood * player.PriorGoodB + player.MinusSixBad * (1 - player.PriorGoodB) elif player.PriceChangeB == -3: numeratorB = player.MinusThreeGood * player.PriorGoodB denominatorB = player.MinusThreeGood * player.PriorGoodB + player.MinusThreeBad * (1 - player.PriorGoodB) elif player.PriceChangeB == 3: numeratorB = player.ThreeGood * player.PriorGoodB denominatorB = player.ThreeGood * player.PriorGoodB + player.ThreeBad * (1 - player.PriorGoodB) elif player.PriceChangeB == 6: numeratorB = player.SixGood * player.PriorGoodB denominatorB = player.SixGood * player.PriorGoodB + player.SixBad * (1 - player.PriorGoodB) player.PriorGoodB = numeratorB / denominatorB # Bayes Stock C if player.round_number == 1: player.PriorGoodC = 0.5 x = C.PATHC[player.pathC - 1] price_changesC = [x[i] - x[i - 1] for i in range(1, 4)] # Calculate price changes from -3 to -2, from -2 to -1, from -1 to 0 for price_changeC in price_changesC: if price_changeC == -6: numeratorC = player.MinusSixGood * player.PriorGoodC denominatorC = player.MinusSixGood * player.PriorGoodC + player.MinusSixBad * ( 1 - player.PriorGoodC) elif price_changeC == -3: numeratorC = player.MinusThreeGood * player.PriorGoodC denominatorC = player.MinusThreeGood * player.PriorGoodC + player.MinusThreeBad * ( 1 - player.PriorGoodC) elif price_changeC == 3: numeratorC = player.ThreeGood * player.PriorGoodC denominatorC = player.ThreeGood * player.PriorGoodC + player.ThreeBad * (1 - player.PriorGoodC) elif price_changeC == 6: numeratorC = player.SixGood * player.PriorGoodC denominatorC = player.SixGood * player.PriorGoodC + player.SixBad * (1 - player.PriorGoodC) player.PriorGoodC = numeratorC / denominatorC if player.round_number > 1 and player.round_number < 5: prev_player = player.in_round(player.round_number - 1) player.PriorGoodC = prev_player.PriorGoodC x = C.PATHC[player.pathC - 1] z = player.round_number CurrentPriceC = x[z + 2] player.PriceChangeC = CurrentPriceC - x[z + 1] if player.PriceChangeC == -6: numeratorC = player.MinusSixGood * player.PriorGoodC denominatorC = player.MinusSixGood * player.PriorGoodC + player.MinusSixBad * (1 - player.PriorGoodC) elif player.PriceChangeC == -3: numeratorC = player.MinusThreeGood * player.PriorGoodC denominatorC = player.MinusThreeGood * player.PriorGoodC + player.MinusThreeBad * (1 - player.PriorGoodC) elif player.PriceChangeC == 3: numeratorC = player.ThreeGood * player.PriorGoodC denominatorC = player.ThreeGood * player.PriorGoodC + player.ThreeBad * (1 - player.PriorGoodC) elif player.PriceChangeC == 6: numeratorC = player.SixGood * player.PriorGoodC denominatorC = player.SixGood * player.PriorGoodC + player.SixBad * (1 - player.PriorGoodC) player.PriorGoodC = numeratorC / denominatorC # Bayes Stock D if player.round_number == 1: player.PriorGoodD = 0.5 x = C.PATHD[player.pathD - 1] price_changesD = [x[i] - x[i - 1] for i in range(1, 4)] # Calculate price changes from -3 to -2, from -2 to -1, from -1 to 0 for price_changeD in price_changesD: if price_changeD == -6: numeratorD = player.MinusSixGood * player.PriorGoodD denominatorD = player.MinusSixGood * player.PriorGoodD + player.MinusSixBad * ( 1 - player.PriorGoodD) elif price_changeD == -3: numeratorD = player.MinusThreeGood * player.PriorGoodD denominatorD = player.MinusThreeGood * player.PriorGoodD + player.MinusThreeBad * ( 1 - player.PriorGoodD) elif price_changeD == 3: numeratorD = player.ThreeGood * player.PriorGoodD denominatorD = player.ThreeGood * player.PriorGoodD + player.ThreeBad * (1 - player.PriorGoodD) elif price_changeD == 6: numeratorD = player.SixGood * player.PriorGoodD denominatorD = player.SixGood * player.PriorGoodD + player.SixBad * (1 - player.PriorGoodD) player.PriorGoodD = numeratorD / denominatorD if player.round_number > 1 and player.round_number < 5: prev_player = player.in_round(player.round_number - 1) player.PriorGoodD = prev_player.PriorGoodD x = C.PATHD[player.pathD - 1] z = player.round_number CurrentPriceD = x[z + 2] player.PriceChangeD = CurrentPriceD - x[z + 1] if player.PriceChangeD == -6: numeratorD = player.MinusSixGood * player.PriorGoodD denominatorD = player.MinusSixGood * player.PriorGoodD + player.MinusSixBad * (1 - player.PriorGoodD) elif player.PriceChangeD == -3: numeratorD = player.MinusThreeGood * player.PriorGoodD denominatorD = player.MinusThreeGood * player.PriorGoodD + player.MinusThreeBad * (1 - player.PriorGoodD) elif player.PriceChangeD == 3: numeratorD = player.ThreeGood * player.PriorGoodD denominatorD = player.ThreeGood * player.PriorGoodD + player.ThreeBad * (1 - player.PriorGoodD) elif player.PriceChangeD == 6: numeratorD = player.SixGood * player.PriorGoodD denominatorD = player.SixGood * player.PriorGoodD + player.SixBad * (1 - player.PriorGoodD) player.PriorGoodD = numeratorD / denominatorD #Bonus Calculation if player.round_number == 1: player.Bonus=0 elif player.round_number == 2: prev_player = player.in_round(player.round_number - 1) player.Bonus = prev_player.Bonus if player.Bonus0==1: if abs(prev_player.A - prev_player.PriorGoodA * 100) <= 5: player.Bonus=1 if player.Bonus0==2: if abs(prev_player.B - prev_player.PriorGoodB * 100) <= 5: player.Bonus=1 if player.Bonus0==3: if abs(prev_player.C - prev_player.PriorGoodC * 100) <= 5: player.Bonus=1 elif player.round_number == 3: prev_player = player.in_round(player.round_number - 1) player.Bonus=prev_player.Bonus if player.Bonus1==1: if abs(prev_player.A - prev_player.PriorGoodA * 100) <= 5: player.Bonus=player.Bonus+1 if player.Bonus1==2: if abs(prev_player.B - prev_player.PriorGoodB * 100) <= 5: player.Bonus=player.Bonus+1 if player.Bonus1==3: if abs(prev_player.C - prev_player.PriorGoodC * 100) <= 5: player.Bonus=player.Bonus+1 elif player.round_number == 4: prev_player = player.in_round(player.round_number - 1) player.Bonus=prev_player.Bonus if player.Bonus2==1: if abs(prev_player.A - prev_player.PriorGoodA * 100) <= 5: player.Bonus=player.Bonus+1 if player.Bonus2==2: if abs(prev_player.B - prev_player.PriorGoodB * 100) <= 5: player.Bonus=player.Bonus+1 if player.Bonus2==3: if abs(prev_player.C - prev_player.PriorGoodC * 100) <= 5: player.Bonus=player.Bonus+1 elif player.round_number == 5: prev_player = player.in_round(player.round_number - 1) player.Bonus=prev_player.Bonus if player.Bonus3==1: if abs(prev_player.A - prev_player.PriorGoodA * 100) <= 5: player.Bonus=player.Bonus+1 if player.Bonus3==2: if abs(prev_player.B - prev_player.PriorGoodB * 100) <= 5: player.Bonus=player.Bonus+1 if player.Bonus3==3: if abs(prev_player.C - prev_player.PriorGoodC * 100) <= 5: player.Bonus=player.Bonus+1 participant=player.participant participant.Bonus=player.Bonus return player.round_number < 5 or (player.round_number==5 and player.id_in_group>1) class Disclosure(Page): form_model = "player" @staticmethod def is_displayed(player): return player.round_number == 1 and player.treatment2 == "public" page_sequence = [Start, PreviousParticipant, PriceDevelopments_Alt, Disclosure]