from otree.api import * import random import numpy as np c = Currency doc = """ Your app description """ # 0: interest rate bank 2 # 1: control_prob_bank_2 # 2: fine2 # 3: RD_Payoff2 # 0: RND_Payoff2 p = np.array([[40, 61, 40, 40, 52, 44], [75, 75, 50, 45, 60, 50], [24, 52, 36, 40, 50, 44], [16, 9, 4, 0, 2, 0]]) # , dtype="float" rng = np.random.default_rng() rng.shuffle(p, axis=1) # shuffle only the columns, default is 0 class Constants(BaseConstants): name_in_url = 'Baseline' players_per_group = None num_rounds = 6 endowment = 100 interest_rate_bank_1 = 40 interest_rate_bank_2 = p[0, :] control_prob_bank_1 = 75 control_prob_bank_2 = p[1, :] tax_rate = 45 tax = interest_rate_bank_1 * tax_rate/100 RF_Payoff1 = 22 RF_Payoff2 = 22 hiding_cost = p[0, :] - RF_Payoff2 fine1 = 24 fine2 = p[2, :] RF_Payoff1 = 22 # risk-free payoff (paying tax) RF_Payoff2 = 22 # risk-free payoff (paying hiding cost) RD_Payoff1 = 16 # payoff of Risky choice but Detected RD_Payoff2 = p[3, :] RND_Payoff1 = 40 # payoff of Risky choice and Not Detected RND_Payoff2 = p[0, :] ums_rate = '$0.02' class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): tax_compliance = models.BooleanField(label="") control = models.BooleanField(initial=False) investmentChoice = models.BooleanField(label="") income = models.FloatField(initial=0) tax_to_pay = models.IntegerField() payoff1 = models.FloatField() payoff_selected = models.FloatField() def investmentChoice_choices(player): choices = [ [True, "I choose A"], [False, "I choose B"] ] random.shuffle(choices) return choices def tax_compliance_choices(player): choices = [ [True, "Yes, I do"], [False, "No, I don't"] ] random.shuffle(choices) return choices # ---------------------------------------------------------- # FUNCTION # ---------------------------------------------------------- def creating_session(subsession): session = subsession.session if subsession.round_number == 1: for p in subsession.get_players(): p.participant.vars['exited'] = False # ---------------------------------------------------------- # PAGES # ---------------------------------------------------------- class introduction(Page): @staticmethod def is_displayed(player: Player): return player.round_number == 1 class investment(Page): form_model = "player" form_fields = ["investmentChoice"] @staticmethod def vars_for_template(player: Player): investFile = 'Baseline/firstRandPage.html' if ( random.random() > 0.5) else 'Baseline/secondRandPage.html' return dict( interest_rate_bank_2=Constants.interest_rate_bank_2[player.round_number - 1], control_prob_bank_2=Constants.control_prob_bank_2[player.round_number - 1], fine2=Constants.fine2[player.round_number - 1], hiding_cost=Constants.hiding_cost[player.round_number - 1], RD_Payoff2=Constants.RD_Payoff2[player.round_number - 1], RND_Payoff2=Constants.RND_Payoff2[player.round_number - 1], investFile=investFile ) class taxChoice(Page): form_model = "player" form_fields = ["tax_compliance"] @staticmethod def vars_for_template(player: Player): if player.investmentChoice: player.income = int(Constants.endowment * Constants.interest_rate_bank_1 / 100) player.tax_to_pay = int(Constants.tax / 100) else: player.income = int(Constants.endowment * Constants.interest_rate_bank_2[ player.round_number - 1] / 100) # can be deleted this line the income of choice 2 is calculated in result player.tax_to_pay = int(Constants.hiding_cost[player.round_number - 1]) return dict( fine2=Constants.fine2[player.round_number - 1], control_prob_bank_2=Constants.control_prob_bank_2[player.round_number - 1], ) def before_next_page(player: Player, timeout_happened): r = random.random() check_prob = Constants.control_prob_bank_1 / 100 if player.investmentChoice else Constants.control_prob_bank_2[ player.round_number - 1] / 100 if player.tax_compliance: player.payoff1 = player.income - player.tax_to_pay else: if r <= check_prob: player.control = True player.payoff1 = player.income - Constants.fine1 if player.investmentChoice else player.income - \ Constants.fine2[ player.round_number - 1] else: player.payoff1 = player.income player.payoff1 = round(player.payoff1, 0) class finalResult(Page): @staticmethod def is_displayed(player: Player): return player.round_number == Constants.num_rounds @staticmethod def vars_for_template(player: Player): rnd_round = random.randint(1, Constants.num_rounds) finalpayoff1 = int(player.in_round(rnd_round).payoff1) player.payoff_selected = finalpayoff1 # finalpayoff1= player.in_round(2).payoff1 return {"finalpayoff1": finalpayoff1, "selectedRound": rnd_round} class end(Page): def is_displayed(player: Player): return player.round_number == Constants.num_rounds @ staticmethod def before_next_page(player: Player): participant = player.participant participant.finished = True page_sequence = [introduction, investment, taxChoice, finalResult, end]