from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range, ) import random author = 'Chanjoo Lee' doc = """ Repeated cheap talk """ class Constants(BaseConstants): name_in_url = 'repeated_CT' players_per_group = None num_rounds = 11 Roles=['S','R','R_vs_bot'] incentive = 15000 num_prac_rounds = 1 class Subsession(BaseSubsession): expertise=models.FloatField(initial=0.9) robotR=models.IntegerField(initial=0) gamemode=models.IntegerField(initial=0) local_seed=models.IntegerField(initial=-1) local_seed2 = models.IntegerField(initial=-1) num_S=models.IntegerField(initial=1) def creating_session(self): self.expertise=self.session.config['expertise'] self.robotR=self.session.config['robotR'] self.gamemode=self.session.config['gamemode'] self.num_S=self.session.config['num_S'] players=self.get_players() self.local_seed = random.randint(0, 999) self.local_seed2 = random.randint(0, 999) if self.robotR == 0: local_random = random.Random(99) local_random.shuffle(players) to_shuffle = players[self.num_S:] random.Random(self.local_seed + self.round_number).shuffle(to_shuffle) players = players[ :self.num_S] + to_shuffle # The first num_S player are not shuffled for index in range(0, len(players)): if index < self.num_S: # for the first num_R_vs_bot players, they are assigned R against robot S players[index].roles = Constants.Roles[0] players[index].pseudo_group = index + 1 local_random = random.Random(self.local_seed + players[index].pseudo_group) draw = local_random.random() if draw <= 2 / 3: players[index].type = 0 # Blue else: players[index].type = 1 # Red local_random2 = random.Random(self.local_seed + players[index].pseudo_group+1) draw2 = local_random2.random() if draw2 <= self.expertise: players[index].shell = players[index].type else: players[index].shell = 1-players[index].type if self.gamemode == 2: local_random3 = random.Random(self.local_seed2 + players[index].pseudo_group) draw3 = local_random3.random() if draw3 <= 2 / 3: players[index].type2 = 0 # Blue else: players[index].type2 = 1 # Red local_random4 = random.Random(self.local_seed2 + players[index].pseudo_group + 1) draw4 = local_random4.random() if draw4 <= self.expertise: players[index].shell2 = players[index].type2 else: players[index].shell2 = 1 - players[index].type2 elif self.num_S <= index < 2 * self.num_S: # R players[index].roles = Constants.Roles[1] players[index].pseudo_group = index - self.num_S + 1 players[index].type = players[index - self.num_S].type players[index].shell = players[index - self.num_S].shell if self.gamemode == 2: players[index].type2 = players[index - self.num_S].type2 players[index].shell2 = players[index - self.num_S].shell2 else: # R with robot S players[index].roles = Constants.Roles[2] players[index].pseudo_group = index - self.num_S + 1 local_random = random.Random(self.local_seed + players[index].pseudo_group) draw = local_random.random() if draw <= 2 / 3: players[index].type = 0 # Blue else: players[index].type = 1 # Red local_random2 = random.Random(self.local_seed + players[index].pseudo_group + 1) draw2 = local_random2.random() if draw2 <= self.expertise: players[index].shell = players[index].type else: players[index].shell = 1 - players[index].type if self.gamemode == 2: local_random3 = random.Random(self.local_seed2 + players[index].pseudo_group) draw3 = local_random3.random() if draw3 <= 2 / 3: players[index].type2 = 0 # Blue else: players[index].type2 = 1 # Red local_random4 = random.Random(self.local_seed2 + players[index].pseudo_group + 1) draw4 = local_random4.random() if draw4 <= self.expertise: players[index].shell2 = players[index].type2 else: players[index].shell2 = 1 - players[index].type2 else: self.num_S=self.session.num_participants for index in range(0, len(players)): players[index].roles = Constants.Roles[0] local_random = random.Random(self.local_seed + index) draw = local_random.random() if draw <= 2 / 3: players[index].type = 0 # Blue else: players[index].type = 1 # Red local_random2 = random.Random(self.local_seed + index + 1) draw2 = local_random2.random() if draw2 <= self.expertise: players[index].shell = players[index].type else: players[index].shell = 1 - players[index].type if self.gamemode == 2: local_random3 = random.Random(self.local_seed2 + index) draw3 = local_random3.random() if draw3 <= 2 / 3: players[index].type2 = 0 # Blue else: players[index].type2 = 1 # Red local_random4 = random.Random(self.local_seed2 + index) draw4 = local_random4.random() if draw4 <= self.expertise: players[index].shell2 = players[index].type2 else: players[index].shell2 = 1 - players[index].type2 class Group(BaseGroup): pass class Player(BasePlayer): roles = models.StringField() type = models.IntegerField(initial=-1, min=0, max=1) shell=models.IntegerField(initial=-1,min=0,max=1) type2 = models.IntegerField(initial=-1, min=0, max=1) shell2 = models.IntegerField(initial=-1, min=0, max=1) recom_0=models.FloatField() recom_1=models.FloatField() recom2_0=models.FloatField() recom2_1=models.FloatField() message_sent = models.IntegerField(initial=-1) message_sent2 = models.IntegerField(initial=-1) conjecture = models.IntegerField(initial=-1, min=0, max=1) conjecture2 = models.IntegerField(initial=-1, min=0, max=1) R_sbelief = models.FloatField() R_tbelief = models.FloatField() S_tbelief = models.FloatField() message_received = models.IntegerField(initial=-1, min=0, max=1) message_received2 = models.CurrencyField(initial=-1, min=0, max=1) pseudo_group = models.IntegerField() payoff1 = models.CurrencyField() roundpay = models.CurrencyField() exer_0 = models.FloatField() exer_1 = models.FloatField() finalDeg0 = models.FloatField() finalDeg1 = models.FloatField() Rpayoff = models.IntegerField(initial=-1, min=0, max=Constants.incentive) Rpayoff1 = models.IntegerField(initial=-1, min=0, max=Constants.incentive) check_slider_one = models.IntegerField() check_slider_two = models.IntegerField() def live_instruct(self, data): if data['read'] == 1: if self.read == -1: self.read = 1 return {self.id_in_group: {'read': self.read}} read = models.IntegerField(initial=-1) q1a = models.IntegerField(choices=[[1, "True"], [2, "False"]], widget=widgets.RadioSelectHorizontal, label="A. 귀하의 역할은 각 라운드에 무작위로 배정될 것입니다. 따라서, 귀하는 Sender의 역할 또한 플레이해보게 될 수 있습니다.") q1b = models.IntegerField(choices=[[1, "True"], [2, "False"]], widget=widgets.RadioSelectHorizontal, label="B. 귀하는 각 라운드에 H-sender와 무작위로 매칭될 것입니다.") q1c = models.IntegerField(choices=[[1, "True"], [2, "False"]], widget=widgets.RadioSelectHorizontal, label="C. 귀하는 각 라운드에 H-sender 혹은 C-sender에 50:50 확률로 무작위 매칭될 것입니다.") q2a = models.IntegerField(choices=[[1, "True"], [2, "False"]], widget=widgets.RadioSelectHorizontal, label="A. 귀하의 역할은 각 라운드에 무작위로 배정될 것입니다. 따라서, 귀하는 Receiver의 역할 또한 플레이해보게 될 수 있습니다.") q2b = models.IntegerField(choices=[[1, 'True'], [2, 'False']], widget=widgets.RadioSelectHorizontal, label="B. 귀하는 각 라운드에 Receiver와 무작위로 매칭될 것입니다.") q2c = models.IntegerField(choices=[[1, 'True'], [2, 'False']], widget=widgets.RadioSelectHorizontal, label="C. 귀하와 매칭되는 Receiver는 귀하가 H-Sender라는 사실을 알고 있습니다.") q3 = models.IntegerField(choices=[[1, 'True'], [2, 'False']], widget=widgets.RadioSelectHorizontal, label="각 라운드는 두 stage로 구성되어 있습니다. 각 stage에서, 귀하는 동일한 sender와 매칭될 것입니다.") q4 = models.IntegerField(choices=[[1, 'True'], [2, 'False']], widget=widgets.RadioSelectHorizontal, label="각 라운드가 시작할 때, 각 sender-receiver짝에 대해 공 하나가 박스에서 무작위로 뽑힐 것입니다. 이 공이 실험참여자들의 두 stage 모두에서의 보수를 결정할 것입니다.") q5 = models.IntegerField(choices=[[1, 'True'], [2, 'False']], widget=widgets.RadioSelectHorizontal, label="박스 안에는 30개의 공이 들어 있습니다. 각 공은 안쪽의 Core와 바깥쪽의 Shell로 구성되어 있습니다. 박스 안의 공들 중 90%의 공들만 Core와 Shell의 색깔이 일치합니다.") q6 = models.IntegerField(choices=[[1, 'True'], [2, 'False']], widget=widgets.RadioSelectHorizontal, label="만약 귀하가 Receiver에 배정받았다면, 귀하가 선택한 action이 뽑힌 공의 Shell의 색깔과 일치할 때 15000원을 받으시게 됩니다.") q7 = models.IntegerField(choices=[[1, 'True'], [2, 'False']], widget=widgets.RadioSelectHorizontal, label="만약 귀하가 H-Sender에 배정받았다면, 귀하의 상대편 Receiver가 선택한 action이 뽑힌 공의 Core 색깔과 일치할 때 15000원을 받으시게 됩니다.") q8 = models.IntegerField(choices=[[1, 'True'], [2, 'False']], widget=widgets.RadioSelectHorizontal, label="귀하의 최종 수령액은 무작위로 뽑힌 한 라운드에 의해 계산될 것입니다. 본 라운드 중 앞쪽의 라운드들이 뒤쪽의 라운드들에 비해 더 선택될 확률이 높습니다.") def set_error_message(self, value): if self.subsession.gamemode == 2: correct_answers = {"q1a": 2, "q1b": 2, "q1c": 1, "q2a": 2, "q2b": 1, "q2c": 2, "q3": 1, "q4": 2, "q5": 1, "q6": 2, "q7": 2, "q8": 2 } else: correct_answers = {"q1a": 2, "q1b": 2, "q1c": 1, "q2a": 2, "q2b": 1, "q2c": 2, "q5": 1, "q6": 2, "q7": 2, "q8": 2 } list_answers = list(value.items())[0:] list_correct_answers = list(correct_answers.items()) if list_answers != list_correct_answers: Text = '제출하신 답 중 일부가 잘못되었습니다. 상단의 바를 이용하여 instruction을 자유롭게 다시 보실 수 있습니다.' \ '오답(들)을 고친 뒤 다시 제출해주세요.' return Text