from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range ) import random doc = '\nSender-receiver game\n' class Constants(BaseConstants): name_in_url = 'sender_receiver' players_per_group = 2 num_rounds = 10 state_space = 5 k = 1.4 belief_round = 5 class Subsession(BaseSubsession): bias = models.FloatField() noise = models.FloatField() truthful_messages = models.IntegerField() followed_messages = models.IntegerField() truth_running = models.IntegerField() followed_running = models.IntegerField() def creating_session(self): if self.round_number >= Constants.num_rounds/2: if self.session.config['treatment_honest']: self.bias = 0.2 else: self.bias = 2 else: self.bias = 1 self.group_randomly(fixed_id_in_group=True) self.noise = int(random.uniform(-5, 5)) for group in self.get_groups(): group.state = random.randint(1, Constants.state_space) self.payoff_matrices() for p in self.get_players(): p.belief_payoff = 0 def payoff_matrices(self): sender_matrix = [] receiver_matrix = [] for state in range(1, Constants.state_space + 1): sender = [] receiver = [] for action in range(1, Constants.state_space + 1): u_s = int(110 - 20 * pow(abs(state + self.bias - action), Constants.k) + self.noise) u_r = int(110 - 20 * pow(abs(state - action), Constants.k) + self.noise) sender.append(round(u_s, 2)) receiver.append(round(u_r, 2)) sender_matrix.append(sender) receiver_matrix.append(receiver) return sender_matrix, receiver_matrix def information(self): self.truthful_messages = 0 self.followed_messages = 0 for group in self.get_groups(): self.truthful_messages = self.truthful_messages + group.truthful_message self.followed_messages = self.followed_messages + group.followed_message self.truth_running = self.truthful_messages self.followed_running = self.followed_messages for r in range(1, min(2, self.round_number)): self.truth_running = self.truth_running + self.in_round(self.round_number - r).truthful_messages self.followed_running = self.followed_running + self.in_round(self.round_number - r).followed_messages total = (self.session.num_participants / Constants.players_per_group) * min(2, self.round_number) self.truth_running = int(round(100 * self.truth_running / total, 1)) self.followed_running = int(round(100 * self.followed_running / total, 1)) class Group(BaseGroup): state = models.IntegerField(min=1, max=Constants.state_space) message = models.IntegerField(min=0, max=5) action = models.IntegerField(min=1, max=5) truthful_message = models.IntegerField() followed_message = models.IntegerField() def set_payoffs(self): sender = self.get_player_by_role('sender') receiver = self.get_player_by_role('receiver') sender.payoff = int(110 - 20 * pow(abs(self.state + self.subsession.bias - self.action), Constants.k) + self.subsession.noise) receiver.payoff = int(110 - 20 * pow(abs(self.state - self.action), Constants.k) + self.subsession.noise) def information_group(self): self.truthful_message = int((self.state == self.message)) self.followed_message = int((self.message == self.action)) class Player(BasePlayer): belief_sender = models.IntegerField(min=0, max=100) belief_receiver = models.IntegerField(min=0, max=100) belief_payoff = models.IntegerField() def role(self): if self.session.config['role_change']: if self.round_number % 2 == 1: if self.id_in_group == 1: return 'sender' else: return 'receiver' else: if self.id_in_group == 1: return 'receiver' else: return 'sender' else: if self.id_in_group == 1: return 'sender' else: return 'receiver' def set_belief_payoffs(self): if self.round_number in \ [Constants.belief_round, Constants.num_rounds/2 - Constants.belief_round, Constants.num_rounds/2 + Constants.belief_round, Constants.num_rounds - Constants.belief_round]: if abs(self.belief_sender - self.subsession.in_round(self.round_number - 1).truth_running) < 10: self.belief_payoff = self.belief_payoff + 50 if abs(self.belief_receiver - self.subsession.in_round(self.round_number - 1).followed_running) < 10: self.belief_payoff = self.belief_payoff + 50