from random import shuffle from shared_out import * from otree.api import * """ Sim for Voluntary Contributions with Punishment game - code pulled from first VC game """ class Constants(BaseConstants): name_in_url = 'punishment' players_per_group = None num_rounds = 10 instructions_template = 'punishment/instructions.html' class Subsession(BaseSubsession): pass class Group(BaseGroup): group_project = models.IntegerField(initial=0) class Player(BasePlayer): contribution = models.IntegerField(min=0, max=20) punished = models.IntegerField(initial=0) first_payoff = models.IntegerField(initial=0) final_payoff = models.IntegerField(initial=0) actual = models.IntegerField(initial=0) reduced = models.IntegerField(initial=0) deduct_P1 = models.IntegerField(min=0, max=5, label="Deduct from P1:") deduct_P2 = models.IntegerField(min=0, max=5, label="Deduct from P2:") deduct_P3 = models.IntegerField(min=0, max=5, label="Deduct from P3:") deduct_P4 = models.IntegerField(min=0, max=5, label="Deduct from P4:") # FUNCTIONS def creating_session(subsession: Subsession): set_players_per_group(subsession) def set_labels(group: Group): labels = [1, 2, 3, 4] shuffle(labels) x = 0 for p in group.get_players(): p.id_in_group = labels[x] x = x + 1 def set_pot(group: Group): for player in group.get_players(): group.group_project += player.Contribution for player in group.get_players(): player.first_payoff = int(group.group_project * 0.5) + ( 20 - player.Contribution ) def set_payoff(group: Group): for p in group.get_players(): my_deduct_field = f'deduct_P{p.id_in_group}' setattr(p, my_deduct_field, 0) p.reduced = p.deduct_P1 + p.deduct_P2 + p.deduct_P3 + p.deduct_P4 for other_p in p.get_others_in_group(): p.punished = p.punished + getattr(other_p, my_deduct_field) p.final_payoff = p.first_payoff - (p.punished * 3) - p.reduced p.actual = int(p.punished * 3) def contribution_max(player: Player): return player.session.config['endowment'] # PAGES class Introduction(Page): @staticmethod def is_displayed(player: Player): return player.round_number == 1 class roundWaitPage(WaitPage): after_all_players_arrive = set_labels class Main(Page): form_model = 'player' form_fields = ['contribution'] class ContributionsWaitPage(WaitPage): after_all_players_arrive = set_pot class Deductions(Page): form_model = 'player' @staticmethod def get_form_fields(player: Player): return [f'deduct_P{p.id_in_group}' for p in player.get_others_in_group()] @staticmethod def vars_for_template(player: Player): group = player.group session = player.session contributions = [(p.Contribution, p.id_in_group) for p in group.get_players()] return { 'contributions': contributions, 'range': range(1, session.config['players_per_group'] + 1), } class ResultsWaitPage(WaitPage): after_all_players_arrive = set_payoff class Results(Page): pass page_sequence = [ Introduction, roundWaitPage, Main, ContributionsWaitPage, Deductions, ResultsWaitPage, Results, ]