from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range ) import random doc = """ PGG5 - manager rewards / punishes fixed amount """ class Constants(BaseConstants): name_in_url = 'public_goods_Wmanager_v2' players_per_group = 4 num_rounds = 10 punishment_amount = 10 reward_amount = 10 instructions_template_for_workers = 'public_goods_Wmanager_v2/Instructions_for_workers.html' instructions_template_for_manager = 'public_goods_Wmanager_v2/Instructions_for_manager.html' endowment = c(100) multiplier = 2 class Subsession(BaseSubsession): def creating_session(self): self.session.vars['assortment'] = 0 def vars_for_admin_report(self): contributions = [p.contribution for p in self.get_players() if p.contribution != None] if contributions: return { 'avg_contribution': sum(contributions)/len(contributions), 'min_contribution': min(contributions), 'max_contribution': max(contributions), } else: return { 'avg_contribution': '(no data)', 'min_contribution': '(no data)', 'max_contribution': '(no data)', } #TO WRITE A COMMENT WHAT's HAPPENING HERE #to know how much each person contributes, define a field contribution #we are interested in knowing the total contributions to the group, and the individual share returned to each player #so we define those 2 fields class Group(BaseGroup): total_contribution = models.CurrencyField() individual_share = models.CurrencyField() total_payoff = models.CurrencyField() #to set the payoffs: the common pool is multiplying the contribution w 2 and is equally diving according to how many players are playing #define a method that calculates the payoff (and other fields like total_contribution and individual_share - that's set_payoffs def set_payoffs(self): self.total_contribution = sum([p.contribution for p in self.get_players()]) self.individual_share = self.total_contribution * Constants.multiplier / Constants.players_per_group self.total_payoff = self.total_contribution * Constants.multiplier for p in self.get_players(): playerID = p.id_in_group totalPunishment = 0 totalReward = 0 for otherPlayers in self.get_players(): if playerID == 1: if otherPlayers.punish_1: totalPunishment += Constants.punishment_amount elif playerID == 2: if otherPlayers.punish_2: totalPunishment += Constants.punishment_amount elif playerID == 3: if otherPlayers.punish_3: totalPunishment += Constants.punishment_amount elif playerID == 4: if otherPlayers.punish_4: totalPunishment += Constants.punishment_amount for otherPlayers in self.get_players(): if playerID == 1: if otherPlayers.reward_1: totalReward += Constants.reward_amount elif playerID == 2: if otherPlayers.reward_2: totalReward += Constants.reward_amount elif playerID == 3: if otherPlayers.reward_3: totalReward += Constants.reward_amount elif playerID == 4: if otherPlayers.reward_4: totalReward += Constants.reward_amount p.individual_share_after_PR = self.individual_share - totalPunishment + totalReward p.payoff = (Constants.endowment - p.contribution) + self.individual_share - totalPunishment + totalReward class Player(BasePlayer): individual_share_after_PR = models.CurrencyField() contribution = models.CurrencyField( min=0, max=Constants.endowment, doc="""The amount contributed by the player""", ) age = models.PositiveIntegerField( verbose_name='What is your age?', min=13, max=125) gender = models.StringField( choices=['Male', 'Female'], verbose_name='What is your gender?', widget=widgets.RadioSelect) punish_1 = models.BooleanField(blank=True) punish_2 = models.BooleanField(blank=True) punish_3 = models.BooleanField(blank=True) punish_4 = models.BooleanField(blank=True) reward_1 = models.BooleanField(blank=True) reward_2 = models.BooleanField(blank=True) reward_3 = models.BooleanField(blank=True) reward_4 = models.BooleanField(blank=True)