from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range ) import random from django import forms from django.forms.widgets import NumberInput from django.db import models as djmodels class Constants(BaseConstants): name_in_url = 'pggfg' players_per_group = 4 num_others_per_group = players_per_group - 1 num_rounds = 10 instructions_template = 'pggfg/Instructions.html' endowment = 20 efficiency_factor = 1.4 punishment_endowment = 20 punishment_factor = 0.1#3 class Subsession(BaseSubsession): def creating_session(self): for p in self.get_players(): for o in p.get_others_in_group(): Punishment.objects.create(sender=p, receiver=o, ) class Group(BaseGroup): total_contribution = models.IntegerField() average_contribution = models.FloatField() individual_share = models.CurrencyField() 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 = int(sum([+ Constants.endowment, - p.contribution, + self.individual_share, ])) def set_punishments(self): for p in self.get_players(): p.set_punishment() class Player(BasePlayer): contribution = models.PositiveIntegerField( min=0, max=Constants.endowment, doc="""The amount contributed by the player""", ) gender = models.StringField(choices=["Male", "Female", "Other"]) breakfast_this_morning = models.BooleanField() breakfast_usually = models.BooleanField() how_hungry = models.CurrencyField(min=1, max=10) Q1 = models.StringField(choices=["16", "20", "24", "28"]) Q2 = models.StringField(choices=["5", "7", "11", "18"]) Q3 = models.StringField(choices=["18", "20", "32", "41"]) Q4 = models.StringField(choices=["14 and 18", "14 and 19", "15 and 18", "14 and 21"]) Q5 = models.StringField(choices=["10 and 80", "10 and 45", "15 and 20", "15 and 35"]) punishment_sent = models.PositiveIntegerField() punishment_received = models.FloatField() pd_payoff = models.IntegerField(doc='to store payoff from contribution stage') punishment_endowment = models.IntegerField(initial=0, doc='punishment endowment') def set_payoff(self): self.payoff = ( + self.pd_payoff - self.punishment_sent - self.punishment_received ) if self.payoff < 0: self.payoff = 0 class Punishment(): def before_next_page(self): self.player.set_payoff() 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 = int(self.pd_payoff) def set_punishment(self): self.punishment_sent = sum([i.amount for i in self.punishments_sent.all()]) self.punishment_received = (self.pd_payoff * Constants.punishment_factor) * sum([i.amount for i in self.punishments_received.all()]) class Punishment(djmodels.Model): sender = djmodels.ForeignKey(to=Player, related_name='punishments_sent') receiver = djmodels.ForeignKey(to=Player, related_name='punishments_received') amount = models.IntegerField(null=True, )