from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range ) import csv import xlrd # for reading XLS-files author = 'Dr. Jana Freundt & Leander Kopp' doc = """ This app reads 2 lotteries from a CSV-file and exports the decision. A prototype_Part2 app that reads its questions from a spreadsheet (see lotteries.csv in this directory). There is 1 decision per page; the number of pages in the game is determined by the number of decisions in the CSV. """ class Constants(BaseConstants): name_in_url = 'Part2_WTP_DOSE' players_per_group = None ############ LANGUAGE SETTINGS # 1: english, 2:german, 3:french..... language_code=1 ############ DEFINE CURRENCY, XRs AND LOTTERYSCALING ### # define displayed currency currency='points' #currency='CHF' currency_real='£' # define exchange rate 1 ECU = xxx $ = xxx CHF XR = 1000 # define scaling of lottery scale = 1 FixedPointsType1 = 2000 payoff_part3 = 1500 ######################################################## ############ DEFINE SHOWUPFEE showup_fee =2 #read & store all prices #with open('Part2_WTP_DOSE/prices.csv') as questions_file: # questions = list(csv.DictReader(questions_file)) #with open('Part2_WTP_DOSE/prices_dez2020.csv') as questions_file: # questions = list(csv.DictReader(questions_file)) with open('Part2_WTP_DOSE/prices.csv') as decisiontree_file: questions = list(csv.DictReader(decisiontree_file)) #with open('Part2_WTP_DOSE/prices_800.csv') as decisiontree_file: # questions = list(csv.DictReader(decisiontree_file)) #tree = ("Part2_WTP_DOSE/decisiontree_WTP.xlsx") #tree = ("Part2_WTP_DOSE/decisiontree_WTP_spicy_prolific3.xlsx") #tree = ("Part2_WTP_DOSE/decisiontree_WTP_dez2020.xlsx") #tree = ("Part2_WTP_DOSE/decisiontree_WTP_feb2021.xlsx") #tree = ("Part2_WTP_DOSE/decisiontree_WTP_10rounds_1-15mu_5random_600points.xlsx") tree = ("Part2_WTP_DOSE/WTP_tree.xlsx") #tree = ("Part2_WTP_DOSE/decisiontree_WTP_nov21.xlsx") # To open Workbook wb = xlrd.open_workbook(tree) sheet = wb.sheet_by_index(0) # Get for every stage all optimal prices (row,column) #num_rounds = len(questions) #num_rounds = 10 # 10 rounds for DOSE #num_rounds = 8 # 8 rounds for DOSE #num_rounds = 9 # 9 rounds for DOSE (prolific) num_rounds = 10 # 10 rounds for DOSE (prolific) # prepare numbers for going along the binary decision tree ### EXPLANATIONS: The horizontal decision tree is a 1024x10 matrix. ### The first stage is located at row 512 in column 1 ### The price information for the 2nd stage are located at row 512+256 and 512-256 and column 2 and so on. (see shift-numbers) #shift=[256,128,64,32,16,8,4,2,1] #shift=[64,32,16,8,4,2,1] # for prolific: 9 rounds #shift=[128,64,32,16,8,4,2,1] shift=[256,128,64,32,16,8,4,2,1] class Subsession(BaseSubsession): def creating_session(self): if self.round_number == 1: self.session.vars['questions'] = Constants.questions.copy() class Group(BaseGroup): pass class Player(BasePlayer): # Define B-Option variables optionB_high = models.FloatField() optionB_low = models.FloatField() # Define A-Option variables optionA_high = models.FloatField() optionA_low = models.FloatField() ######################################### #### Willingness-to-pay for a decision right --> Our primary variable of interest WTP = models.FloatField() #### Choice consistency for WTP DOSE choice_consistency = models.FloatField() #### payoff variable payoff_part2 = models.FloatField() #### selected round for payoff payoffrelevant_round_part2 = models.IntegerField() Payoff_Participant_3_selected_round = models.FloatField() Payoff_Participant_4_selected_round = models.FloatField() #### selected round for payoff (including high and low payoffs of this lottery) payoffrelevant_round_part1 = models.IntegerField() #### Variables for moving in the decision tree optimal_price_index = models.IntegerField() tree_row = models.IntegerField(initial=512) # set the initial row of the optimal price from the binary tree #tree_row = models.IntegerField(initial=128) # set the initial row of the optimal price from the binary tree #tree_row = models.IntegerField(initial=256) # set the initial row of the optimal price from the binary tree #tree_row = models.IntegerField(initial=512) # set the initial row of the optimal price from the binary tree #### price variable for current round current_price = models.FloatField() ######################################### # Define Choice variable: This variable stores whether current_price was chosen to be paid or not (in each round) # (1=autonomy or 0=delegation) pricechoice = models.IntegerField() # Define Choice variable: This variable stores the lottery choice in case of autonomy optionchoice_auto = models.IntegerField() ########## DEFINE CONTROL QUESTION VARIABLES ### ControlQuestion1 = models.IntegerField() ControlQuestion2 = models.IntegerField() ControlQuestion3 = models.IntegerField() ControlQuestion4 = models.IntegerField() # counter for control questions counterWrong = models.IntegerField(initial=0) ################################################ #### Variables from Part 1 (other than lottery information) FixedPointsType1 = models.FloatField() optionchoice_part1 = models.IntegerField() Payoff_Participant_1_selected_round = models.FloatField() Payoff_Participant_2_selected_round = models.FloatField() #### Other payoff-variables final_payoff = models.FloatField() final_payoff_converted = models.FloatField() payoff_part1_converted = models.FloatField() payoff_part2_converted = models.FloatField() ### delegation variable --> shows whether delegation or autonomy has been implemented by RLIM delegation = models.BooleanField() #################################################################################################################### ########################## PROLIFIC ONLY (REDUCED SURVEY + FEEDBACK) ############################################### employmentStatus = models.IntegerField( choices=[[1, 'employed'], [2, 'self-employed'], [3, 'unemployed'], [4, 'Student']], verbose_name='What is your current employment status?' ) # 0: employed, 1: self-employed, 2: unemployed ##### GSES GSE1 = models.FloatField() # 0: not at all, 1: very true GSE2 = models.FloatField() # 0: not at all, 1: very true GSE3 = models.FloatField() # 0: not at all, 1: very true GSE4 = models.FloatField() # 0: not at all, 1: very true GSE5 = models.FloatField() # 0: not at all, 1: very true GSE6 = models.FloatField() # 0: not at all, 1: very true GSE7 = models.FloatField() # 0: not at all, 1: very true GSE8 = models.FloatField() # 0: not at all, 1: very true GSE9 = models.FloatField() # 0: not at all, 1: very true GSE10 = models.FloatField() # 0: not at all, 1: very true ########## ##### IAF IAF1 = models.FloatField() IAF2 = models.FloatField() IAF3 = models.FloatField() IAF4 = models.FloatField() IAF5 = models.FloatField() IAF6 = models.FloatField() IAF7 = models.FloatField() ###### WORK work1 = models.FloatField() work2 = models.FloatField() work3 = models.FloatField() work4 = models.FloatField() work5 = models.FloatField() ##################### Attentionchecks ############################################################################## attentioncheck1 = models.FloatField() attentioncheck2 = models.FloatField() attentioncheck3 = models.FloatField() #################################################################################################################### ##################### Exclusion #################################################################################### exclusion = models.IntegerField() # FEEDBACK Feedback1_11 = models.FloatField() Feedback1_12 = models.LongStringField(blank=True) Feedback1_21 = models.FloatField() Feedback1_22 = models.LongStringField(blank=True) Feedback1_3 = models.IntegerField(blank=True) Feedback1_4 = models.FloatField() Feedback1_5 = models.FloatField() Feedback1_6 = models.LongStringField(blank=True) Feedback2_11 = models.FloatField() Feedback2_12 = models.LongStringField(blank=True) Feedback2_21 = models.FloatField() Feedback2_22 = models.LongStringField(blank=True) Feedback2_3 = models.FloatField() Feedback2_4 = models.FloatField() Feedback2_5 = models.LongStringField(blank=True) Feedback2_6 = models.LongStringField(blank=True) Feedback1 = models.LongStringField( verbose_name='If you have any general comments for us please leave them here:', blank=True) Feedback2 = models.IntegerField( choices=[[1, 'Extremely easy'], [2, 'moderately easy'], [3, 'neither easy nor difficult'], [4, 'moderately difficult'], [5, 'extremely difficult']], verbose_name='Overall, how easy or difficult was it for you to answer the questions?', widget=widgets.RadioSelect) Feedback3 = models.FloatField( # choices=[[0, 'I did not care at all'], [1, 'Very important']], verbose_name='Did you feel as if the choices you made during the experiment were important to you?', widget=widgets.Slider(attrs={'step': '0.01'}, show_value=False)) Feedback4 = models.LongStringField( verbose_name='Please briefly describe the choices you made in this experiment in your own words! In this pilot study, we are interested in learning what you perceived your tasks in part 1 and part 2 of this experiment to be.', blank=True) Feedback_Rationale_Part1 = models.IntegerField( choices=[[1, 'I followed my intuition / gut feeling'], [2, 'I set a risk threshold'], [3, 'I tried to maximize the expected monetary outcome'], [4, 'I always chose at random'], [5, 'None of the above']], verbose_name='6. Which reasoning best describes how you made your choices in part 1?') Feedback_Rationale_Part2 = models.IntegerField( choices=[[1, 'I set a price threshold'], [2, 'I wanted to pay to be able to choose by myself'], [3, 'I wanted to pay to choose the safer lottery'], [4, 'I wanted to pay to choose the riskier lottery'], [5, 'I did not want to pay because I did not care'], [6, 'I did not want to pay because the outcome is chance-determined'], [7, 'I wanted to maximize my monetary outcome'], [8, 'None of the above']], verbose_name='11. Which reasoning best describes how you made your choices in part 2?') ######################### END OF PROLIFIC ONLY ##################################################################### #################################################################################################################### # tab switches & focus-/unfocus-time tab_intro_title_part2 = models.IntegerField() tab_general_part2 = models.IntegerField() tab_desc_options_part2 = models.IntegerField() tab_desc_choice_part2 = models.IntegerField() tab_desc_rlim_part2 = models.IntegerField() tab_pre_question_part2 = models.IntegerField() tab_pre_decision_part2 = models.IntegerField() tab_question_part2 = models.IntegerField() tab_self_part2 = models.IntegerField() tab_delegation_part2 = models.IntegerField() tab_payoff_part2 = models.IntegerField() # tab switches & focus-/unfocus-time focus_intro_title_part2 = models.FloatField() focus_general_part2 = models.FloatField() focus_desc_options_part2 = models.FloatField() focus_desc_choice_part2 = models.FloatField() focus_desc_rlim_part2 = models.FloatField() focus_pre_question_part2 = models.FloatField() focus_pre_decision_part2 = models.FloatField() focus_question_part2 = models.FloatField() focus_self_part2 = models.FloatField() focus_delegation_part2 = models.FloatField() focus_payoff_part2 = models.FloatField() # tab switches & focus-/unfocus-time totaltime_intro_title_part2 = models.FloatField() totaltime_general_part2 = models.FloatField() totaltime_desc_options_part2 = models.FloatField() totaltime_desc_choice_part2 = models.FloatField() totaltime_desc_rlim_part2 = models.FloatField() totaltime_pre_question_part2 = models.FloatField() totaltime_pre_decision_part2 = models.FloatField() totaltime_question_part2 = models.FloatField() totaltime_self_part2 = models.FloatField() totaltime_delegation_part2 = models.FloatField() totaltime_payoff_part2 = models.FloatField()