from otree.api import Currency as c, currency_range from ._builtin import Page, WaitPage from .models import Constants from scipy import stats import numpy as np import random class InstructionsOverall(Page): #timeout_seconds = 80 pass class Instructions0(Page): #timeout_seconds = Constants.timeout2Short pass class Instructions1(Page): #timeout_seconds = Constants.timeout2Short def vars_for_template(self): enter = round(Constants.entering_probability * 100, 0) return dict(n_j=Constants.players_per_group - 1, enter=int(enter)) class Instructions1Tut(Page): #timeout_seconds = Constants.timeout2 form_model = 'player' form_fields = ['effortTut1'] def before_next_page(self): self.player.effortTut1PC = random.randint(0, 100) class Results1Tut(Page): #timeout_seconds = Constants.timeout2 def vars_for_template(self): total = self.player.effortTut1 + self.player.effortTut1PC if total == 0: winningP1 = 1/2 winningPC = 1/2 else: winningP1 = self.player.effortTut1 / total winningPC = self.player.effortTut1PC / total probabilities = [winningP1, winningPC] winner = np.random.choice([1, 2], 1, p=probabilities) pay = Constants.endowment - self.player.effortTut1 donations = total + Constants.donation_base if winner == 1: pay = pay + Constants.prize winner = 1 else: winner = 2 return dict(pay=pay, winChanceP1=round(winningP1 * 100, 2), winChancePC=round(winningPC * 100, 2), winner=winner, total=total, donations=donations) def js_vars(self): total = self.player.effortTut1 + self.player.effortTut1PC if total == 0: winningP1 = 1/2 winningPC = 1/2 else: winningP1 = self.player.effortTut1 / total winningPC = self.player.effortTut1PC / total return dict(winChanceP1=round(winningP1, 2), winChancePC=round(winningPC, 2)) class Instructions2(Page): #timeout_seconds = Constants.timeout2Short def vars_for_template(self): enter = round(Constants.entering_probability * 100, 0) return dict(n_j=Constants.players_per_group - 1, enter=int(enter)) class Instructions2Tut(Page): #timeout_seconds = Constants.timeout2 form_model = 'player' form_fields = ['effortTut2', 'sabotageTut2'] def before_next_page(self): self.player.effortTut2PC = random.randint(0, 100) self.player.sabotageTut2PC = random.randint(0, 100) class Results2Tut(Page): #timeout_seconds = Constants.timeout2 def vars_for_template(self): performanceP1 = self.player.effortTut2 / (1 + self.player.sabotageTut2PC) performanceP2 = self.player.effortTut2PC / (1 + self.player.sabotageTut2) total = performanceP1 + performanceP2 if total == 0: winningP1 = 1/2 winningPC = 1/2 else: winningP1 = performanceP1 / total winningPC = performanceP2 / total probabilities = [winningP1, winningPC] winner = np.random.choice([1, 2], 1, p=probabilities) pay = Constants.endowment - self.player.effortTut2 - self.player.sabotageTut2 donations = total + Constants.donation_base if winner == 1: pay = pay + Constants.prize winner = 1 else: winner = 2 return dict(pay=pay, winChanceP1=round(winningP1 * 100, 2), performanceP1=round(performanceP1, 1), performanceP2=round(performanceP2, 1), winChancePC=round(winningPC * 100, 2), winner=winner, total=total, donations=round(donations, 1)) def js_vars(self): performanceP1 = self.player.effortTut2 / (1 + self.player.sabotageTut2PC) performanceP2 = self.player.effortTut2PC / (1 + self.player.sabotageTut2) total = performanceP1 + performanceP2 if total == 0: winningP1 = 1/2 winningPC = 1/2 else: winningP1 = performanceP1 / total winningPC = performanceP2 / total return dict(winChanceP1=round(winningP1, 2), winChancePC=round(winningPC, 2)) class InstructionsDonations(Page): def vars_for_template(self): performanceP1 = self.player.effortTut2 / (1 + self.player.sabotageTut2PC) performanceP2 = self.player.effortTut2PC / (1 + self.player.sabotageTut2) total = performanceP1+performanceP2 donations = Constants.donation_base + total if total == 0: winningP1 = 1/2 winningPC = 1/2 else: winningP1 = performanceP1 / total winningPC = performanceP2 / total return dict(performanceP1=round(performanceP1, 1), performanceP2=round(performanceP2, 1), donations=round(donations, 2), winChanceP1=round(winningP1 * 100, 2), winChancePC=round(winningPC * 100, 2)) class Instructions3Tut(Page): #timeout_seconds = Constants.timeout2 form_model = 'player' form_fields = ['effortTut3', 'sabotageTut3'] def vars_for_template(self): return dict(n_j=Constants.players_per_group - 1) def before_next_page(self): self.player.effortTut3P2 = random.randint(0, 100) self.player.sabotageTut3P2 = random.randint(0, 100) self.player.effortTut3P3 = random.randint(0, 100) self.player.sabotageTut3P3 = random.randint(0, 100) class Results3Tut(Page): #timeout_seconds = Constants.timeout2 def vars_for_template(self): performanceP1 = self.player.effortTut3 / (1 + self.player.sabotageTut3P2 + self.player.sabotageTut3P3) performanceP2 = self.player.effortTut3P2 / (1 + self.player.sabotageTut3 + self.player.sabotageTut3P3) performanceP3 = self.player.effortTut3P3 / (1 + self.player.sabotageTut3 + self.player.sabotageTut3P2) total = performanceP1 + performanceP2 + performanceP3 donations = Constants.donation_base + total * Constants.donation_fraction if total == 0: winningP1 = 1/3 winningP2 = 1/3 winningP3 = 1/3 else: winningP1 = performanceP1 / total winningP2 = performanceP2 / total winningP3 = performanceP3 / total probabilities = [winningP1, winningP2, winningP3] winner = np.random.choice([1, 2, 3], 1, p=probabilities) pay = Constants.endowment - self.player.effortTut3 - self.player.sabotageTut3 if winner == 1: pay = pay + Constants.prize winner = 1 elif winner == 2: winner = 2 elif winner == 3: winner = 3 return dict(pay=pay, winChanceP1=round(winningP1 * 100, 2), winChanceP2=round(winningP2 * 100, 2), winChanceP3=round(winningP3 * 100, 2), performanceP1=round(performanceP1, 2), performanceP2=round(performanceP2, 2), performanceP3=round(performanceP3, 2), winner=winner, total=total, donations=round(donations, 2)) def js_vars(self): performanceP1 = self.player.effortTut3 / (1 + self.player.sabotageTut3P2 + self.player.sabotageTut3P3) performanceP2 = self.player.effortTut3P2 / (1 + self.player.sabotageTut3 + self.player.sabotageTut3P3) performanceP3 = self.player.effortTut3P3 / (1 + self.player.sabotageTut3 + self.player.sabotageTut3P2) total = performanceP1 + performanceP2 + performanceP3 if total == 0: winningP1 = 1/3 winningP2 = 1/3 winningP3 = 1/3 else: winningP1 = performanceP1 / total winningP2 = performanceP2 / total winningP3 = performanceP3 / total probabilities = [winningP1, winningP2, winningP3] winner = np.random.choice([1, 2, 3], 1, p=probabilities) pay = Constants.endowment - self.player.effortTut3 - self.player.sabotageTut3 if winner == 1: pay = pay + Constants.prize winner = 1 elif winner == 2: winner = 2 elif winner == 3: winner = 3 return dict(pay=pay, winChanceP1=round(winningP1 * 100, 2), winChanceP2=round(winningP2 * 100, 2), winChanceP3=round(winningP3 * 100, 2), performanceP1=round(performanceP1, 2), performanceP2=round(performanceP2, 2), performanceP3=round(performanceP3, 2), winner=winner) class Instructions4Tut(Page): timeout_seconds = Constants.timeout2 form_model = 'player' form_fields = ['effortTut4_1', 'sabotageTut4_1', 'effortTut4_2', 'sabotageTut4_2', 'effortTut4_3', 'sabotageTut4_3'] def vars_for_template(self): return dict(n_j=Constants.players_per_group - 1, enter=int(round(Constants.entering_probability * 100, 0))) def before_next_page(self): self.player.effortTut4P2 = random.randint(0, 100) self.player.sabotageTut4P2 = random.randint(0, 100) self.player.effortTut4P3 = random.randint(0, 100) self.player.sabotageTut4P3 = random.randint(0, 100) class Results4Tut(Page): timeout_seconds = Constants.timeout2 def vars_for_template(self): performanceP1 = self.player.effortTut4_2 / (1 + self.player.sabotageTut4P2) performanceP2 = self.player.effortTut4P2 / (1 + self.player.sabotageTut4_2) total = performanceP1 + performanceP2 donations = Constants.donation_base + total * Constants.donation_fraction if total == 0: winningChanceP1 = 1 / 2 winningChanceP2 = 1 / 2 else: winningChanceP1 = performanceP1 / total winningChanceP2 = performanceP2 / total probabilities = [winningChanceP1, winningChanceP2] win = np.random.choice([1, 2], 1, p=probabilities) # bon = Constants.externality_effort * sum([self.player.effort_calc_try,2*self.player.effort_opponent_calc_try]) - \ # Constants.externatlity_sabotage * sum([self.player.sabotage_calc_try,2*self.player.sabotage_opponent_calc_try]) pay = Constants.endowment - self.player.effortTut4_3 - self.player.sabotageTut4_3 # +bon if win == 1: pay = pay + Constants.prize win = 1 elif win == 2: win = 2 return dict(winChanceP1=round(winningChanceP1 * 100, 2), winChanceP2=round(winningChanceP2 * 100, 2), winner=win, pay=round(pay, 2), enter=int(round(Constants.entering_probability * 100, 0)), performanceP1=round(performanceP1, 2), performanceP2=round(performanceP2, 2), total=total, donations=round(donations, 2) ) def js_vars(self): performanceP1 = self.player.effortTut4_2 / (1 + self.player.sabotageTut4P2) performanceP2 = self.player.effortTut4P2 / (1 + self.player.sabotageTut4_2) total = performanceP1 + performanceP2 if total == 0: winningChanceP1 = 1 / 2 winningChanceP2 = 1 / 2 else: winningChanceP1 = performanceP1 / total winningChanceP2 = performanceP2 / total return dict(winChanceP1=round(winningChanceP1 * 100, 2), winChanceP2=round(winningChanceP2 * 100, 2), winChanceP3=0, winChanceP5=0) class WinningCalculator(Page): form_model = 'player' form_fields = ['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' ] timeout_seconds = 300 def before_next_page(self): 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 OverviewInstructions(Page): timeout_seconds = 20 # Give group size probabilities to the pages and javascript for the pie chart def vars_for_template(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) enter = round(Constants.entering_probability * 100, 0) return dict(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) return dict(g1=round(group1 * 100, 1), g2=round(group2 * 100, 1), g3=round(group3 * 100, 1), externality_effort=Constants.externality_effort, externatlity_sabotage=Constants.externatlity_sabotage) class Quiz(Page): form_model = 'player' form_fields = ['q1', 'q2', 'q3', 'q4', 'q5', 'q6', 'q7', 'q8', 'q9', 'q10'] def error_message(self, values): # print('values is', values) # Here to make one message with all errors, I could built up a string in every if loop: # QX, and then add it all up in the end with return: " is not correct, please try again" if values['q1'] != Constants.players_per_group: return 'Q1 is not correct, please try again' if values['q2'] != "Increase my performance and reduce the other active group members' performances": return 'Q2 is not correct, please try again' if values['q3'] != "Increase my performance": return 'Q3 is not correct, please try again' if values['q4'] != "Decrease all other active group members' performances simultaneously": return 'Q4 is not correct, please try again' if values['q5'] != "Increase my performance (by investing in Option A)": return 'Q5 is not correct, please try again' if values['q6'] != "Decrease the other active group members' performances (by investing in Option B)": return 'Q6 is not correct, please try again' if values['q7'] != "Me, the other active group members of my group, and the charity": return 'Q7 is not correct, please try again' if values['q8'] != "This is determined randomly in every round": return 'Q8 is not correct, please try again' if values['q9'] != "This group member wins the 200-point prize independently of his/her choices": return 'Q9 is not correct, please try again' if values['q10'] != "I can keep the points and they will be added to my payoff of this round": return 'Q10 is not correct, please try again' def vars_for_template(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) enter = round(Constants.entering_probability * 100, 0) return dict(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) return dict(g1=round(group1 * 100, 1), g2=round(group2 * 100, 1), g3=round(group3 * 100, 1), externality_effort=Constants.externality_effort, externatlity_sabotage=Constants.externatlity_sabotage) page_sequence = [InstructionsOverall, Instructions0, Instructions1Tut, Results1Tut, Instructions2Tut, Results2Tut, Instructions3Tut, Results3Tut, Instructions1, Instructions2, Instructions4Tut, Results4Tut, WinningCalculator, OverviewInstructions, Quiz]