from otree.api import ( Page, WaitPage, models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range, ) from random import choice import random from random import randint doc = """ 2 firms complete in a market by setting prices for homogenous goods. See "Kruse, J. B., Rassenti, S., Reynolds, S. S., & Smith, V. L. (1994). Bertrand-Edgeworth competition in experimental markets. Econometrica: Journal of the Econometric Society, 343-371." """ class Constants(BaseConstants): players_per_group = 6 name_in_url = 'school_choice' num_rounds = 2 instructions_template = 'school_choice/instructions.html' chosen_round = 41 StudentA = ['student_1', 'student_3', 'student_4'] StudentB = ['student_2', 'student_5', 'student_6'] StudentC = ['student1', 'student3', 'student4'] StudentD = ['student2', 'student5', 'student6'] class Subsession(BaseSubsession): def after_all_players_arrive(self, players): if self.round_number == 1: random.shuffle(players) return players pass class Group(BaseGroup): pass class Player(BasePlayer): random_number = models.IntegerField() slider_value = models.IntegerField(min=0, max=100) number = models.IntegerField() chosen_bet = models.CharField( choices=[['A', 'School A'], ['B', 'School B']], widget=widgets.RadioSelect, verbose_name="Select your choice of school" ) accept = models.StringField() school_accepted = models.StringField() practice = models.IntegerField(min=0, max=100) student_1 = models.BooleanField(blank=True) student_2 = models.BooleanField(blank=True) student_3 = models.BooleanField(blank=True) student_4 = models.BooleanField(blank=True) student_5 = models.BooleanField(blank=True) student_6 = models.BooleanField(blank=True) student1 = models.BooleanField(blank=True) student2 = models.BooleanField(blank=True) student3 = models.BooleanField(blank=True) student4 = models.BooleanField(blank=True) student5 = models.BooleanField(blank=True) student6 = models.BooleanField(blank=True) Percentage = models.IntegerField(min=0, max=100) Percentage2 = models.IntegerField(min=0, max=100) guess_a = models.IntegerField(min=0, max=100) guess_b = models.IntegerField(min=0, max=100) guess_am = models.IntegerField(min=0, max=100) guess_bm = models.IntegerField(min=0, max=100) belief_a = models.IntegerField() winA = models.IntegerField() belief_b = models.IntegerField() winB = models.IntegerField() # FUNCTIONS def creating_session(subsession: Subsession): subsession.group_randomly(fixed_id_in_group=True) def set_winner(group: Group): all_players = group.get_players() for player in all_players: if player.id_in_group in [1, 2]: player.number_JP = choice([100, 90, 75]) elif player.id_in_group in [3, 4]: player.number_JP = choice([95, 80, 65]) else: player.number_JP = choice([85, 70, 60]) chosen_a = [p for p in all_players if p.chosen_betJP == 'A'] chosen_b = [p for p in all_players if p.chosen_betJP == 'B'] top_a = sorted(chosen_a, key=lambda x: x.number_JP, reverse=True)[:2] top_b = sorted(chosen_b, key=lambda x: x.number_JP, reverse=True)[:2] guessa1 = [p for p in all_players if p.chosen_betJP == 'A' or p.id_in_group == 1] guessb1 = [p for p in all_players if p.chosen_betJP == 'B' or p.id_in_group == 1] top_guessa1 = sorted(guessa1, key=lambda x: x.number_JP, reverse=True)[:2] top_guessb1 = sorted(guessb1, key=lambda x: x.number_JP, reverse=True)[:2] guessa2 = [p for p in all_players if p.chosen_betJP == 'A' or p.id_in_group == 2] guessb2 = [p for p in all_players if p.chosen_betJP == 'B' or p.id_in_group == 2] top_guessa2 = sorted(guessa2, key=lambda x: x.number_JP, reverse=True)[:2] top_guessb2 = sorted(guessb2, key=lambda x: x.number_JP, reverse=True)[:2] guessa3 = [p for p in all_players if p.chosen_betJP == 'A' or p.id_in_group == 3] guessb3 = [p for p in all_players if p.chosen_betJP == 'B' or p.id_in_group == 3] top_guessa3 = sorted(guessa3, key=lambda x: x.number_JP, reverse=True)[:2] top_guessb3 = sorted(guessb3, key=lambda x: x.number_JP, reverse=True)[:2] guessa4 = [p for p in all_players if p.chosen_betJP == 'A' or p.id_in_group == 4] guessb4 = [p for p in all_players if p.chosen_betJP == 'B' or p.id_in_group == 4] top_guessa4 = sorted(guessa4, key=lambda x: x.number_JP, reverse=True)[:2] top_guessb4 = sorted(guessb4, key=lambda x: x.number_JP, reverse=True)[:2] guessa5 = [p for p in all_players if p.chosen_betJP == 'A' or p.id_in_group == 5] guessb5 = [p for p in all_players if p.chosen_betJP == 'B' or p.id_in_group == 5] top_guessa5 = sorted(guessa5, key=lambda x: x.number_JP, reverse=True)[:2] top_guessb5 = sorted(guessb5, key=lambda x: x.number_JP, reverse=True)[:2] guessa6 = [p for p in all_players if p.chosen_betJP == 'A' or p.id_in_group == 6] guessb6 = [p for p in all_players if p.chosen_betJP == 'B' or p.id_in_group == 6] top_guessa6 = sorted(guessa6, key=lambda x: x.number_JP, reverse=True)[:2] top_guessb6 = sorted(guessb6, key=lambda x: x.number_JP, reverse=True)[:2] for player in top_a: player.winA_JP = 10 for player in top_b: player.winB_JP = 7 for player in all_players: if player.id_in_group == 1 and player in top_guessa1: player.belief_a_JP = 1 elif player.id_in_group == 2 and player in top_guessa2: player.belief_a_JP = 1 elif player.id_in_group == 3 and player in top_guessa3: player.belief_a_JP = 1 elif player.id_in_group == 4 and player in top_guessa4: player.belief_a_JP = 1 elif player.id_in_group == 5 and player in top_guessa5: player.belief_a_JP = 1 elif player.id_in_group == 6 and player in top_guessa6: player.belief_a_JP = 1 for player in all_players: if player.id_in_group == 1 and player in top_guessb1: player.belief_b = 1 elif player.id_in_group == 2 and player in top_guessb2: player.belief_b = 1 elif player.id_in_group == 3 and player in top_guessb3: player.belief_b = 1 elif player.id_in_group == 4 and player in top_guessb4: player.belief_b = 1 elif player.id_in_group == 5 and player in top_guessb5: player.belief_b = 1 elif player.id_in_group == 6 and player in top_guessb6: player.belief_b = 1 for player in all_players: if player in top_a or player in top_b: player.accept_JP = 'accepted' else: player.accept_JP = 'rejected' def set_payoffs(group: Group): for player in group.get_players(): if player.random_number_JP ==1: player.payoff = player.in_round(1).winA_JP + player.in_round(1).winB_JP elif player.random_number_JP == 2: player.payoff = player.in_round(2).winA_JP + player.in_round(2).winB_JP elif player.random_number_JP == 3: if player.in_round(2).belief_a_JP ==1: player.payoff = player.in_round(2).guess_a_JP else: player.payoff = 100-player.in_round(2).guess_a_JP else: if player.in_round(2).belief_a_JP ==1: player.payoff = player.in_round(2).guess_b_JP else: player.payoff = 100-player.in_round(2).guess_b_JP # PAGES class Introduction(Page): pass class Introduction2(Page): @staticmethod def is_displayed(player: Player): return player.round_number == 1 class Intro1(Page): @staticmethod def is_displayed(player: Player): return player.round_number == 1 class Intro2(Page): form_model = 'player' form_fields = ['student_1', 'student_2', 'student_3','student_4', 'student_5', 'student_6'] @staticmethod def is_displayed(player: Player): return player.round_number == 1 class WrongA(Page): @staticmethod def is_displayed(player: Player): return player.field_maybe_none('student_1')==None or player.field_maybe_none('student_3')==None or player.field_maybe_none('student_4')==True form_model = 'player' form_fields = ['student_2', 'student_5', 'student_6'] @staticmethod def is_displayed(player: Player): return player.round_number == 1 class CorrectA(Page): @staticmethod def is_displayed(player: Player): return player.field_maybe_none('student_1')==1 and player.field_maybe_none('student_3')==1 and player.field_maybe_none('student_4')==None form_model = 'player' form_fields = ['student_2', 'student_5', 'student_6'] @staticmethod def is_displayed(player: Player): return player.round_number == 1 class WrongB(Page): @staticmethod def is_displayed(player: Player): if player.round_number == 1: return player.field_maybe_none('student_2')==0 or player.field_maybe_none('student_5')==1 or player.field_maybe_none('student_6')==0 form_model = 'player' form_fields = ['student1', 'student2', 'student3','student4', 'student5', 'student6'] class CorrectB(Page): @staticmethod def is_displayed(player: Player): if player.round_number == 1: return player.field_maybe_none('student_2') == True and player.field_maybe_none( 'student_5') == None and player.field_maybe_none('student_6') == True class WrongB2(Page): @staticmethod def is_displayed(player: Player): if player.round_number == 1: if player.field_maybe_none('student_2')!=1 and player.field_maybe_none( 'student_5')!=0 and player.field_maybe_none( 'student_6')!=1: return player.field_maybe_none('student1') == 0 or player.field_maybe_none( 'student2') == 0 or player.field_maybe_none( 'student3') == 0 or player.field_maybe_none( 'student4') == 1 or player.field_maybe_none( 'student5') == 1 or player.field_maybe_none( 'student6') == 0 class Intro4(Page): form_model = 'player' form_fields = ['Percentage'] @staticmethod def is_displayed(player: Player): return player.round_number == 1 pass class Intro4wrong(Page): pass @staticmethod def is_displayed(player: Player): if player.round_number == 1: return player.field_maybe_none('Percentage') != 7 class Intro4wrong2(Page): form_model = 'player' form_fields = ['Percentage2'] @staticmethod def is_displayed(player: Player): if player.round_number == 1: return player.field_maybe_none('Percentage') != 7 class Intro4wrongRight(Page): @staticmethod def is_displayed(player: Player): if player.round_number == 1: return player.field_maybe_none('Percentage2') == 30 class Intro4wrongWrong(Page): @staticmethod def is_displayed(player: Player): if player.round_number == 1: if player.field_maybe_none('Percentage') != 7: return player.field_maybe_none('Percentage2') != 30 class Intro4right(Page): @staticmethod def is_displayed(player: Player): if player.round_number == 1: return player.field_maybe_none('Percentage') == 7 class Intro5(Page): pass @staticmethod def is_displayed(player: Player): return player.round_number == 1 class ChoosingBet(Page): form_model = 'player' form_fields = ['chosen_bet'] class GuessingA(Page): form_model = 'player' form_fields = ['guess_a','guess_am'] class GuessingB(Page): form_model = 'player' form_fields = ['guess_b','guess_bm'] class ResultsWaitPage(WaitPage): after_all_players_arrive = 'set_winner' class Results(Page): @staticmethod def vars_for_template(player: Player): group = player.group all_players = group.get_players() top_a = sorted( [p for p in all_players if p.chosen_betJP == 'A'], key=lambda x: x.number_JP, reverse=True)[:2] top_b = sorted( [p for p in all_players if p.chosen_betJP == 'B'], key=lambda x: x.number_JP, reverse=True)[:2] top_guessa1 = sorted( [p for p in all_players if p.chosen_betJP == 'A' or p.id_in_group == 1], key=lambda x: x.number_JP, reverse=True)[:2] top_guessb1 = sorted( [p for p in all_players if p.chosen_betJP == 'B' or p.id_in_group == 1], key=lambda x: x.number_JP, reverse=True)[:2] top_guessa2 = sorted( [p for p in all_players if p.chosen_betJP == 'A' or p.id_in_group == 2], key=lambda x: x.number_JP, reverse=True)[:2] top_guessb2 = sorted( [p for p in all_players if p.chosen_betJP == 'B' or p.id_in_group == 2], key=lambda x: x.number_JP, reverse=True)[:2] top_guessa3 = sorted( [p for p in all_players if p.chosen_betJP == 'A' or p.id_in_group == 3], key=lambda x: x.number_JP, reverse=True)[:2] top_guessb3 = sorted( [p for p in all_players if p.chosen_betJP == 'B' or p.id_in_group == 3], key=lambda x: x.number_JP, reverse=True)[:2] top_guessa4 = sorted( [p for p in all_players if p.chosen_betJP == 'A' or p.id_in_group == 4], key=lambda x: x.number_JP, reverse=True)[:2] top_guessb4 = sorted( [p for p in all_players if p.chosen_betJP == 'B' or p.id_in_group == 4], key=lambda x: x.number_JP, reverse=True)[:2] top_guessa5 = sorted( [p for p in all_players if p.chosen_betJP == 'A' or p.id_in_group == 5], key=lambda x: x.number_JP, reverse=True)[:2] top_guessb5 = sorted( [p for p in all_players if p.chosen_betJP == 'B' or p.id_in_group == 5], key=lambda x: x.number_JP, reverse=True)[:2] top_guessa6 = sorted( [p for p in all_players if p.chosen_betJP == 'A' or p.id_in_group == 6], key=lambda x: x.number_JP, reverse=True)[:2] top_guessb6 = sorted( [p for p in all_players if p.chosen_betJP == 'B' or p.id_in_group == 6], key=lambda x: x.number_JP, reverse=True)[:2] return { 'top_a': top_a, 'top_b': top_b, 'top_guessa1': top_guessa1, 'top_guessb1': top_guessb1, 'top_guessa2': top_guessa2, 'top_guessb2': top_guessb2, 'top_guessa3': top_guessa3, 'top_guessb3': top_guessb3, 'top_guessa4': top_guessa4, 'top_guessb4': top_guessb4, 'top_guessa5': top_guessa5, 'top_guessb5': top_guessb5, 'top_guessa6': top_guessa6, 'top_guessb6': top_guessb6, } pass class Payout1(ResultsWaitPage): after_all_players_arrive = 'set_payoffs' @staticmethod def is_displayed(player: Player): return player.round_number == 2 class Payout(Page): @staticmethod def is_displayed(player: Player): return player.round_number == 2 class Intro3(Page): form_model = 'player' @staticmethod def vars_for_template(player: Player): example_report = random.randint(2, 5) return dict(example_report=example_report, num_rounds=Constants.num_rounds - 1,) @staticmethod def is_displayed(player: Player): return player.round_number == 1 class Intro3_1(Page): form_model = 'player' class Belief(Page): form_model = 'player' form_fields = ['guess_a','guess_b','guess_n'] class Belief2(Page): form_model = 'player' form_fields = ['guess_b','guess_n'] class Pose(WaitPage): wait_for_all_groups = True @staticmethod def is_displayed(player: Player): if player.round_number == 1: return class Number (Page): form_model = 'player' form_fields = ['random_number'] @staticmethod def is_displayed(player: Player): return player.round_number == 2 class Practice_rev (Page): pass class Practice1_rev (Page): pass class Practice2 (Page): pass class Practice2_rev (Page): pass page_sequence = [Practice1_rev, Intro1, Intro2, WrongB, WrongB2, Intro3,Intro3_1,Intro4, Intro4right, Intro4wrong,Intro4wrong2, Intro4wrongRight, Intro4wrongWrong, Intro5, ChoosingBet, GuessingA, GuessingB, ResultsWaitPage, Results, Pose, Number,Payout1,Payout]