from otree.api import * doc = """ Public goods with punishment, roughly based on Fehr & Gaechter 2000. """ class C(BaseConstants): NAME_IN_URL = 'public_goods' PLAYERS_PER_GROUP = 3 NUM_ROUNDS = 10 ENDOWMENT = cu(100) MULTIPLIER = 0.4 class Subsession(BaseSubsession): pass class Group(BaseGroup): tot_contribution = models.CurrencyField() ind_share = models.CurrencyField() total_contribution = models.CurrencyField() individual_share = models.CurrencyField() class Player(BasePlayer): contribution = models.CurrencyField( min=0, max=C.ENDOWMENT, label="Wie viel möchten Sie in das Gemeinschaftsprojekt investieren?" ) haeufigkeit = models.IntegerField( label= "Wie häufig treffen Sie sich mit Ihren Mitspieler:innen?", choices = [ [1, 'täglich'], [2, 'mehrmals pro Woche'], [3, 'einmal pro Woche'], [4, 'mehrmals pro Monat'], [5, 'einmal pro Monat'], [6, 'mehrmals pro Jahr'], [7, 'einmal pro Jahr'] ], blank=True ) laenge = models.IntegerField( label='Wie lange sind Sie schon befreundet (in Jahren)?', blank=True ) fortfuehrung = models.BooleanField( label='Denken Sie, Sie werden in fünf Jahren noch befreundet sein?', blank = True ) einverstaendnis = models.BooleanField(choices=[ [True, "Ja"], [False, "Nein (nicht teilnehmen)"] ], label= 'Hiermit bestätige ich, dass ich mindestens 18 Jahre alt bin sowie die Einverständniserklärung gelesen und verstanden habe.') def set_payoffs(group: Group): players = group.get_players() contributions = [p.contribution for p in players] group.tot_contribution = sum(contributions) group.ind_share = group.tot_contribution * C.MULTIPLIER for p in players: p.payoff = C.ENDOWMENT - p.contribution + group.ind_share # PAGES class Name(Page): timeout_seconds = 180 @staticmethod def is_displayed(player): return player.round_number == 1 class Aufklaerung(Page): form_model = 'player' form_fields = ['einverstaendnis'] @staticmethod def is_displayed(player): return player.round_number == 1 class Contribute(Page): form_model = 'player' form_fields = ['contribution'] timeout_seconds = 180 class Instruktionen(Page): timeout_seconds = 300 @staticmethod def is_displayed(player): return player.round_number == 1 class WaitPage1(WaitPage): after_all_players_arrive = set_payoffs pass class WaitPage2(WaitPage): pass class WaitPage3(WaitPage): pass class Punish(Page): form_model = 'player' timeout_seconds = 120 @staticmethod def vars_for_template(player: Player): return dict( other_players=player.get_others_in_group(), ) class Freunde(Page): form_model = 'player' form_fields = ['laenge', 'haeufigkeit','fortfuehrung'] @staticmethod def is_displayed(player): return player.round_number == 10 class Code(Page): form_model = 'player' @staticmethod def vars_for_template(player): player_1 = player.in_round(1) player_2 = player.in_round(2) player_3 = player.in_round(3) player_4 = player.in_round(4) player_5 = player.in_round(5) player_6 = player.in_round(6) player_7 = player.in_round(7) player_8 = player.in_round(8) player_9 = player.in_round(9) player_10 = player.in_round(10) ges_payoff = player_1.payoff + player_2.payoff + player_3.payoff + player_4.payoff + player_5.payoff + player_6.payoff + player_7.payoff + player_8.payoff+ player_9.payoff + player_10.payoff display_payoff = int(ges_payoff) * 43 return dict( ges_payoff = ges_payoff, code = display_payoff ) @staticmethod def is_displayed(player): return player.round_number == 10 class Erinnerung(Page): pass @staticmethod def is_displayed(player): return player.round_number == 1 page_sequence = [ Aufklaerung, Erinnerung, WaitPage3, Name, WaitPage2, Instruktionen, Contribute, WaitPage1, Punish, Code, Freunde ]