from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range ) import random from django.db import models as djmodels author = "Philip Chapkovski, chapkovski@gmail.com" doc = """ Public Good Game with Punishment (Fehr and Gaechter). Fehr, E. and Gachter, S., 2000. Cooperation and punishment in public goods experiments. American Economic Review, 90(4), pp.980-994. """ class Constants(BaseConstants): name_in_url = 'pgg' players_per_group = 3 num_others_per_group = players_per_group - 1 num_rounds = 6 instructions_template = 'pgg/Instructions.html' endowment = 20 efficiency_factor = 1.5 MPCR=efficiency_factor/players_per_group punishment_endowment = 6 punishment_factor = 2 example_payoff=30*efficiency_factor yen_rate=0.3 q1_a = 3 # conditionGSI =1 from django.db.models import Q, F class Subsession(BaseSubsession): conditionGSI = models.IntegerField() def get_game(self): self.conditionGSI = self.session.config['conditionGSI'] def creating_session(self): ps = [] for p in self.get_players(): others_r=random.sample(p.get_others_in_group(),Constants.num_others_per_group) for o in others_r: ps.append(Punishment(sender=p, receiver=o, )) Punishment.objects.bulk_create(ps) class Group(BaseGroup): total_contribution = models.IntegerField() average_contribution = models.FloatField() individual_share = models.FloatField() individual_share_presen1=models.FloatField() # individual_share = models.CurrencyField() min_contribution=models.FloatField() def set_pd_payoffs(self): contributions = [ p.contribution for p in self.get_players() if p.contribution != None ] self.total_contribution = sum([p.contribution for p in self.get_players()]) self.min_contribution=min(contributions) self.individual_share = ( self.total_contribution * Constants.efficiency_factor / Constants.players_per_group) # self.min_contribution * Constants.efficiency_factor) self.average_contribution=(self.total_contribution / Constants.players_per_group) self.individual_share_presen1 =round(self.individual_share,1) for p in self.get_players(): p.payoff_before = (Constants.endowment - p.contribution) + self.individual_share p.profit_before = (Constants.endowment - p.contribution) + self.individual_share for p in self.get_players(): if self.average_contribution < 10 and self.subsession.conditionGSI == 1: p.Ipunishment = -2 p.punish_pat = 1 elif self.min_contribution < 10 and self.subsession.conditionGSI == 2: p.Ipunishment = -2 p.punish_pat = 2 elif p.contribution < 10 and self.subsession.conditionGSI == 3: p.Ipunishment = -2 p.punish_pat = 3 elif self.average_contribution >= 10 and self.subsession.conditionGSI == 1: p.Ipunishment = 0 p.punish_pat = 4 elif self.min_contribution >= 10 and self.subsession.conditionGSI == 2: p.Ipunishment = 0 p.punish_pat = 5 elif p.contribution >= 10 and self.subsession.conditionGSI == 3: p.Ipunishment = 0 p.punish_pat = 6 for p in self.get_players(): p.pd_payoff = p.payoff_before + p.Ipunishment p.pd_profit = p.profit_before + p.Ipunishment p.set_punishment_endowment() for p in self.get_players(): p.pd_profit_presen = round(p.pd_profit, 1) p.Ipunishment_presen=p.Ipunishment*-1 # p.Yen_profit = p.participant.pd_payoff * Constants.yen_rate # for p in self.get_players(): # p.pd_payoff = sum([+ Constants.endowment, # - p.contribution, # + self.individual_share, # ]) # p.pd_profit = sum([+ Constants.endowment, # - p.contribution, # + self.individual_share, # ]) # p.set_punishment_endowment() #元々のpayoff計算 # def set_pd_payoffs(self): # self.total_contribution = sum([p.contribution for p in self.get_players()]) # self.average_contribution = self.total_contribution / Constants.players_per_group # self.individual_share = self.total_contribution * Constants.efficiency_factor / Constants.players_per_group # for p in self.get_players(): # p.pd_payoff = sum([+ Constants.endowment, # - p.contribution, # + self.individual_share, # ]) # p.set_punishment_endowment() def set_punishments(self): for p in self.get_players(): p.set_punishment() for p in self.get_players(): p.set_payoff() for p in self.get_players(): p.profit_presen = round(p.profit,1) class Player(BasePlayer): # contribution = models.IntegerField(verbose_name='あなたはいくら提供しますか?', # choices=range(0, Constants.endowment+1), # initial=None) Total_DropPC = models.IntegerField() contribution = models.PositiveIntegerField( min=0, max=Constants.endowment, doc="""The amount contributed by the player""", label="あなたはいくら提供しますか?(0点-20点)".format(Constants.endowment) ) punishment_sent = models.IntegerField() punishment_received = models.IntegerField() pd_payoff = models.CurrencyField(doc='to store payoff from contribution stage') punishment_endowment = models.IntegerField(initial=0, doc='punishment endowment') profit_before = models.FloatField() pd_profit = models.FloatField() profit_presen = models.FloatField() pd_profit_presen = models.FloatField() payoff_before = models.CurrencyField() Ipunishment = models.IntegerField() total_profit = models.FloatField() total_payoff = models.CurrencyField() punish_pat = models.IntegerField() Yen_profit = models.CurrencyField() Ipunishment_presen=models.IntegerField() dropWP = models.IntegerField() dropGS = models.IntegerField() dropPC = models.IntegerField(initial=0) dropPP = models.IntegerField() dropPR = models.IntegerField() # pd_profit = models.FloatField() profit = models.FloatField() # profit_presen = models.FloatField() def set_payoff(self): self.payoff = self.pd_payoff - self.punishment_sent - self.punishment_received self.profit = self.pd_profit - self.punishment_sent - self.punishment_received def set_punishment_endowment(self): assert self.pd_payoff is not None, 'You have to set pd_payoff before setting punishment endowment' # self.punishment_endowment = min(self.pd_payoff, Constants.punishment_endowment) self.punishment_endowment = Constants.punishment_endowment def set_punishment(self): self.punishment_sent = sum([i.amount for i in self.punishments_sent.all()]) self.punishment_received = sum( [i.amount for i in self.punishments_received.all()]) * Constants.punishment_factor q11 = models.IntegerField(initial=None, choices=[ [1, '3点'], [2, '5点'], [3, '11点'], ], verbose_name='あなたは、他メンバーの減額に合計2点使用し、他メンバーから合計3点減額に使用されたとします。あなたは、減額ステージでいくら失うことになりますか?', widget=widgets.RadioSelectHorizontal()) q12 = models.IntegerField(initial=None, choices=[ [1, '3点'], [2, '5点'], [3, '11点'], ], verbose_name='あなたは、他メンバーの減額に合計2点使用し、他メンバーから合計3点減額に使用されたとします。あなたは、減額ステージでいくら失うことになりますか?', widget=widgets.RadioSelectHorizontal()) q13 = models.IntegerField(initial=None, choices=[ [1, '3点'], [2, '5点'], [3, '11点'], ], verbose_name='あなたは、他メンバーの減額に合計2点使用し、他メンバーから合計3点減額に使用されたとします。あなたは、減額ステージでいくら失うことになりますか?', widget=widgets.RadioSelectHorizontal()) class Punishment(djmodels.Model): sender = djmodels.ForeignKey(to=Player, related_name='punishments_sent', on_delete=djmodels.CASCADE) receiver = djmodels.ForeignKey(to=Player, related_name='punishments_received', on_delete=djmodels.CASCADE) amount = models.IntegerField(initial=0)