from otree.api import Currency as c, currency_range from ._builtin import Page, WaitPage from .models import Constants import numpy as np import random from scipy import stats class Instructions(Page): def is_displayed(self): return self.round_number == 1 class ElicitationBeliefs(Page): form_model = 'player' form_fields = ['belief_effort', 'belief_sabotage', 'effort_calc_try', 'sabotage_calc_try', 'effort_opponent_calc_try', 'sabotage_opponent_calc_try', 'clicksEffort_calc_try', 'clicksSabotage_calc_try', 'clicksOpponentEffort_calc_try', 'clicksOpponentSabotage_calc_try', 'effort_p2_calc_try', 'sabotage_p2_calc_try', 'effort_p3_calc_try', 'sabotage_p3_calc_try', 'effort_p4_calc_try', 'sabotage_p4_calc_try', 'effort_p5_calc_try', 'sabotage_p5_calc_try', 'effort_p1_calc_try', 'sabotage_p1_calc_try'] def get_timeout_seconds(self): if self.group.round_number == 1: timeout_seconds = 120 # 2 minutes return timeout_seconds elif self.round_number == 7: timeout_seconds = 60 # 1 minute return timeout_seconds elif self.round_number == 13: timeout_seconds = 60 # 1 minute return timeout_seconds ### Only shown every 6 rounds def is_displayed(self): round = self.round_number if round == 1 or round == 7 or round == 13: a = True else: a = False return a def vars_for_template(self): p = self.player if p.round_number == 1: effort = 0 sabotage = 0 effort_calc_try = p.participant.vars['effort_calc_try'] sabotage_calc_try = p.participant.vars['sabotage_calc_try'] effort_opponent_calc_try = p.participant.vars['effort_opponent_calc_try'] sabotage_opponent_calc_try = p.participant.vars['sabotage_opponent_calc_try'] effort_p1_calc_try = p.participant.vars['effort_p1_calc_try'] sabotage_p1_calc_try = p.participant.vars['sabotage_p1_calc_try'] effort_p2_calc_try = p.participant.vars['effort_p2_calc_try'] sabotage_p2_calc_try = p.participant.vars['sabotage_p2_calc_try'] effort_p3_calc_try = p.participant.vars['effort_p3_calc_try'] sabotage_p3_calc_try = p.participant.vars['sabotage_p3_calc_try'] effort_p4_calc_try = p.participant.vars['effort_p4_calc_try'] sabotage_p4_calc_try = p.participant.vars['sabotage_p4_calc_try'] effort_p5_calc_try = p.participant.vars['effort_p5_calc_try'] sabotage_p5_calc_try = p.participant.vars['sabotage_p5_calc_try'] else: effort = p.in_round(p.round_number - 6).belief_effort sabotage = p.in_round(p.round_number - 6).belief_sabotage effort_calc_try = p.in_round(p.round_number - 1).effort_calc_try sabotage_calc_try = p.in_round(p.round_number - 1).sabotage_calc_try effort_opponent_calc_try = p.in_round(p.round_number - 1).effort_opponent_calc_try sabotage_opponent_calc_try = p.in_round(p.round_number - 1).sabotage_opponent_calc_try effort_p1_calc_try = p.in_round(p.round_number - 1).effort_p1_calc_try sabotage_p1_calc_try = p.in_round(p.round_number - 1).sabotage_p1_calc_try effort_p2_calc_try = p.in_round(p.round_number - 1).effort_p2_calc_try sabotage_p2_calc_try = p.in_round(p.round_number - 1).sabotage_p2_calc_try effort_p3_calc_try = p.in_round(p.round_number - 1).effort_p3_calc_try sabotage_p3_calc_try = p.in_round(p.round_number - 1).sabotage_p3_calc_try effort_p4_calc_try = p.in_round(p.round_number - 1).effort_p4_calc_try sabotage_p4_calc_try = p.in_round(p.round_number - 1).sabotage_p4_calc_try effort_p5_calc_try = p.in_round(p.round_number - 1).effort_p5_calc_try sabotage_p5_calc_try = p.in_round(p.round_number - 1).sabotage_p5_calc_try performance1 = effort_calc_try performance2 = effort_calc_try / (1 + sabotage_opponent_calc_try) performance3 = effort_calc_try / (1 + sabotage_opponent_calc_try * 2) performance4 = effort_calc_try / (1 + sabotage_opponent_calc_try * 3) performance5 = effort_calc_try / (1 + sabotage_opponent_calc_try * 4) othersPerformance2 = effort_opponent_calc_try / (1 + sabotage_calc_try) othersPerformance3 = effort_opponent_calc_try / (1 + sabotage_calc_try + sabotage_opponent_calc_try) othersPerformance4 = effort_opponent_calc_try / (1 + sabotage_calc_try + sabotage_opponent_calc_try * 2) othersPerformance5 = effort_opponent_calc_try / (1 + sabotage_calc_try + sabotage_opponent_calc_try * 3) payoffWin = 400 - effort_calc_try - sabotage_calc_try payoffLose = 200 - effort_calc_try - sabotage_calc_try donations1 = performance1 + Constants.donation_base donations2 = performance2 + othersPerformance2 + Constants.donation_base donations3 = performance3 + othersPerformance3 + Constants.donation_base donations4 = performance4 + othersPerformance4 + Constants.donation_base donations5 = performance5 + othersPerformance5 + Constants.donation_base group1 = stats.binom.pmf(0, Constants.players_per_group - 1, Constants.entering_probability) group2 = stats.binom.pmf(1, Constants.players_per_group - 1, Constants.entering_probability) group3 = stats.binom.pmf(2, Constants.players_per_group - 1, Constants.entering_probability) group4 = stats.binom.pmf(3, Constants.players_per_group - 1, Constants.entering_probability) group5 = stats.binom.pmf(4, Constants.players_per_group - 1, Constants.entering_probability) enter = round(Constants.entering_probability * 100, 0) return dict(e1=effort, s1=sabotage, eCalc=effort_calc_try, sCalc=sabotage_calc_try, eOppCalc=effort_opponent_calc_try, sOppCalc=sabotage_opponent_calc_try, eCalcP1=effort_p1_calc_try, sCalcP1=sabotage_p1_calc_try, eCalcP2=effort_p2_calc_try, sCalcP2=sabotage_p2_calc_try, eCalcP3=effort_p3_calc_try, sCalcP3=sabotage_p3_calc_try, eCalcP4=effort_p4_calc_try, sCalcP4=sabotage_p4_calc_try, eCalcP5=effort_p5_calc_try, sCalcP5=sabotage_p5_calc_try, performance1=round(performance1, 1), performance2=round(performance2, 1), performance3=round(performance3, 1), performance4=round(performance4, 1), performance5=round(performance5, 1), othersPerformance2=round(othersPerformance2, 1), othersPerformance3=round(othersPerformance3, 1), othersPerformance4=round(othersPerformance4, 1), othersPerformance5=round(othersPerformance5, 1), donations1=round(donations1, 1), donations2=round(donations2, 1), donations3=round(donations3, 1), donations4=round(donations4, 1), donations5=round(donations5, 1), payoffWin=payoffWin, payoffLose=payoffLose, g1=round(group1 * 100, 1), g2=round(group2 * 100, 1), g3=round(group3 * 100, 1), g4=round(group4 * 100, 1), g5=round(group5 * 100, 1), enter=int(enter)) def js_vars(self): p = self.player if p.round_number == 1: effort_calc_try = p.participant.vars['effort_calc_try'] sabotage_calc_try = p.participant.vars['sabotage_calc_try'] effort_opponent_calc_try = p.participant.vars['effort_opponent_calc_try'] sabotage_opponent_calc_try = p.participant.vars['sabotage_opponent_calc_try'] else: effort_calc_try = p.in_round(p.round_number - 1).effort_calc_try sabotage_calc_try = p.in_round(p.round_number - 1).sabotage_calc_try effort_opponent_calc_try = p.in_round(p.round_number - 1).effort_opponent_calc_try sabotage_opponent_calc_try = p.in_round(p.round_number - 1).sabotage_opponent_calc_try performance2 = effort_calc_try / (1 + sabotage_opponent_calc_try) performance3 = effort_calc_try / (1 + sabotage_opponent_calc_try*2) performance4 = effort_calc_try / (1 + sabotage_opponent_calc_try*3) performance5 = effort_calc_try / (1 + sabotage_opponent_calc_try*4) othersPerformance2 = effort_opponent_calc_try / (1 + sabotage_calc_try) othersPerformance3 = effort_opponent_calc_try / (1 + sabotage_calc_try + sabotage_opponent_calc_try) othersPerformance4 = effort_opponent_calc_try / (1 + sabotage_calc_try + sabotage_opponent_calc_try*2) othersPerformance5 = effort_opponent_calc_try / (1 + sabotage_calc_try + sabotage_opponent_calc_try*3) if (performance2+othersPerformance2) > 0: winning2 = performance2 / (performance2+othersPerformance2) else: winning2 = 0.5 if (performance3 + othersPerformance3) > 0: winning3 = performance3 / (performance3 + othersPerformance3*2) else: winning3 = 1/3 if (performance4 + othersPerformance4) > 0: winning4 = performance4 / (performance4 + othersPerformance4*3) else: winning4 = 0.5 if (performance5 + othersPerformance5) > 0: winning5 = performance5 / (performance5 + othersPerformance5*4) else: winning5 = 0.5 # Calculate probabilities for group sizes group1 = stats.binom.pmf(0, Constants.players_per_group - 1, Constants.entering_probability) group2 = stats.binom.pmf(1, Constants.players_per_group - 1, Constants.entering_probability) group3 = stats.binom.pmf(2, Constants.players_per_group - 1, Constants.entering_probability) group4 = stats.binom.pmf(3, Constants.players_per_group - 1, Constants.entering_probability) group5 = stats.binom.pmf(4, Constants.players_per_group - 1, Constants.entering_probability) return dict(g1=round(group1 * 100, 1), g2=round(group2 * 100, 1), g3=round(group3 * 100, 1), g4=round(group4 * 100, 1), g5=round(group5 * 100, 1), winning2=winning2, winning3=winning3, winning4=winning4, winning5=winning5) class ElicitationChoices(Page): form_model = 'player' form_fields = ['effort', 'sabotage', 'effort_calc_try', 'sabotage_calc_try', 'effort_opponent_calc_try', 'sabotage_opponent_calc_try', 'clicksEffort_calc_try', 'clicksSabotage_calc_try', 'clicksOpponentEffort_calc_try', 'clicksOpponentSabotage_calc_try', 'clicksEffort_calc_advanced_try', 'clicksSabotage_calc_advanced_try', 'clicksOpponentEffort_calc_advanced_try', 'clicksOpponentSabotage_calc_advanced_try', 'effort_p2_calc_try', 'sabotage_p2_calc_try', 'effort_p3_calc_try', 'sabotage_p3_calc_try', 'effort_p1_calc_try', 'sabotage_p1_calc_try'] def get_timeout_seconds(self): if self.group.round_number == 1: timeout_seconds = 300 # 5minutes elif self.group.round_number == 2: timeout_seconds = 240 # 4minutes elif self.group.round_number < 5: timeout_seconds = 180 # 3minutes else: timeout_seconds = 90 # 1.5 minutes return timeout_seconds def vars_for_template(self): p = self.player if p.round_number == 1: effort = 0 sabotage = 0 effort_calc_try = p.participant.vars['effort_calc_try'] sabotage_calc_try = p.participant.vars['sabotage_calc_try'] effort_opponent_calc_try = p.participant.vars['effort_opponent_calc_try'] sabotage_opponent_calc_try = p.participant.vars['sabotage_opponent_calc_try'] effort_p1_calc_try = p.participant.vars['effort_p1_calc_try'] sabotage_p1_calc_try = p.participant.vars['sabotage_p1_calc_try'] effort_p2_calc_try = p.participant.vars['effort_p2_calc_try'] sabotage_p2_calc_try = p.participant.vars['sabotage_p2_calc_try'] effort_p3_calc_try = p.participant.vars['effort_p3_calc_try'] sabotage_p3_calc_try = p.participant.vars['sabotage_p3_calc_try'] else: effort = p.in_round(p.round_number - 1).effort sabotage = p.in_round(p.round_number - 1).sabotage effort_calc_try = p.in_round(p.round_number - 1).effort_calc_try sabotage_calc_try = p.in_round(p.round_number - 1).sabotage_calc_try effort_opponent_calc_try = p.in_round(p.round_number - 1).effort_opponent_calc_try sabotage_opponent_calc_try = p.in_round(p.round_number - 1).sabotage_opponent_calc_try effort_p1_calc_try = p.in_round(p.round_number - 1).effort_p1_calc_try sabotage_p1_calc_try = p.in_round(p.round_number - 1).sabotage_p1_calc_try effort_p2_calc_try = p.in_round(p.round_number - 1).effort_p2_calc_try sabotage_p2_calc_try = p.in_round(p.round_number - 1).sabotage_p2_calc_try effort_p3_calc_try = p.in_round(p.round_number - 1).effort_p3_calc_try sabotage_p3_calc_try = p.in_round(p.round_number - 1).sabotage_p3_calc_try performance1 = effort_calc_try performance2 = effort_calc_try / (1 + sabotage_opponent_calc_try) performance3 = effort_calc_try / (1 + sabotage_opponent_calc_try*2) othersPerformance2 = effort_opponent_calc_try / (1 + sabotage_calc_try) othersPerformance3 = effort_opponent_calc_try / (1 + sabotage_calc_try + sabotage_opponent_calc_try) payoffWin = 400 - effort_calc_try - sabotage_calc_try payoffLose = 200 - effort_calc_try - sabotage_calc_try donations1 = performance1+Constants.donation_base donations2 = performance2+othersPerformance2+Constants.donation_base donations3 = performance3+othersPerformance3+Constants.donation_base group1 = stats.binom.pmf(0, Constants.players_per_group - 1, Constants.entering_probability) group2 = stats.binom.pmf(1, Constants.players_per_group - 1, Constants.entering_probability) group3 = stats.binom.pmf(2, Constants.players_per_group - 1, Constants.entering_probability) enter = round(Constants.entering_probability * 100, 0) return dict(e1=effort, s1=sabotage, eCalc=effort_calc_try, sCalc=sabotage_calc_try, eOppCalc=effort_opponent_calc_try, sOppCalc=sabotage_opponent_calc_try, eCalcP1=effort_p1_calc_try, sCalcP1=sabotage_p1_calc_try, eCalcP2=effort_p2_calc_try, sCalcP2=sabotage_p2_calc_try, eCalcP3=effort_p3_calc_try, sCalcP3=sabotage_p3_calc_try, performance1=round(performance1, 1), performance2=round(performance2, 1), performance3=round(performance3, 1), othersPerformance2=round(othersPerformance2, 1), othersPerformance3=round(othersPerformance3, 1), donations1=round(donations1, 1), donations2=round(donations2, 1), donations3=round(donations3, 1), payoffWin=payoffWin, payoffLose=payoffLose, g1=round(group1 * 100, 1), g2=round(group2 * 100, 1), g3=round(group3 * 100, 1), enter=int(enter)) def js_vars(self): # Calculate probabilities for group sizes group1 = stats.binom.pmf(0, Constants.players_per_group - 1, Constants.entering_probability) group2 = stats.binom.pmf(1, Constants.players_per_group - 1, Constants.entering_probability) group3 = stats.binom.pmf(2, Constants.players_per_group - 1, Constants.entering_probability) p = self.player if p.round_number == 1: effort_calc_try = p.participant.vars['effort_calc_try'] sabotage_calc_try = p.participant.vars['sabotage_calc_try'] effort_opponent_calc_try = p.participant.vars['effort_opponent_calc_try'] sabotage_opponent_calc_try = p.participant.vars['sabotage_opponent_calc_try'] else: effort_calc_try = p.in_round(p.round_number - 1).effort_calc_try sabotage_calc_try = p.in_round(p.round_number - 1).sabotage_calc_try effort_opponent_calc_try = p.in_round(p.round_number - 1).effort_opponent_calc_try sabotage_opponent_calc_try = p.in_round(p.round_number - 1).sabotage_opponent_calc_try performance2 = effort_calc_try / (1 + sabotage_opponent_calc_try) performance3 = effort_calc_try / (1 + sabotage_opponent_calc_try * 2) othersPerformance2 = effort_opponent_calc_try / (1 + sabotage_calc_try) othersPerformance3 = effort_opponent_calc_try / (1 + sabotage_calc_try + sabotage_opponent_calc_try) if (performance2 + othersPerformance2) > 0: winning2 = performance2 / (performance2 + othersPerformance2) else: winning2 = 0.5 if (performance3 + othersPerformance3) > 0: winning3 = performance3 / (performance3 + othersPerformance3 * 2) else: winning3 = 1 / 3 if self.group.round_number < 3: timeout = 300000 ### 5 minutes elif self.group.round_number < 6: timeout = 180000 #### 3minutes else: timeout = 120000 #### 2minutes if self.group.round_number < 3: timeout = 300000 ### 5 minutes elif self.group.round_number < 6: timeout = 180000 #### 3minutes else: timeout = 120000 #### 2minutes return dict(g1=round(group1 * 100, 1), g2=round(group2 * 100, 1), g3=round(group3 * 100, 1), timeout=timeout, eCalc=effort_calc_try, sCalc=sabotage_calc_try, eOppCalc=effort_opponent_calc_try, sOppCalc=sabotage_opponent_calc_try, winning2=winning2, winning3=winning3) class ResultsWaitPage(WaitPage): def after_all_players_arrive(self): self.group.realize_group_size() self.group.set_performances_probabilities_and_winner() self.group.set_payoff_round() self.group.set_individual_display() class Results(Page): def get_timeout_seconds(self): if self.group.round_number < 3: timeout_seconds = 120 # 2 minutes else: timeout_seconds = 90 # 1 minute return timeout_seconds def vars_for_template(self): group1 = stats.binom.pmf(0, Constants.players_per_group - 1, Constants.entering_probability) group2 = stats.binom.pmf(1, Constants.players_per_group - 1, Constants.entering_probability) group3 = stats.binom.pmf(2, Constants.players_per_group - 1, Constants.entering_probability) enter = round(Constants.entering_probability * 100, 0) if self.player.active: winProbYou = round(100*self.player.probability, 2) else: winProbYou = 0 return dict(g1=round(group1 * 100, 1), g2=round(group2 * 100, 1), g3=round(group3 * 100, 1), enter=int(enter), winProbYou=winProbYou) def js_vars(self): group1 = stats.binom.pmf(0, Constants.players_per_group - 1, Constants.entering_probability) group2 = stats.binom.pmf(1, Constants.players_per_group - 1, Constants.entering_probability) group3 = stats.binom.pmf(2, Constants.players_per_group - 1, Constants.entering_probability) enter = round(Constants.entering_probability * 100, 0) if self.player.active: winProbYou = round(100 * self.player.probability, 2) else: winProbYou = 0 return dict( p1=winProbYou, p2=self.player.probability_other1, p3=self.player.probability_other2, g1=round(group1 * 100, 1), g2=round(group2 * 100, 1), g3=round(group3 * 100, 1), enter=int(enter) ) # Calculate the ultimate payoffs for this app. def before_next_page(self): self.player.set_average_choices_others() if self.player.round_number == 15: ### get the payoff from the sabotage game. Therefore get the 3 numbers from 30 rounds from part A. payoffRound1 = self.player.participant.vars['payoffRound1'] payoffRound2 = self.player.participant.vars['payoffRound2'] payoffRound3 = self.player.participant.vars['payoffRound3'] if 15 < payoffRound1 < 31: p = self.player.in_round(payoffRound1-15) self.player.participant.vars['payoff1'] = p.payoff_round self.player.participant.vars['donations1'] = p.group.donations if 15 < payoffRound2 < 31: p = self.player.in_round(payoffRound2-15) self.player.participant.vars['payoff2'] = p.payoff_round self.player.participant.vars['donations2'] = p.group.donations if 15 < payoffRound3 < 31: p = self.player.in_round(payoffRound3-15) self.player.participant.vars['payoff3'] = p.payoff_round self.player.participant.vars['donations3'] = p.group.donations ### Give the values from the calculator to the next app self.participant.vars['effort_calc_try'] = self.player.effort_calc_try self.participant.vars['sabotage_calc_try'] = self.player.sabotage_calc_try self.participant.vars['effort_opponent_calc_try'] = self.player.effort_opponent_calc_try self.participant.vars['sabotage_opponent_calc_try'] = self.player.sabotage_opponent_calc_try self.participant.vars['effort_p1_calc_try'] = self.player.effort_p1_calc_try self.participant.vars['sabotage_p1_calc_try'] = self.player.sabotage_p1_calc_try self.participant.vars['effort_p2_calc_try'] = self.player.effort_p2_calc_try self.participant.vars['sabotage_p2_calc_try'] = self.player.sabotage_p2_calc_try self.participant.vars['effort_p3_calc_try'] = self.player.effort_p3_calc_try self.participant.vars['sabotage_p3_calc_try'] = self.player.sabotage_p3_calc_try class Payoff(Page): def is_displayed(self): return self.round_number == 15 def vars_for_template(self): #payoffRoundBelief = self.player.participant.vars['payoffRoundBelief'] payoff1 = self.player.participant.vars['payoff1'] payoff2 = self.player.participant.vars['payoff2'] payoff3 = self.player.participant.vars['payoff3'] payoffRound1 = self.player.participant.vars['payoffRound1'] payoffRound2 = self.player.participant.vars['payoffRound2'] payoffRound3 = self.player.participant.vars['payoffRound3'] donations1 = self.player.participant.vars['donations1'] donations2 = self.player.participant.vars['donations2'] donations3 = self.player.participant.vars['donations3'] return dict(#payoffRoundBelief=payoffRoundBelief, payoff1=payoff1, payoff2=payoff2, payoff3=payoff3, payoffRound1=payoffRound1, payoffRound2=payoffRound2, payoffRound3=payoffRound3, donations1=donations1, donations2=donations2, donations3=donations3) page_sequence = [ Instructions, #ElicitationBeliefs, ElicitationChoices, ResultsWaitPage, Results # Payoff ]