from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range ) import csv import xlrd # for reading XLS-files import random from otree.models import Participant from collections import (Counter, defaultdict) 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' currency2='£' #currency='USD' # define exchange rate 1 ECU = xxx $ = xxx CHF XR = 0.01 XR = 0.001 XR = 0.00075 # define scaling of price scale = 0.5 scale = 1 ######################################################## ############ DEFINE SHOWUPFEE showup_fee = 2000 showup_fee = 2667 showup_fee_converted = showup_fee * XR #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_600.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/tree_WTP.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): self.session.vars['questions'] = Constants.questions.copy() for index, player in enumerate(self.get_players(), start=1): if index % 2 == 1: player.version = 'PIC1' else: player.version = 'PIC2' class Group(BaseGroup): pass class Player(BasePlayer): version = models.StringField( choices=['DEMO','REPU','PIC1','PIC2','MALE','FEMALE'], doc="Randomly assigned version", ) current_page = models.IntegerField(initial=0) ############ DEFINE LOTTERY VARIABLES ### # Define B-Lottery variables # lotteryB_high = models.IntegerField(initial=2000) # lotteryB_low = models.IntegerField(initial=1000) lotteryB_high = models.FloatField(null=True, default=None) lotteryB_low = models.FloatField(null=True, default=None) probB_low = models.FloatField() probB_high = models.FloatField() # Define A-Lottery variables lotteryA_high = models.FloatField(null=True, default=None) lotteryA_low = models.FloatField(null=True, default=None) # lotteryA_high = models.IntegerField(initial=2000) # lotteryA_low = models.IntegerField(initial=200) probA_low = models.FloatField() probA_high = 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() #### 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 lotterychoice_auto = models.IntegerField(null=True, default=0) # Define variables for lottery outcome (a random draw is performed for both lotteries, # s.t. it is possible to quickly announce what the outcome of the chosen lottery was on the same page) drawC = models.FloatField() drawD = models.FloatField() # draw of chosen lottery draw = models.FloatField(null=True, default=0) ########## DEFINE CONTROL QUESTION VARIABLES ### ControlQuestion1 = models.IntegerField() ControlQuestion2 = models.IntegerField() ControlQuestion3 = models.IntegerField() ControlQuestion4 = models.IntegerField() ControlQuestion5 = models.IntegerField() # counter for control questions counterWrong = models.IntegerField(initial=0) ################################################ #### Variables from Part 1 (other than lottery information) payoff_part1 = models.FloatField() lotterychoice_part1 = models.IntegerField() payoffrelevant_round_part1 = models.IntegerField() payoffrelevant_round_part1_low = models.FloatField() payoffrelevant_round_part1_high = 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 ######################### END OF PROLIFIC ONLY ##################################################################### #################################################################################################################### # tab switches & focus-/unfocus-time tab_intro_title_part2 = models.IntegerField() tab_general_part2 = models.IntegerField() tab_desc_lotteries_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_survey_part2 = models.IntegerField() # tab switches & focus-/unfocus-time focus_intro_title_part2 = models.FloatField() focus_general_part2 = models.FloatField() focus_desc_lotteries_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_survey_part2 = models.FloatField() # tab switches & focus-/unfocus-time totaltime_intro_title_part2 = models.FloatField() totaltime_general_part2 = models.FloatField() totaltime_desc_lotteries_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_survey_part2 = models.FloatField() risk = models.IntegerField(choices=range(0,11), verbose_name="") urbanrural = models.IntegerField(choices=[[1, 'Rural'], [2, 'Urban']], verbose_name="", widget=widgets.RadioSelect) children = models.IntegerField(choices=[[1, '0'], [2, '1'], [3, '2'],[4, '3'],[5, '4'],[6, '5'], [7, '6'], [8, '7'], [9, '8'], [10, '9'], [11, '10'], [12, 'More'],], verbose_name="") household = models.IntegerField(choices=[[1, '0'], [2, '1'], [3, '2'],[4, '3'],[5, '4'],[6, '5'], [7, '6'], [8, '7'], [9, '8'], [10, '9'], [11, '10'], [12, 'More'],], verbose_name="") income = models.IntegerField(choices=[[1, 'Less than 9,999$'], [2, 'Between 10,000$ and 19,999$'], [3, 'Between 20,000$ and 29,999$'], [4, 'Between 30,000$ and 39,999$'], [5, 'Between 40,000$ and 49,999$'], [6, 'Between 50,000$ and 59,999$'], [7, 'Between 60,000$ and 69,999$'], [8, 'Between 70,000$ and 79,999$'], [9, 'Between 80,000$ and 89,999$'], [10, 'Between 90,000$ and 99,999$'], [11, 'Between 100,000$ and 109,999$'], [12, 'Between 110,000$ and 119,999$'], [13, 'Between 120,000$ and 129,999$'], [14, 'Between 130,000$ and 139,999$'], [15, 'Between 140,000$ and 149,999$'], [16, 'More than 150,000$']], verbose_name="") maritalstatus = models.IntegerField(choices=[[4, 'Divorced'],[1, 'Married'], [2, 'Single'], [3, 'Widowed']], verbose_name="", widget=widgets.RadioSelect) education = models.IntegerField(choices=[[1, 'Less than High School'], [2, 'High School Diploma'], [3, 'Some college or associate degree'], [4, '4-year college degree'], [5, 'More than 4-year college degree']], verbose_name="") religious = models.IntegerField(choices=[[1, 'Yes'],[0, 'No'],[2, 'Prefer not to answer']], verbose_name="", widget=widgets.RadioSelect) employmentstatus = models.IntegerField(choices=[[1, 'Employed'],[6, 'Retired'],[2, 'Self-employed'],[5, 'Stay-at-home mother/father'],[4, 'Student'],[3, 'Unemployed']],verbose_name='') race = models.IntegerField(choices=[[1, 'American Indian or Alaska Native'],[2, 'Asian / Asian American'], [3, 'Black / African American'],[4, 'Hispanic or Latino'],[5, 'Middle Eastern or North African'], [6, 'Native Hawaiian or Other Pacific Islander'],[7, 'White / European American']],verbose_name='') citizen = models.IntegerField(choices=[[1, 'Yes'], [0, 'No'], [2, 'Prefer not to answer']], verbose_name="", widget=widgets.RadioSelect) vote = models.IntegerField(choices=[[1, 'Yes'], [0, 'No'], [2, 'Prefer not to answer']], verbose_name="", widget=widgets.RadioSelect) social = models.IntegerField(choices=[[1, 'Extremely liberal'], [2, 'Liberal'], [3, 'Slightly liberal'],[4, 'Moderate'],[5, 'Slightly conservative'],[6, 'Conservative'], [7, 'Extremely conservative']], verbose_name="", widget=widgets.RadioSelect) economic = models.IntegerField(choices=[[1, 'Extremely liberal'], [2, 'Liberal'], [3, 'Slightly liberal'],[4, 'Moderate'],[5, 'Slightly conservative'],[6, 'Conservative'], [7, 'Extremely conservative']], verbose_name="", widget=widgets.RadioSelect) voteB = models.IntegerField(choices=[[1,'Never'],[2,'Rarely'],[3,'Sometimes'],[4,'Usually'],[5,'Always']], verbose_name="", widget=widgets.RadioSelect, default=3) registered = models.IntegerField(choices=[[1, 'Yes'], [0, 'No'], [2, 'Prefer not to answer']], verbose_name="", widget=widgets.RadioSelect) trust1 = models.IntegerField(choices=[[1, 'Completely distrust'], [2, 'Distrust'], [3, 'Neither distrust nor trust'], [4, 'Trust'],[5, 'Completely trust']], verbose_name="", widget=widgets.RadioSelect) trust2 = models.IntegerField(choices=[[1, 'Completely distrust'], [2, 'Distrust'], [3, 'Neither distrust nor trust'], [4, 'Trust'],[5, 'Completely trust']], verbose_name="", widget=widgets.RadioSelect) circle = models.IntegerField(choices=[[1, '1'], [2, '2'], [3, '3'],[4, '4'],[5, '5'],[6, '6'],[7, '7']], verbose_name="", widget=widgets.RadioSelect) attention_check = models.StringField(choices=['Not important at all','Not important', 'Somewhat important', 'Important', 'Very important'], verbose_name="", widget=widgets.RadioSelect) ##################### Exclusion #################################################################################### exclusion = models.IntegerField(initial=0)