from otree.api import * doc = """ Public good game """ class C(BaseConstants): NAME_IN_URL = 'public_goods' PLAYERS_PER_GROUP = 4 NUM_ROUNDS = 5 ENDOWMENT = 20 MPCR = 0.5 class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): private_account = models.IntegerField() public_account = models.IntegerField( label="Enter the number of tokens you place in the public account", min=0, max=C.ENDOWMENT ) # METHODS def creating_session(subsession: Subsession): if subsession.round_number == 1: subsession.group_randomly() else: subsession.group_like_round(1) def compute_total_public_account(group: Group): group.total_public_account = sum( [p.public_account for p in group.get_players()] ) for p in group.get_players(): p.payoff = p.private_account + group.total_public_account * C.MPCR # PAGES class Decision(Page): form_model = "player" form_fields = ["public_account"] def before_next_page(player: Player, timeout_happened): player.private_account = C.ENDOWMENT - player.public_account class DecisionWaitForGroup(WaitPage): wait_for_all_groups = False def after_all_players_arrive(group: Group): compute_total_public_account(group) class Results(Page): def vars_for_template(player: Player): return dict( nb_others_in_group=C.PLAYERS_PER_GROUP - 1 ) class Final(Page): def is_displayed(player: Player): return player.round_number == C.NUM_ROUNDS page_sequence = [Decision, DecisionWaitForGroup, Results, Final]