from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range, ) doc = """ Public goods game to avoid probablistic disaster """ class Constants(BaseConstants): name_in_url = 'practice_rounds' players_per_group = None num_rounds = 2 instruction_summary = '../_templates/Instruction_Summary.html' endowment = 120 disaster_damage = 80 cost_A = 1 num_trash = 30 max_trash = 120 alpha = 2 beta = 1 others_cont = [30,60] others_trash = [60,30] class Subsession(BaseSubsession): info = models.BooleanField() F_Form = models.BooleanField() initial_trash = models.IntegerField() def creating_session(self): import random for p in self.get_players(): p.disaster_threshold = random.uniform(0,1) trash_list = [40,70] self.initial_trash = trash_list[self.round_number - 1] def get_game(self): self.info = self.session.config['info'] self.F_Form = self.session.config['F_Form'] class Group(BaseGroup): pass class Player(BasePlayer): contribution = models.IntegerField(label='', min=0) trash_B = models.IntegerField() total_contribution = models.IntegerField() total_trash_B = models.IntegerField() disaster_threshold = models.FloatField() disaster_probability = models.FloatField() disaster = models.BooleanField() rebate = models.FloatField() def contribution_max(self): return Constants.max_trash def calc_B(self): self.trash_B = Constants.num_trash - self.contribution self.total_contribution = self.contribution + Constants.others_cont[self.round_number - 1] self.total_trash_B = self.trash_B + self.subsession.initial_trash + Constants.others_trash[self.round_number - 1] def calc_disaster(self): # import random # from scipy import stats # self.disaster_probability2 = stats.beta.cdf(self.total_trash_B/Constants.max_trash,Constants.alpha,Constants.beta,loc=0,scale=1) if self.total_trash_B <= 0: self.disaster_probability = 0 self.rebate = - self.total_trash_B / 4 else: self.disaster_probability = (self.total_trash_B / Constants.max_trash) ** 2 self.rebate = 0 if self.disaster_probability >= self.disaster_threshold: self.disaster = 1 else: self.disaster = 0 import math self.payoff = (Constants.endowment - self.contribution) - self.disaster * Constants.disaster_damage + math.ceil( self.rebate)