from otree.api import * from decimal import * author = "Nathaniel Archer Lawrence, LEMMA, Université Panthéon-Assas - Paris II" doc = """ Consumption simulation with interface based off of 'Shopping app (online grocery store)' from oTree demos, see: . """ class C(BaseConstants): NAME_IN_URL = 'intructions' PLAYERS_PER_GROUP = None NUM_ROUNDS = 1 # task constants NUM_PERIODS = 120 INITIAL_ENDOWMENT = cu(210) INCOME = 3.99 INTEREST_RATE = 0.1/12 INTEREST_PERCENT = round(INTEREST_RATE*100,2) INTEREST_EARNED = cu((INITIAL_ENDOWMENT + INCOME) * INTEREST_RATE ) CONSUMPTION_RATE = 1 # amount of good consumed from stock balance each period MONETARY_POLICY = 0 TOTAL_CASH = cu(INITIAL_ENDOWMENT + INCOME) class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): ### choices = [[value,label],[value,label],...] q1 = models.IntegerField( label='The objective of the Savings Game is to maximize which Balance over 120 periods?', widget=widgets.RadioSelect ) q2 = models.IntegerField( label='In addition to interest earned on your Savings Account balance from the previous period, how much income do you receive at the start of each period?', widget=widgets.RadioSelect ) q3 = models.IntegerField( label='Total Cash is the sum of what?', widget=widgets.RadioSelect ) q4 = models.IntegerField( label='''In order to survive to the next period, you Starting Stock Next Period must be greater than or equal to what amount before clicking the "Finalize Purchase" button?''', widget=widgets.RadioSelect ) q5 = models.IntegerField( label='How many units of Basket of Goods are you required to purchase each period?', widget=widgets.RadioSelect ) q6 = models.IntegerField( label='Which of the following statements is false?', widget=widgets.RadioSelect ) q7 = models.FloatField() # models.IntegerField( # label='''After you complete period 12, when asked "How confident are you with your decision in the previous period?", this refers to your decision in which period?''', # widget=widgets.RadioSelect # ) # q8 = def q1_choices(player): import random choices = [[1,'Savings Account'],[2,'Starting Stock Next Period'],[3,'Total Cash'],[4,'Interest earned']] random.shuffle(choices) return choices def q2_choices(player): import random choices = [[1,cu(3.99)],[2,cu(120)],[3,cu(4)],[4,'I only receive interest']] random.shuffle(choices) return choices def q3_choices(player): import random choices = [[1,'Interest Earned Last Period + Savings Account balance (from last period) + Wage'], [2,'Interest Earned Last Period + Savings Account balance (from last period)'], [3,'Savings Account balance (from last period) + Wage'], [4,'Interest Earned Last Period + Wage'], [5,'The total price of my purchase of baskets of goods']] random.shuffle(choices) return choices def q4_choices(player): import random choices = [[1,'0'],[2,'-1'],[3,'120'],[4,float(3.99)]] random.shuffle(choices) return choices def q5_choices(player): import random choices = [[1,'There is no minimum as long as my Starting Stock Next Period requirement is met'], [2,'1'], [3,'-1'], [4,'120']] random.shuffle(choices) return choices def q6_choices(player): import random choices = [[1,'The interest rate paid on my Savings Account can change each period.'], [2,'The price of Basket of Goods can change each period.'], [3,'The amount displayed under my Starting Stock Next Period includes the unit I will consume before the next period.'], [4,'My Wage cannot change each period.']] random.shuffle(choices) return choices # def q7_choices(player): # import random # choices = [[1,'11'], # [2,'1'], # [3,'12'], # [4,'120']] # random.shuffle(choices) # return choices # PAGES class Instruction_Page(Page): form_model = 'player' form_fields = ['q1','q2','q3','q4','q5','q6','q7'] @staticmethod def vars_for_template(player: Player): return dict( interest_rounded=round(C.INTEREST_RATE * 100,4), ) @staticmethod def error_message(player, values): solutions = dict( q1=1, q2=1, q3=1, q4=1, q5=1, q6=1, q7=1, # q8=1 ) error_messages = dict() for field_name in solutions: if values[field_name] != solutions[field_name]: error_messages[field_name] = 'Wrong answer. Please, review the instructions and correct your answer(s).' return error_messages class Results(Page): pass # @staticmethod # def app_after_this_page(player, upcoming_apps): # return player.session.config['intervention'] page_sequence = [Instruction_Page, Results]