# from otree.api import ( # models, widgets, BaseSubsession, BaseGroup, BasePlayer, # Currency as c, currency_range # ) from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency, Currency as c, currency_range, ) import random # from .config import Constants author = 'Felix Holzmeister & Armin Pfurtscheller' doc = """ Bomb Risk Elicitation Task (BRET) à la Crosetto/Filippin (2013), Journal of Risk and Uncertainty (47): 31-65. https://github.com/felixholzmeister/bret """ # ******************************************************************************************************************** # # *** CLASS CONSTANTS *** # # ******************************************************************************************************************** # class Constants(BaseConstants): # oTree Constants name_in_url = 'bomb' players_per_group = None # ---------------------------------------------------------------------------------------------------------------- # # --- Overall Settings and Appearance --- # # ---------------------------------------------------------------------------------------------------------------- # # value of single collected box # if the bomb is not collected, player's payoff per round is determined by times # note that the currency of any earnings is determined by the oTree settings in settings.py # if you set this to a decimal number, you must set POINTS_DECIMAL_PLACES in settings.py box_value = Currency(0.02) # number of rows and columns # i.e. the total number of boxes is determined by times num_rows = 8 num_cols = 8 # box height and box width in pixels # make sure that the size of the boxes fits the screen of the device # note that the layout is responsive, i.e. boxes will break into new rows if they don't fit box_height = '50px' box_width = '50px' # number of rounds to be played num_rounds = 3 # determines whether all rounds played are payed-off or whether one round is randomly chosen for payment # if , one round is randomly determined for payment # if , the final payoff of the task is the sum of all rounds played # note that this is only of interest for the case of larger than 1 random_payoff = True # if , a separate template "Instructions.html" is rendered prior to the task in round 1 # if , the task starts immediately (e.g. in case of printed instructions) instructions = True # show feedback by resolving boxes, i.e. toggle boxes and show whether bomb was collected or not # if , the button "Solve" will be rendered and active after game play ends ("Stop") # if , the button "Solve" won't be rendered such that no feedback about game outcome is provided feedback = True # show results page summarizing the game outcome # if , a separate page containing all relevant information is displayed after finishing the task # if larger than 1, results are summarized in a table and only shown after all rounds have been played results = True # ---------------------------------------------------------------------------------------------------------------- # # --- Settings Determining Game Play --- # # ---------------------------------------------------------------------------------------------------------------- # # "dynamic" or "static" game play # if , one box per time interval is collected automatically # in case of , game play is affected by the variables and below # if , subjects collect as many boxes as they want by clicking or entering the respective number # in case of , game play is affected by the variables , and dynamic = True # time interval between single boxes being collected (in seconds) # note that this only affects game play if time_interval = 1.00 # collect boxes randomly or systematically # if , boxes are collected row-wise one-by-one, starting in the top-left corner # if , boxes are collected randomly (Fisher-Yates Algorithm) # note that this affects game play in both cases, and random = True # determines whether static game play allows for selecting boxes by clicking or by entering a number # if , game play is similar to Slovic (1965), i.e. boxes are collected by subjects # if , subjects enter the number of boxes they want to collect # note that this only affects game play if devils_game = False # determine whether boxes can be toggled only once or as often as clicked # if boxes can be selected and de-selected indefinitely often # if boxes can be selected only once (i.e. decisions can not be undone) # note that this only affects game play if and undoable = True # #LIA ADDED -not working! instructions_template = 'bret/instructionstext.html' # ******************************************************************************************************************** # # *** CLASS SUBSESSION *** # # ******************************************************************************************************************** # class Subsession(BaseSubsession): pass # ******************************************************************************************************************** # # *** CLASS GROUP *** # # ******************************************************************************************************************** # class Group(BaseGroup): pass # ******************************************************************************************************************** # # *** CLASS PLAYER *** # # ******************************************************************************************************************** # class Player(BasePlayer): # whether bomb is collected or not # store as integer because it's easier for interop with JS bomb = models.IntegerField() # location of bomb bomb_row = models.PositiveIntegerField() bomb_col = models.PositiveIntegerField() # number of collected boxes boxes_collected = models.IntegerField() # --- set round results and player's payoff # ------------------------------------------------------------------------------------------------------------------ pay_this_round = models.BooleanField() round_result = models.CurrencyField() # LIA ADDED bomb_consequential = models.IntegerField() boxes_collected_consequential = models.IntegerField() my_memory_payoff = models.CurrencyField() timeout = models.IntegerField( choices=[0, 1], initial=0 ) def set_payoff(self): # determine round_result as (potential) payoff per round if self.bomb: self.round_result = c(0) else: self.round_result = self.boxes_collected * Constants.box_value # set payoffs if to round_result of randomly chosen round # randomly determine round to pay on player level if self.subsession.round_number == 1: self.participant.vars['round_to_pay'] = random.randint(1,Constants.num_rounds) if Constants.random_payoff: if self.subsession.round_number == self.participant.vars['round_to_pay']: self.pay_this_round = True self.payoff = self.round_result #LIA ADDED self.participant.vars['bomb_consequential'] = self.bomb self.participant.vars['boxes_collected_consequential'] = self.boxes_collected else: self.pay_this_round = False self.payoff = c(0) # set payoffs to round_result if else: self.payoff = self.round_result