from otree.api import Currency as c, currency_range from ._builtin import Page, WaitPage from .models import Constants import csv import random import time import xlrd # for reading XLS-files import math # import xlsxwriter module import xlsxwriter ########### ALL INSTRUCTION PAGES class A_Consent_Form(Page): form_model = 'player' form_fields = ['tab_consent','focus_consent','totaltime_consent'] def is_displayed(self): return self.round_number == 1 # only display in the first round def vars_for_template(self): loc = ("Part1_IE_DOSE/data/A_ConsentForm.xlsx") # To open Workbook wb = xlrd.open_workbook(loc) sheet = wb.sheet_by_index(0) # Get all titles & paragraphs title = sheet.cell_value(1, Constants.language_code) warning = sheet.cell_value(2, Constants.language_code) subtitle1 = sheet.cell_value(3, Constants.language_code) paragraph1 = sheet.cell_value(4, Constants.language_code) subtitle2 = sheet.cell_value(5, Constants.language_code) paragraph2 = sheet.cell_value(6, Constants.language_code) subtitle3 = sheet.cell_value(7, Constants.language_code) paragraph3 = sheet.cell_value(8, Constants.language_code) subtitle4 = sheet.cell_value(9, Constants.language_code) paragraph4 = sheet.cell_value(10, Constants.language_code) subtitle5 = sheet.cell_value(11, Constants.language_code) paragraph5 = sheet.cell_value(12, Constants.language_code) subtitle6 = sheet.cell_value(13, Constants.language_code) paragraph6 = sheet.cell_value(14, Constants.language_code) subtitle7 = sheet.cell_value(15, Constants.language_code) paragraph7 = sheet.cell_value(16, Constants.language_code) consent = sheet.cell_value(17, Constants.language_code) confirm = sheet.cell_value(18, Constants.language_code) return dict( title=title, warning=warning, subtitle1=subtitle1, subtitle2=subtitle2, subtitle3=subtitle3, subtitle4=subtitle4, subtitle5=subtitle5, subtitle6=subtitle6, subtitle7=subtitle7, paragraph1=paragraph1, paragraph2=paragraph2, paragraph3=paragraph3, paragraph4=paragraph4.format(showup_fee = Constants.showup_fee, currency_real = Constants.currency_real, currency = Constants.currency), paragraph5=paragraph5, paragraph6=paragraph6, paragraph7=paragraph7, consent=consent, confirm=confirm ) class B_prolificID(Page): form_model = 'player' form_fields = ['prolificID'] def is_displayed(self): return self.round_number == 1 # only display in the first round def before_next_page(self): self.participant.vars['prolificID'] = self.player.prolificID class C_Instructions_General(Page): form_model = 'player' form_fields = ['tab_instructions_general_part1', 'focus_instructions_general_part1', 'totaltime_instructions_general_part1'] def is_displayed(self): return self.round_number == 1 # only display in the first round def vars_for_template(self): loc = ("Part1_IE_DOSE/data/B_Instructions_General.xlsx") # To open Workbook wb = xlrd.open_workbook(loc) sheet = wb.sheet_by_index(0) # Get all titles & paragraphs title = sheet.cell_value(1, Constants.language_code) paragraph1 = sheet.cell_value(2, Constants.language_code) confirm = sheet.cell_value(3, Constants.language_code) return dict( title=title, paragraph1=paragraph1.format(showup_fee=Constants.showup_fee ,currency=Constants.currency,currency_real=Constants.currency_real,XR=Constants.XR), confirm=confirm ) class D_Intro_Types(Page): form_model = 'player' def is_displayed(self): return self.round_number == 1 # only display in the first round def vars_for_template(self): loc = ("Part1_IE_DOSE/data/C_Intro_Types.xlsx") # To open Workbook wb = xlrd.open_workbook(loc) sheet = wb.sheet_by_index(0) # Get all titles & paragraphs title = sheet.cell_value(1, Constants.language_code) paragraph1 = sheet.cell_value(2, Constants.language_code) confirm = sheet.cell_value(3, Constants.language_code) return dict( title=title, paragraph1=paragraph1, confirm=confirm, ) class E_Intro_Title_Part1(Page): form_model = 'player' form_fields = ['tab_intro_title_part1', 'focus_intro_title_part1', 'totaltime_intro_title_part1'] def is_displayed(self): return self.round_number == 1 # only display in the first round def vars_for_template(self): loc = ("Part1_IE_DOSE/data/D_Intro_Title_Part1.xlsx") # To open Workbook wb = xlrd.open_workbook(loc) sheet = wb.sheet_by_index(0) # Get all titles & paragraphs title = sheet.cell_value(1, Constants.language_code) confirm = sheet.cell_value(2, Constants.language_code) return dict( title=title.format(currency=Constants.currency,FixedPointsType1=Constants.FixedPointsType1), confirm=confirm ) class F_Description_Options(Page): form_model = 'player' form_fields = ['ControlQuestion1', 'ControlQuestion2', 'ControlQuestion3', 'ControlQuestion4', 'counterWrong_page1', 'tab_desc_lotteries_part1', 'focus_desc_lotteries_part1', 'totaltime_desc_lotteries_part1'] def is_displayed(self): return self.round_number == 1 # only display in the first round def vars_for_template(self): loc = ("Part1_IE_DOSE/data/E_Description_Options.xlsx") # To open Workbook wb = xlrd.open_workbook(loc) sheet = wb.sheet_by_index(0) # Get all titles & paragraphs title = sheet.cell_value(1, Constants.language_code) paragraph1 = sheet.cell_value(2, Constants.language_code) paragraph2 = sheet.cell_value(3, Constants.language_code) paragraph3 = sheet.cell_value(4, Constants.language_code) paragraph4 = sheet.cell_value(5, Constants.language_code) paragraph5 = sheet.cell_value(6, Constants.language_code) confirm = sheet.cell_value(7, Constants.language_code) return dict( title=title, num_rounds=Constants.num_rounds, FixedPointsType1=Constants.FixedPointsType1, currency=Constants.currency, confirm=confirm, ) class G_Xclusion(Page): def is_displayed(self): return self.player.counterWrong_page1==3 or self.player.counterWrong_page2==3 class H_Description_RLIM(Page): form_model = 'player' form_fields = ['tab_understand', 'focus_understand', 'totaltime_understand'] def is_displayed(self): return self.round_number == 1 # only display in the first round def vars_for_template(self): loc = ("Part1_IE_DOSE/data/D_Description_Lotteries.xlsx") # To open Workbook wb = xlrd.open_workbook(loc) sheet = wb.sheet_by_index(0) # Get all titles & paragraphs paragraph = sheet.cell_value(6, Constants.language_code) confirm = sheet.cell_value(7, Constants.language_code) return dict( paragraph = paragraph, confirm=confirm, OptionA_high = Constants.questions[1]['Ahigh'], OptionA_low = Constants.questions[1]['Alow'], OptionB_low = Constants.questions[1]['Blow'], num_rounds=Constants.num_rounds, ) ############### END OF INSTRUCTION PAGES ################################################## # DOSE PROCEDURE class I_Question(Page): form_model = 'player' form_fields = ['optionchoice', 'tab_question_part1', 'focus_question_part1', 'totaltime_question_part1'] def before_next_page(self): current_round = self.round_number if(self.round_number==Constants.num_rounds): # get lotterychoice from last round # only for testing purposes # if (self.player.in_round(self.round_number).lotterychoice == 0): # if lottery A was chosen in previous round # print("your answer was A in last round", (self.round_number)) # elif (self.player.in_round( # self.round_number).lotterychoice == 1): # if lottery B was chosen in previous round # print("your answer was B in last round", (self.round_number)) #### end of testing ### set risk parameter and choice consistency according to the choices in the 10 previous rounds (i.e. look them up in the decision tree file) if(self.player.optionchoice==0): #if A was chosen move down by one cell self.player.IE_parameter = float(Constants.sheet.cell_value(self.player.in_round(current_round).tree_row+1, current_round+1)) self.player.choice_consistency = float(Constants.sheet.cell_value(self.player.in_round(current_round).tree_row+1, current_round+2)) elif(self.player.optionchoice==1): #if B was chosen stay on same line self.player.IE_parameter = float(Constants.sheet.cell_value(self.player.in_round(current_round).tree_row, current_round + 1)) self.player.choice_consistency = float(Constants.sheet.cell_value(self.player.in_round(current_round).tree_row, current_round + 2)) ### select one chosen lottery at random from the 10 choices # select payoff-relevant round self.player.payoffrelevant_round = random.choice(range(1,Constants.num_rounds+1)) payoffrelevant_round = self.player.payoffrelevant_round # determine if A or B was chosen in the payoff-relevant round choice = self.player.in_round(payoffrelevant_round).optionchoice # determine outcome of payoff-relevant lottery if(choice==0): # A was chosen in payoff-relevant round ## Aqui tienes que calcular los puntos del Participant 1 y del Participant 2 self.player.Payoff_Participant_1_selected_round = self.player.in_round(payoffrelevant_round).OptionA_high self.player.Payoff_Participant_2_selected_round = self.player.in_round(payoffrelevant_round).OptionA_low self.player.FixedPointsType1 = self.player.FixedPointsType1 elif(choice==1): # B was chosen ## Aqui tienes que calcular los puntos del Participant 1 y del Participant 2 self.player.Payoff_Participant_1_selected_round = self.player.in_round(payoffrelevant_round).OptionB_high self.player.Payoff_Participant_2_selected_round = self.player.in_round(payoffrelevant_round).OptionB_low self.player.FixedPointsType1 = self.player.FixedPointsType1 ######################### PASSING VARIABLES (i.e. MAKING THEM GLOBALLY AVAILABLE IN 'participant.vars') ##### PASS RISK PREFERENCES ### We here directly calculate the indifference lottery based on the estimated risk-preferences ### We pass lottery A (same for everyone), lottery B (low payoff & probabilities are same for everyone) ### The only payoff that depends on the risk parameter is the high payoff of lottery B ### Find B_high: EU(A | r) = p_low * U(B_low | r) + p_high * U(B_high | r) ##CHECK AGAIN IF THIS IS CORRECT!!!! IE= self.player.IE_parameter B_low_indifferent=(1000+3000*IE)/(1+IE) #EUA = self.player.((OptionB_high+OptionB_low-(OptionA_high+OptionA_low))/(OptionB_high-OptionB_low)) # setup lottery arrays to be inter-app accessible (used in part 2) self.participant.vars['OptionB'] = [3000,(B_low_indifferent)] self.participant.vars['OptionA'] = [2000,2000] self.participant.vars['Payoff_Participant_1_selected_round']=[self.player.Payoff_Participant_1_selected_round] self.participant.vars['Payoff_Participant_2_selected_round'] = [self.player.Payoff_Participant_2_selected_round] # setup other information to be inter-app accessible (used in part 2) self.participant.vars['payoffrelevant_round_part1'] = self.player.payoffrelevant_round self.participant.vars['FixedPointsType1'] = self.player.FixedPointsType1 self.participant.vars['optionchoice_part1'] = self.player.in_round(self.player.payoffrelevant_round).optionchoice def vars_for_template(self): # store current round current_round=self.round_number ########### GET CURRENT OPTIMAL LOTTERY ############# ### PROCEDURE: ### 1. Get the row of the next optimal lottery by looking at the previous answer: ###### if A was chosen in the previous round, move down the decision tree (i.e. row number will increase) ###### if B was chosen in the previous round, move up the decision tree (i.e. row number will decrease) ###### Special Case in 1st round: No answer has been registered. Row is for everyone the same ###### VARIABLE NAME: player.tree_row ###### (Aug. 2020: We use 10 rounds, first row of binary tree is 512) ### 2. Get the number of the next optimal lottery by storing the value in the row of the decision tree ###### Read cell value (excel sheet:"decisiontree.xsls") of the optimal row to get optimal lottery ###### Note: the sheet is read in models.py in the Constants-class ###### Special Case in 1st round: optimal lottery is the on written on row number 512 in the 1st column of the excel sheet ###### VARIABLE NAME: player.optimal_lottery ### 3. set all lottery variables (Bhigh, Blow, pBlow,...) according to the next optimal lottery ###### NOTE: because of the specific CSV-file of the lotteries, we have to go one row up (i.e. subtract 1 from optimal_lottery-value) # intializing for 1st round. tree_row is set initially in models.py to 512, so we don't need make any changes in the 1st round if (current_round == 1): # use the intial value of 512 set in models.py for the 1st round optimal_option_row = self.player.tree_row # set player.optimal_lottery self.player.optimal_option = int(Constants.sheet.cell_value(optimal_option_row, current_round)) elif(current_round>1): # move down (if A was chosen i.e. player.lotterychoice in previous round was 0) in the decision tree matrix # or down (if B was chosen i.e. player.lotterychoice in previous round was 1) in the decision tree matrix if(self.player.in_round(current_round-1).optionchoice == 0): # if A was chosen in previous round self.player.tree_row = self.player.in_round(current_round-1).tree_row + Constants.shift[current_round - 2] # set row of optimal lottery for identification in the binary tree elif(self.player.in_round(current_round-1).optionchoice == 1): # if B was chosen in previous round self.player.tree_row = self.player.in_round(current_round-1).tree_row - Constants.shift[current_round - 2] # set row of optimal lottery for identification in the binary tree optimal_option_row = self.player.tree_row self.player.optimal_option = int(Constants.sheet.cell_value(optimal_option_row, current_round)) optimal_option=self.player.optimal_option-1 #subtract one, because we read the lottery from the CSV-file, which starts at row 0 ##### only for testing purposes #print("lottery_row", optimal_lottery_row) #if(self.round_number>1): #optimal_lottery = int(Constants.sheet.cell_value(Constants.shift[self.round_number])) #if(self.player.in_round(self.round_number-1).lotterychoice == 0): #if lottery A was chosen in previous round #print("your answer was A in round",(self.round_number-1)) #elif(self.player.in_round(self.round_number-1).lotterychoice == 1): #if lottery B was chosen in previous round #print("your answer was B in round", (self.round_number - 1)) ################################# #### Determine the lottery about to be asked self.player.OptionB_high = float(Constants.questions[optimal_option]['Bhigh']) self.player.OptionB_low = float(Constants.questions[optimal_option]['Blow']) self.player.OptionA_high = 2000 self.player.OptionA_low = 2000 return dict( current_round=current_round ) class J_End(Page): form_model = 'player' form_fields = ['tab_end_part1', 'focus_end_part1', 'totaltime_end_part1'] def is_displayed(self): return self.round_number == Constants.num_rounds #only display in the last round ##################################################################################### def vars_for_template(self): player_in_all_rounds = self.player.in_all_rounds() return dict( player_in_all_rounds=player_in_all_rounds, #B_high = self.participant.vars['B_high_indifferent'] B_high =0, ) page_sequence = [ A_Consent_Form, B_prolificID, C_Instructions_General, D_Intro_Types, E_Intro_Title_Part1, F_Description_Options, G_Xclusion, H_Description_RLIM, I_Question, J_End ] #page_sequence = [preQuestion,Question,H_End]