from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range ) import random doc = """ This is two-player Public Goods Game made for Daisuke Nakama in March 2020. In Homo condition, both participants in a group is given either 40yen or 20yen. For example, once a participant is given 40yen, he will be given 40yen every round. They usually keep playing with each other until the last round; but in One-shot condition, they change who to play with every round and their endowment also changes. """ class Constants(BaseConstants): name_in_url = 'Nakama2020_public_goods_Homo' players_per_group = 2 num_rounds = 3 # """Amount allocated to each player""" endowment_1 = c(40) endowment_2 = c(20) multiplier = 1.5 class Subsession(BaseSubsession): '''One-shotでのみ使用 def creating_session(self): self.group_randomly(fixed_id_in_group=False) ''' def creating_session(self): import itertools treatment = itertools.cycle(['Homo40', 'Homo20']) for g in self.get_groups(): g.treatment = next(treatment) class Group(BaseGroup): treatment = models.StringField() total_contribution = models.CurrencyField() total_earnings = models.CurrencyField() individual_share = models.CurrencyField() def set_payoffs(self): if self.treatment == 'Homo40': self.total_contribution = sum([p.contribution1 for p in self.get_players()]) self.total_earnings = self.total_contribution * Constants.multiplier self.individual_share = self.total_earnings / Constants.players_per_group for p in self.get_players(): p.payoff = (Constants.endowment_1 - p.contribution1) + self.individual_share else: self.total_contribution = sum([p.contribution2 for p in self.get_players()]) self.total_earnings = self.total_contribution * Constants.multiplier self.individual_share = self.total_earnings / Constants.players_per_group for p in self.get_players(): p.payoff = (Constants.endowment_2 - p.contribution2) + self.individual_share contribution1_average = models.CurrencyField() contribution2_average = models.CurrencyField() contribution1_average_history = models.CurrencyField() contribution2_average_history = models.CurrencyField() # 参加者がいなくなったとき、その参加者が居続けているように見せたい。ここではその参加者が過去の全体平均の金額を出し続けるよう設定する。 def contributions_average(self): players = self.get_players() all_rounds = self.round_number if self.treatment == 'Homo40': self.contribution1_average = sum([p.contribution1 for p in players]) / len(players) self.contribution1_average_history = sum([r.contribution1_average for r in self.in_all_rounds()]) / all_rounds else: self.contribution2_average = sum([p.contribution2 for p in players]) / len(players) self.contribution2_average_history = sum([r.contribution2_average for r in self.in_all_rounds()]) / all_rounds class Player(BasePlayer): contribution1 = models.CurrencyField( min=0, max=Constants.endowment_1, doc="The amount contributed by P1", ) contribution2 = models.CurrencyField( min=0, max=Constants.endowment_2, doc="The amount contributed by P2", ) opponent_payoff = models.CurrencyField() def other_player(self): return self.get_others_in_group()[0] totalpayoff = models.CurrencyField() skip = models.BooleanField( choices=[ [False, 'Continued'], [True, 'Skipped'], ] ) quiz1 = models.StringField( choices=['0コイン', '200コイン', '500コイン', '800コイン', '1000コイン'], label='下から正解を選んでください.', widget=widgets.RadioSelect)