from otree.api import * from otree import settings import numpy as np import pandas as pd doc = """Experiment 2 for Social Inference project """ # TO DOs --------------------------------------------------------------------------------------------------------------- # Questions whether participants thought it was a real human partner # Screen at the end of training phase that the experiment starts now # NOTES TO SELF -------------------------------------------------------------------------------------------------------- # A player is initialized per session, i.e., in every session I will have x players # Otree initializes a participant code that is valid across different subsessions # I can create 1 room and in that 1 room I have 3 session configs that the experimenter can select. Then, # once a session config is selected the experimenter can create however many links they need and share it with the participants. # BUT with that set-up I would not have continuous participant numbers... however, I assign environment and demonstrator based on those participant numbers # and I want to make sure that the same environments and demonstrators are used in all conditions... # OTREE CLASSES -------------------------------------------------------------------------------------------------------- class C(BaseConstants): NAME_IN_URL = 'SI_Exp2_a_TrainingSequence' PLAYERS_PER_GROUP = None NUM_ROUNDS = 10 class Subsession(BaseSubsession): environment = models.IntegerField() subject_number = models.IntegerField() class Group(BaseGroup): pass class Player(BasePlayer): Two_comprehension_check_spatial = models.IntegerField(label="Are points more similar to each other when the cells are closer to each other?", widget=widgets.RadioSelect, choices=[[1, 'a) Yes'], [2, 'b) No'],]) Two_result = models.IntegerField() Three_comprehension_check_inference = models.IntegerField(label="Is the following statement True or False: I will see all selections that the player made and all points that the player received.", widget=widgets.RadioSelect, choices=[[1, 'a) True'], [2, 'b) False'],]) Three_result = models.IntegerField() page_name = models.StringField() counter = models.IntegerField(default=0) IV_num_choice_only = models.IntegerField() inferred_reward = models.IntegerField( min=0, max=500, label='What reward did the player get on the previous trial?', blank=True, null=True, doc="""This player's decision""") inferred_choice = models.StringField( max_length=500, blank=True, null=True) predicted_reward = models.IntegerField( min=0, max=500, label='What reward will the player get on the next trial?', blank=True, null=True, doc="""This player's decision""") predicted_choice = models.StringField( max_length=500, blank=True, null=True) predicted_choice_row = models.IntegerField( max_length=500, blank=True, null=True) predicted_choice_column = models.IntegerField( max_length=500, blank=True, null=True) RT_inferred_reward = models.FloatField(initial=None, null=True, blank=True) RT_inferred_choice = models.FloatField(initial=None, null=True, blank=True) RT_predicted_reward = models.FloatField(initial=None, null=True, blank=True) RT_predicted_choice = models.FloatField(initial=None, null=True, blank=True) round_data_field = models.IntegerField() performance = models.FloatField() payout = models.FloatField() participant_code = models.StringField() ObsB_predicted_reward = models.IntegerField(field_maybe_none=True) ObsB_inferred_reward = models.IntegerField(field_maybe_none=True) ObsB_highlight_index_row = models.IntegerField(field_maybe_none=True) ObsB_highlight_index_column = models.IntegerField(field_maybe_none=True) ObsB_inf_highlight_index_row = models.IntegerField(field_maybe_none=True) ObsB_inf_highlight_index_column = models.IntegerField(field_maybe_none=True) ObsB_time_to_decide = models.FloatField(field_maybe_none=True) cheat_stay_on_page = models.IntegerField() # if we use Player model for read_csv these fields are required trial_index = models.IntegerField() trial_type = models.StringField() reward_inference_query = models.IntegerField() choice_inference_query = models.IntegerField() reward_prediction_query = models.IntegerField() choice_prediction_query = models.IntegerField() def store_round_data(self): self.round_data_field = self.round_number # Storing round number as an example def before_next_page(self): self.store_round_data() def increment_counter(self): self.counter += 1 return self.counter class Row(ExtraModel): player = models.Link(Player) SN = models.IntegerField() participant_label = models.IntegerField() participant_code = models.StringField() IV_number_choice_only_trials = models.IntegerField() trial_index = models.IntegerField() trial = models.IntegerField() trial_type = models.StringField() inferred_reward = models.IntegerField( min=0, max=500, label='What reward did the player get on the previous trial?', blank=True, doc="""This player's decision""") inferred_choice = models.StringField( max_length=500, blank=True) predicted_reward = models.IntegerField( min=0, max=500, label='What reward will the player get on the next trial?', blank=True, null=True, doc="""This player's decision""") predicted_choice = models.StringField( max_length=500, blank=True) RT_inferred_reward = models.FloatField(initial=None) RT_inferred_choice = models.FloatField(initial=None) RT_predicted_reward = models.FloatField(initial=None) RT_predicted_choice = models.FloatField(initial=None) reward_inference_query = models.BooleanField() choice_inference_query = models.BooleanField() reward_prediction_query = models.BooleanField() choice_prediction_query = models.BooleanField() demonstrator_choice_index = models.IntegerField() demonstrator_choice_index_row = models.IntegerField() demonstrator_choice_index_column = models.IntegerField() demonstrator_noisy_rescaled_reward = models.IntegerField() demonstrator_choice_probs = models.StringField() demonstrator_noisy_rescaled_all_rewards = models.StringField() mean_reward = models.FloatField() x1_index = models.IntegerField() x2_index = models.IntegerField() money = models.FloatField(initial=0) # per trial # fields I have to create, but hopefully not save Demonstrator_for_SN = models.IntegerField() environment = models.IntegerField() scale = models.IntegerField() demonstrator_choice_prob = models.FloatField() demonstrator_true_all_rewards = models.LongStringField() demonstrator_noisy_reward = models.FloatField() ObsB_predicted_reward = models.IntegerField(field_maybe_none=True) ObsB_inferred_reward = models.IntegerField(field_maybe_none=True) ObsB_predicted_choice_row = models.IntegerField(field_maybe_none=True) ObsB_predicted_choice_col = models.IntegerField(field_maybe_none=True) ObsB_inferred_choice_row = models.IntegerField(field_maybe_none=True) ObsB_inferred_choice_col = models.IntegerField(field_maybe_none=True) ObsB_time_to_decide = models.FloatField(field_maybe_none=True) # PAGES ---------------------------------------------------------------------------------------------------------------- class empty_grid(Page): template_name = 'SI_Exp2_NoPartner_TrainingSequence/empty_grid.html' counter = 0 def is_displayed(player: Player): # "Next round" should not be shown on first trial if player.round_number > 1: return True def vars_for_template(self): my_array = np.empty((11, 11)) grid_number = my_array.tolist() return {'grid_number': grid_number} timeout_seconds = 4 class predict_choice(Page): template_name = 'SI_Exp2_NoPartner_TrainingSequence/predict_choice.html' form_model = 'player' form_fields = ['predicted_choice', 'RT_predicted_choice'] #cheat_stay_on_page def is_displayed(player: Player): # import the csv # placerholder ObsA_trials = read_csv('SI_Exp2_ObsB_TrainingSequence2/SI_Exp2_PageSequence_Training.csv', Player) #print('ObsA_trials', ObsA_trials) #ObsB_trials = read_csv('SI_Exp2_AlgoPartner_MainExp/01_ParticipantFiles/SI_PageSequence_' + str(int(player.session.config['subject_number'])+1) + '.csv', Row) # Change back #ObsA_trials = 'SI_Exp2_ObsB_TrainingSequence2/SI_Exp2_PageSequence_Training.csv' #ObsB_trials = read_csv('SI_Exp2_AlgoPartner_MainExp/01_ParticipantFiles/SI_PageSequence_' + str(int(player.session.config['subject_number'])+1) + '.csv', Row) # check whether page sequence csv says we have to ask choice prediction query for either Observer t = (player.round_number - 1) ObsA_this_trials_data = ObsA_trials[t] #print('ObsA_this_trials_data', ObsA_this_trials_data) #ObsB_this_trials_data = ObsB_trials[t] if int(ObsA_this_trials_data['choice_prediction_query']) == 1: return True def vars_for_template(self): #environment = self.session.config['environment'] # this just gives the grid grid_numbers = np.empty((11, 11)) grid_data = [] for row_idx, row in enumerate(grid_numbers): grid_row = [] for col_idx, value in enumerate(row): cell = {'value': value, 'row_index': row_idx, 'column_index': col_idx} grid_row.append(cell) grid_data.append(grid_row) ObserverA_PageSequence = read_csv('SI_Exp2_ObsB_TrainingSequence2/SI_Exp2_PageSequence_Training.csv', Row) ObserverB_PageSequence = read_csv('SI_Exp2_AlgoPartner_MainExp/01_ParticipantFiles/SI_PageSequence_' + str(int(self.session.config['subject_number'])+1) + '.csv', Row) # THIS IS A PLACEHOLDER FOR NOW demonstrator = read_csv('SI_Exp2_AlgoPartner_MainExp/01_ParticipantFiles/SI_Demonstrator_' + str(int(self.session.config['subject_number'])-1+self.id_in_group+3) + '.csv', Row) # THIS ALSO IS A PLACEHOLDER t = (self.round_number - 1) ObsA_this_trials_data = ObserverA_PageSequence[t] ObsB_this_trials_data = ObserverB_PageSequence[t] demonstrator_this_trials_data = demonstrator[t] # What is being shown for Obs A if ObsA_this_trials_data['choice_prediction_query'] == 1: ObsA_query_row1 = 'Which cell do you think the player will select next?' ObsA_query_row2 = '(Please click into the respective cell and then submit)' show_form_field = 1 else: ObsA_query_row1 = 'Wait' ObsA_query_row2 = '' show_form_field = 0 # What is being shown for Obs B if ObsB_this_trials_data['choice_prediction_query'] == 1: ObsB_query_row1 = 'Which cell do you think the player will select next?' ObsB_query_row2 = '(Please click into the respective cell and then submit)' # The following is a placerholder because I take the real demonstrators value and just add some small noise ObsB_highlight_index_row = np.clip(int(np.random.normal(demonstrator_this_trials_data['demonstrator_choice_index_row'], scale=1)), 0, 10) ObsB_highlight_index_column = np.clip(int(np.random.normal(demonstrator_this_trials_data['demonstrator_choice_index_column'], scale=1)), 0, 10) ObsB_show_form_field = 1 ObsB_show_guess_text = 'Observer B\'s prediction is shown in purple.' ObsB_time_to_decide = np.clip(np.random.lognormal(5000, 7000), 4000, 10000) else: ObsB_query_row1 = 'Wait' ObsB_query_row2 = '' ObsB_highlight_index_row = '' ObsB_highlight_index_column = '' ObsB_show_form_field = 0 ObsB_show_guess_text = '' ObsB_time_to_decide = 0 #print('ObsB_highlight_index_row', ObsB_highlight_index_row, type(ObsB_highlight_index_row)) return {'grid_data': grid_data, 'ObsB_highlight_index_row': ObsB_highlight_index_row, 'ObsB_highlight_index_column': ObsB_highlight_index_column, 'ObsA_query_row1':ObsA_query_row1, 'ObsA_query_row2':ObsA_query_row2, 'ObsB_query_row1':ObsB_query_row1, 'ObsB_query_row2':ObsB_query_row2, 'show_form_field':show_form_field, 'ObsB_show_form_field':ObsB_show_form_field, 'ObsB_show_guess_text': ObsB_show_guess_text, 'ObsB_time_to_decide':ObsB_time_to_decide} @staticmethod def live_method(player: Player, data): if player.id_in_group == 1: if data["predicted_choice"] == 'NA,NA': return {1: {"predicted_choice": '', "predicted_choice_row": '', "predicted_choice_column": ''}} # else: strings = data["predicted_choice"].split(',') return {1: {"predicted_choice":data["predicted_choice"], "predicted_choice_row":int(strings[0]), "predicted_choice_column":int(strings[1])}} # if player.id_in_group == 2: if data["predicted_choice"] == 'NA,NA': return {2: {"predicted_choice": '', "predicted_choice_row": '', "predicted_choice_column": ''}} # else: strings = data["predicted_choice"].split(',') #print('livesend success', data["predicted_choice"], type(data["predicted_choice"])) # for only Obs B query, [0] and [1] will return an N and an A return {2: {"predicted_choice":data["predicted_choice"], "predicted_choice_row":int(strings[0]), "predicted_choice_column":int(strings[1])}} # if player.id_in_group == 3: if data["predicted_choice"] == 'NA,NA': return {3: {"predicted_choice": '', "predicted_choice_row": '', "predicted_choice_column": ''}} # else: strings = data["predicted_choice"].split(',') #print('livesend success', data["predicted_choice"], type(data["predicted_choice"])) # for only Obs B query, [0] and [1] will return an N and an A return {3: {"predicted_choice":data["predicted_choice"], "predicted_choice_row":int(strings[0]), "predicted_choice_column":int(strings[1])}} # if player.id_in_group == 4: if data["predicted_choice"] == 'NA,NA': return {4: {"predicted_choice": '', "predicted_choice_row": '', "predicted_choice_column": ''}} # else: strings = data["predicted_choice"].split(',') #print('livesend success', data["predicted_choice"], type(data["predicted_choice"])) # for only Obs B query, [0] and [1] will return an N and an A return {4: {"predicted_choice":data["predicted_choice"], "predicted_choice_row":int(strings[0]), "predicted_choice_column":int(strings[1])}} # class choice_phase(Page): template_name = 'SI_Exp2_NoPartner_TrainingSequence/choice_phase.html' def vars_for_template(self): # this just gives the grid grid_numbers = np.empty((11, 11)) #print('grid_numbers', grid_numbers) grid_data = [] for row_idx, row in enumerate(grid_numbers): grid_row = [] #print('row_idx', row_idx) #print('row', row) for col_idx, value in enumerate(row): #print('col_idx', col_idx) #print('value', value) cell = {'value': value, 'row_index': row_idx, 'column_index': col_idx} grid_row.append(cell) grid_data.append(grid_row) #print('grid_data', grid_data) demonstrator = read_csv('SI_Exp2_AlgoPartner_MainExp/01_ParticipantFiles/SI_Demonstrator_' + str(int(self.session.config['subject_number'])-1+self.id_in_group+3) + '.csv', Row) ObserverA_PageSequence = read_csv('SI_Exp2_ObsB_TrainingSequence2/SI_Exp2_PageSequence_Training.csv', Row) ObserverB_PageSequence = read_csv('SI_Exp2_AlgoPartner_MainExp/01_ParticipantFiles/SI_PageSequence_' + str(int(self.session.config['subject_number'])+1) + '.csv', Row) # THIS IS A PLACEHOLDER FOR NOW t = (self.round_number - 1) ObsA_this_trials_data = ObserverA_PageSequence[t] ObsB_this_trials_data = ObserverB_PageSequence[t] if int(ObsA_this_trials_data['trial_type']) == 1 or int(ObsA_this_trials_data['trial_type']) == 2: ObsA_query_row1 = 'See player\'s selection' ObsA_query_row2 = '' this_trials_demonstrator_data = demonstrator[self.round_number - 1] highlight_index_row = this_trials_demonstrator_data['demonstrator_choice_index_row'] highlight_index_column = this_trials_demonstrator_data['demonstrator_choice_index_column'] ObsA_sees = True else: ObsA_query_row1 = '?' ObsA_query_row2 = '' highlight_index_row = np.NaN highlight_index_column = np.NaN ObsA_sees = False if int(ObsB_this_trials_data['trial_type']) == 1 or int(ObsB_this_trials_data['trial_type']) == 2: ObsB_query_row1 = 'See player\'s selection' ObsB_query_row2 = '' ObsB_sees = True else: ObsB_query_row1 = '?' ObsB_query_row2 = '' ObsB_sees = False return {'grid_data': grid_data, 'highlight_index_row': highlight_index_row, 'highlight_index_column': highlight_index_column, 'ObsA_query_row1':ObsA_query_row1, 'ObsA_query_row2':ObsA_query_row2, 'ObsB_query_row1':ObsB_query_row1, 'ObsB_query_row2':ObsB_query_row2, 'ObsA_sees':ObsA_sees, 'ObsB_sees':ObsB_sees} timeout_seconds = 6 class infer_reward(Page): template_name = 'SI_Exp2_NoPartner_TrainingSequence/infer_reward.html' form_model = 'player' form_fields = ['inferred_reward', 'RT_inferred_reward'] def error_message(self, values): ObsA_trials = read_csv('SI_Exp2_AlgoPartner_MainExp/01_ParticipantFiles/SI_PageSequence_' + str(int(self.session.config['subject_number'])-1+self.id_in_group) + '.csv', Row) t = (self.round_number - 2) ObsA_previous_trials_data = ObsA_trials[t] if int(ObsA_previous_trials_data['reward_inference_query']) == 1 : if values["inferred_reward"] is None or values["inferred_reward"] == '': return 'You must enter a value' def is_displayed(player: Player): #print("ROUND NUMBER:", player.round_number) # import the csv, #ALEX not if first trial ObsA_trials = read_csv('SI_Exp2_ObsB_TrainingSequence2/SI_Exp2_PageSequence_Training.csv', Player) t = (player.round_number - 2) #print('round number - 2', t) ObsA_previous_trials_data = ObsA_trials[t] #print('ObsA_previous_trials_data', ObsA_previous_trials_data) # this should be displayed on the current trial, if the reward inference query on the previous trial was... #print('show reward inf Obs A', int(ObsA_previous_trials_data['reward_inference_query']) == 1) #print('show reward inf Obs B', int(ObsB_previous_trials_data['reward_inference_query']) == 1) if int(ObsA_previous_trials_data['reward_inference_query']) == 1 : # if a reward inference should be made return True def vars_for_template(self): grid_numbers = np.empty((11, 11)) # Restructure data to include indices grid_data = [] for row_idx, row in enumerate(grid_numbers): grid_row = [] for col_idx, value in enumerate(row): cell = {'value': value, 'row_index': row_idx, 'column_index': col_idx} grid_row.append(cell) grid_data.append(grid_row) # need to identify the row and column that should be highlighted demonstrator = read_csv('SI_Exp2_AlgoPartner_MainExp/01_ParticipantFiles/SI_Demonstrator_' + str(int(self.session.config['subject_number'])-1+self.id_in_group+3) + '.csv', Row) ObserverA_PageSequence = read_csv('SI_Exp2_ObsB_TrainingSequence2/SI_Exp2_PageSequence_Training.csv', Row) ObserverB_PageSequence = read_csv('SI_Exp2_AlgoPartner_MainExp/01_ParticipantFiles/SI_PageSequence_' + str(int(self.session.config['subject_number'])+1) + '.csv', Row) # THIS IS A PLACEHOLDER FOR NOW t = (self.round_number - 2) ObsA_prev_trials_data = ObserverA_PageSequence[t] ObsB_prev_trials_data = ObserverB_PageSequence[t] c = (self.round_number - 1) ObsA_current_trials_data = ObserverA_PageSequence[c] ObsB_current_trials_data = ObserverB_PageSequence[c] # Get the "real" reward and grid index of demonstrator's choice and reward prev_trials_demonstrator_data = demonstrator[self.round_number - 2] prev_highlight_index_row = int(prev_trials_demonstrator_data['demonstrator_choice_index_row']) prev_highlight_index_column = int(prev_trials_demonstrator_data['demonstrator_choice_index_column']) demonstrator_reward = prev_trials_demonstrator_data['demonstrator_noisy_rescaled_reward']#grid_data[prev_highlight_index_row][prev_highlight_index_column]['value'] # What is shown for Obs A if int(ObsA_prev_trials_data['reward_inference_query']) == 1: ObsA_query_row1 = 'How many points do you think the player received for their previous selection (highlighted in light red)?' ObsA_query_row2 = '(the current selection is highlighted in yellow)' ObsA_show_guess = 'Observer A inferred a reward of: ' # This is important! The -2 indicates that we're getting the info from the trial before (-1 because counter starting at 1) previous_trials_demonstrator_data = demonstrator[self.round_number - 2] current_trials_demonstrator_data = demonstrator[self.round_number - 1] highlight_index_row = int(previous_trials_demonstrator_data['demonstrator_choice_index_row']) highlight_index_column = int(previous_trials_demonstrator_data['demonstrator_choice_index_column']) current_highlight_index_row = int(current_trials_demonstrator_data['demonstrator_choice_index_row']) current_highlight_index_column = int(current_trials_demonstrator_data['demonstrator_choice_index_column']) show_form_field = 1 elif int(ObsA_prev_trials_data['reward_inference_query']) == 0 and int(ObsA_prev_trials_data['trial_type']) != 3 and int(ObsA_current_trials_data['trial_type']) != 3: ObsA_query_row1 = 'Wait' ObsA_query_row2 = '' ObsA_show_guess = '' previous_trials_demonstrator_data = demonstrator[self.round_number - 2] current_trials_demonstrator_data = demonstrator[self.round_number - 1] highlight_index_row = int(previous_trials_demonstrator_data['demonstrator_choice_index_row']) highlight_index_column = int(previous_trials_demonstrator_data['demonstrator_choice_index_column']) current_highlight_index_row = int(current_trials_demonstrator_data['demonstrator_choice_index_row']) current_highlight_index_column = int(current_trials_demonstrator_data['demonstrator_choice_index_column']) show_form_field = 0 elif int(ObsA_prev_trials_data['reward_inference_query']) == 0 and int(ObsA_prev_trials_data['trial_type']) != 3 and int(ObsA_current_trials_data['trial_type']) == 3: ObsA_query_row1 = 'Wait' ObsA_query_row2 = '' ObsA_show_guess = '' previous_trials_demonstrator_data = demonstrator[self.round_number - 2] current_trials_demonstrator_data = demonstrator[self.round_number - 1] highlight_index_row = int(previous_trials_demonstrator_data['demonstrator_choice_index_row']) highlight_index_column = int(previous_trials_demonstrator_data['demonstrator_choice_index_column']) current_highlight_index_row = np.NaN current_highlight_index_column = np.NaN show_form_field = 0 elif int(ObsA_prev_trials_data['reward_inference_query']) == 0 and int(ObsA_prev_trials_data['trial_type']) == 3 and int(ObsA_current_trials_data['trial_type']) != 3: ObsA_query_row1 = 'Wait' ObsA_query_row2 = '' ObsA_show_guess = '' previous_trials_demonstrator_data = demonstrator[self.round_number - 2] current_trials_demonstrator_data = demonstrator[self.round_number - 1] highlight_index_row = np.NaN highlight_index_column = np.NaN current_highlight_index_row = int(current_trials_demonstrator_data['demonstrator_choice_index_row']) current_highlight_index_column = int(current_trials_demonstrator_data['demonstrator_choice_index_column']) show_form_field = 0 else: ObsA_query_row1 = 'Wait' ObsA_query_row2 = '' ObsA_show_guess = '' highlight_index_row = np.NaN highlight_index_column = np.NaN current_highlight_index_row = np.NaN current_highlight_index_column = np.NaN show_form_field = 0 # What is shown for Obs B if int(ObsB_prev_trials_data['reward_inference_query']) == 1: ObsB_query_row1 = 'How many points do you think the player received for their previous selection (highlighted in light red)?' ObsB_query_row2 = '(the current selection is highlighted in yellow)' ObsB_inferred_reward = np.clip(int(np.random.normal(demonstrator_reward, scale=1)), 0, 100) ObsB_show_guess = 'Observer B inferred a reward of: ' ObsB_time_to_decide = np.clip(np.random.lognormal(10000, 8000), 4000, 14000) else: ObsB_query_row1 = 'Wait' ObsB_query_row2 = '' ObsB_inferred_reward = '' ObsB_show_guess = '' ObsB_time_to_decide = 0 # When to show background boxes # don't show box if 3 if int(ObsA_current_trials_data['trial_type']) == 3: ObsA_sees = False else: ObsA_sees = True if int(ObsB_current_trials_data['trial_type']) == 3: ObsB_sees = False else: ObsB_sees = True return {'grid_data': grid_data, 'highlight_index_row': highlight_index_row, 'highlight_index_column': highlight_index_column, 'current_highlight_index_row': current_highlight_index_row, 'current_highlight_index_column': current_highlight_index_column, 'ObsA_query_row1':ObsA_query_row1, 'ObsA_query_row2':ObsA_query_row2, 'ObsB_query_row1':ObsB_query_row1, 'ObsB_query_row2':ObsB_query_row2, 'show_form_field':show_form_field, 'ObsB_inferred_reward':ObsB_inferred_reward, 'ObsA_show_guess':ObsA_show_guess, 'ObsB_show_guess':ObsB_show_guess, 'ObsA_sees':ObsA_sees, 'ObsB_sees':ObsB_sees, 'ObsB_time_to_decide':ObsB_time_to_decide} @staticmethod def live_method(player: Player, data): if player.id_in_group == 1: return {1: {"result":data["result"]}} if player.id_in_group == 2: return {2: {"result":data["result"]}} if player.id_in_group == 3: return {3: {"result":data["result"]}} if player.id_in_group == 4: return {4: {"result":data["result"]}} class predict_reward(Page): template_name = 'SI_Exp2_NoPartner_TrainingSequence/predict_reward.html' form_model = 'player' form_fields = ['predicted_reward', 'RT_predicted_reward'] def error_message(self, values): ObsA_trials = read_csv('SI_Exp2_AlgoPartner_MainExp/01_ParticipantFiles/SI_PageSequence_' + str(int(self.session.config['subject_number'])-1+self.id_in_group) + '.csv', Row) t = (self.round_number - 1) ObsA_previous_trials_data = ObsA_trials[t] if int(ObsA_previous_trials_data['reward_prediction_query']) == 1 : if values["predicted_reward"] is None or values["predicted_reward"] == '': return 'You must enter a value' def is_displayed(player: Player): ObsA_trials = read_csv('SI_Exp2_ObsB_TrainingSequence2/SI_Exp2_PageSequence_Training.csv', Player) #ObsB_trials = read_csv('SI_Exp2_AlgoPartner_MainExp/01_ParticipantFiles/SI_PageSequence_' + str(int(player.session.config['subject_number'])+1) + '.csv', Row) t = (player.round_number - 1) ObsA_this_trials_data = ObsA_trials[t] #ObsB_this_trials_data = ObsB_trials[t] #print('ObsA_this_trials_data', int(ObsA_this_trials_data['reward_prediction_query']) == 1) #print('ObsB_this_trials_data', int(ObsB_this_trials_data['reward_prediction_query']) == 1) return (int(ObsA_this_trials_data['reward_prediction_query']) == 1) def vars_for_template(self): grid_numbers = np.empty((11, 11)) #highlight_index_row = 1 # Row index of the cell to highlight #highlight_index_column = 2 # Column index of the cell to highlight # This block gives which choice should be highlighted demonstrator = read_csv('SI_Exp2_AlgoPartner_MainExp/01_ParticipantFiles/SI_Demonstrator_' + str(int(self.session.config['subject_number'])-1+self.id_in_group+3) + '.csv', Row) trials_demonstrator_data = demonstrator[self.round_number - 1] highlight_index_row = trials_demonstrator_data['demonstrator_choice_index_row'] highlight_index_column = trials_demonstrator_data['demonstrator_choice_index_column'] # Restructure data to include indices grid_data = [] for row_idx, row in enumerate(grid_numbers): grid_row = [] for col_idx, value in enumerate(row): cell = {'value': value, 'row_index': row_idx, 'column_index': col_idx} grid_row.append(cell) grid_data.append(grid_row) ObserverA_PageSequence = read_csv('SI_Exp2_ObsB_TrainingSequence2/SI_Exp2_PageSequence_Training.csv', Row) ObserverB_PageSequence = read_csv('SI_Exp2_AlgoPartner_MainExp/01_ParticipantFiles/SI_PageSequence_' + str(int(self.session.config['subject_number'])+1) + '.csv', Row) # THIS IS A PLACEHOLDER FOR NOW t = (self.round_number - 1) ObsA_this_trials_data = ObserverA_PageSequence[t] ObsB_this_trials_data = ObserverB_PageSequence[t] # Get the "real" reward and grid index of demonstrator's choice and reward current_trials_demonstrator_data = demonstrator[self.round_number - 1] current_highlight_index_row = int(current_trials_demonstrator_data['demonstrator_choice_index_row']) current_highlight_index_column = int(current_trials_demonstrator_data['demonstrator_choice_index_column']) demonstrator_reward = trials_demonstrator_data['demonstrator_noisy_rescaled_reward']#int(grid_data[current_highlight_index_row][current_highlight_index_column]['value']) # What is shown for Obs A # if trial type either full info or choice-only and Obs A asked a query, show choice on screen if int(ObsA_this_trials_data['reward_prediction_query']) == 1 and int(ObsA_this_trials_data['trial_type']) != 3: ObsA_query_row1 = 'How many points do you think the player will receive for this selection?' ObsA_query_row2 = '' show_form_field = 1 ObsA_show_guess = 'Observer A predicted a reward of: ' # if trial type either full info or choice-only, but only Obs B makes prediction (but choice should still be shown on screen) elif int(ObsA_this_trials_data['reward_prediction_query']) == 0 and int(ObsA_this_trials_data['trial_type']) != 3: ObsA_query_row1 = 'Wait' ObsA_query_row2 = '' show_form_field = 0 ObsA_show_guess = '' # if trial type reward-only (i.e. 3), no choice on screen elif int(ObsA_this_trials_data['reward_prediction_query']) == 1 and int(ObsA_this_trials_data['trial_type']) == 3: ObsA_query_row1 = 'How many points do you think the player will receive for their selection?' ObsA_query_row2 = '' current_highlight_index_row = np.NaN current_highlight_index_column = np.NaN show_form_field = 1 ObsA_show_guess = 'Observer A predicted a reward of: ' else: ObsA_query_row1 = 'Wait' ObsA_query_row2 = '' current_highlight_index_row = np.NaN current_highlight_index_column = np.NaN show_form_field = 0 ObsA_show_guess = '' # What is shown for Obs B if int(ObsB_this_trials_data['reward_prediction_query']) == 1 and int(ObsB_this_trials_data['trial_type']) != 3: ObsB_query_row1 = 'How many points do you think the player will receive for this selection?' ObsB_query_row2 = '' ObsB_show_guess = 'Observer B predicted a reward of: ' show_form_field_ObsB = 1 ObsB_time_to_decide = np.clip(np.random.lognormal(6000, 7000), 4000, 10000) # THIS IS A PLACEHOLDER. TAKING THE REAL REWARD VALUE AND PUTTING A NORMAL DISTRIBUTION ON IT ObsB_predicted_reward = np.clip(int(np.random.normal(demonstrator_reward, scale=1)), 0, 100) elif int(ObsB_this_trials_data['reward_prediction_query']) == 1 and int(ObsB_this_trials_data['trial_type']) == 3: ObsB_query_row1 = 'How many points do you think the player will receive for their selection?' ObsB_query_row2 = '' ObsB_show_guess = 'Observer B predicted a reward of: ' show_form_field_ObsB = 1 # THIS IS A PLACEHOLDER. TAKING THE REAL REWARD VALUE AND PUTTING A NORMAL DISTRIBUTION ON IT ObsB_predicted_reward = np.clip(int(np.random.normal(demonstrator_reward, scale=1)), 0, 100) ObsB_time_to_decide = np.clip(np.random.lognormal(6000, 7000), 4000, 10000) else: ObsB_query_row1 = 'Wait' ObsB_query_row2 = '' ObsB_show_guess = ' ' show_form_field_ObsB = 0 ObsB_predicted_reward = '' ObsB_time_to_decide = 0 # Determine the background boxes. 1 full-inf trial, 2 choice only, 3 reward only # Should have background box if choice was shown if int(ObsA_this_trials_data['trial_type']) == 1 or int(ObsA_this_trials_data['trial_type']) == 2: ObsA_sees = True else: ObsA_sees = False if int(ObsB_this_trials_data['trial_type']) == 1 or int(ObsB_this_trials_data['trial_type']) == 2: ObsB_sees = True else: ObsB_sees = False ObsB_trial_type = int(ObsB_this_trials_data['trial_type']) return {'grid_data': grid_data, 'current_highlight_index_row': current_highlight_index_row, 'current_highlight_index_column': current_highlight_index_column, 'ObsA_query_row1':ObsA_query_row1, 'ObsA_query_row2':ObsA_query_row2, 'ObsB_query_row1':ObsB_query_row1, 'ObsB_query_row2':ObsB_query_row2, 'show_form_field':show_form_field, 'show_form_field_ObsB':show_form_field_ObsB, 'ObsB_predicted_reward': ObsB_predicted_reward, 'ObsA_show_guess':ObsA_show_guess, 'ObsB_show_guess':ObsB_show_guess, 'ObsA_sees':ObsA_sees, 'ObsB_sees':ObsB_sees, 'ObsB_trial_type':ObsB_trial_type, 'ObsB_time_to_decide':ObsB_time_to_decide} # live pages consists of 3 parts: py, once JS sends data, the other receives data # in the html file I'll have an input field for the form_fields. # # id is what will be used for JS, name has to be exactly the same as in python page file @staticmethod def live_method(player: Player, data): if player.id_in_group == 1: return {1: {"result":data["result"]}} if player.id_in_group == 2: return {2: {"result":data["result"]}} if player.id_in_group == 3: return {3: {"result":data["result"]}} if player.id_in_group == 4: return {4: {"result":data["result"]}} class reward_phase(Page): template_name = 'SI_Exp2_NoPartner_TrainingSequence/reward_phase.html' def vars_for_template(self): demonstrator = read_csv('SI_Exp2_AlgoPartner_MainExp/01_ParticipantFiles/SI_Demonstrator_' + str(int(self.session.config['subject_number'])-1+self.id_in_group+3) + '.csv', Row) this_trials_demonstrator_data = demonstrator[self.round_number - 1] # This block gives which choice should be highlighted highlight_index_row = this_trials_demonstrator_data['demonstrator_choice_index_row'] highlight_index_column = this_trials_demonstrator_data['demonstrator_choice_index_column'] grid_data = [] # as input take the whole reward matrix from the current trial # PROBLEM: Otree imports the demonstrator_reward matrix into a string (but it seems like I can't import it as a list/array) demonstrator_rewards_list = this_trials_demonstrator_data['demonstrator_noisy_rescaled_all_rewards'].replace("[", "").replace("]","") # int() converts to required integers res = [int(ele) for ele in demonstrator_rewards_list.split()] demonstrator_rewards_matrix = np.array(res) demonstrator_rewards_matrix = np.reshape(demonstrator_rewards_matrix, (11, 11)) # this is relevant to identify whether reward is shown in grid (full-info trial) or just below (in case of reward-info trial) or not at all ObserverA_PageSequence = read_csv('SI_Exp2_ObsB_TrainingSequence2/SI_Exp2_PageSequence_Training.csv', Row) ObserverB_PageSequence = read_csv('SI_Exp2_AlgoPartner_MainExp/01_ParticipantFiles/SI_PageSequence_' + str(int(self.session.config['subject_number'])+1) + '.csv', Row) # THIS IS A PLACEHOLDER FOR NOW t = (self.round_number - 1) ObsA_this_trials_data = ObserverA_PageSequence[t] ObsB_this_trials_data = ObserverB_PageSequence[t] # here I need to get the value that corresponds to the choice row and column index for row_idx, row in enumerate(demonstrator_rewards_matrix): grid_row = [] for col_idx, value in enumerate(row): if int(ObsA_this_trials_data['trial_type']) != 2: reward = demonstrator_rewards_matrix[highlight_index_row][highlight_index_column] else: reward = '' cell = {'reward': reward, 'row_index': row_idx, 'column_index': col_idx} grid_row.append(cell) grid_data.append(grid_row) # What is shown for Obs A if int(ObsA_this_trials_data['trial_type']) == 2: # if choice only trial, show 'wait' ObsA_query_row1 = '?' ObsA_query_row2 = '' ObsA_reward ='?' ObsA_sees = False else: ObsA_query_row1 = 'See player\'s points' ObsA_query_row2 = '' ObsA_sees = True # I have this in there 2x because I don't know any better. I need it within cell to be referenced in grid, and just the one value to be referenced below grid ObsA_reward = demonstrator_rewards_matrix[highlight_index_row][highlight_index_column] # What is shown for Obs B if int(ObsB_this_trials_data['trial_type']) == 2: # if choice only trial, show 'wait' ObsB_query_row1 = '?' ObsB_query_row2 = '' ObsB_sees = False else: ObsB_query_row1 = 'See player\'s points' ObsB_query_row2 = '' ObsB_sees = True ObsB_trial_type = int(ObsB_this_trials_data['trial_type']) #print('int(ObsA_this_trials_data[trial_type])', int(ObsA_this_trials_data['trial_type'])) return {'grid_data': grid_data, 'highlight_index_row': highlight_index_row, 'highlight_index_column': highlight_index_column, 'ObsA_reward_below':ObsA_reward, 'trial_type':int(ObsA_this_trials_data['trial_type']), 'ObsA_query_row1':ObsA_query_row1, 'ObsA_query_row2':ObsA_query_row2, 'ObsB_query_row1':ObsB_query_row1, 'ObsB_query_row2':ObsB_query_row2, 'ObsA_sees':ObsA_sees, 'ObsB_sees':ObsB_sees, 'ObsB_trial_type':ObsB_trial_type} timeout_seconds = 6 # CONTINUE WITH INFER CHOICE HTML class infer_choice(Page): template_name = 'SI_Exp2_NoPartner_TrainingSequence/infer_choice.html' # Define form fields form_model = 'player' form_fields = ['inferred_choice', 'RT_inferred_choice'] def is_displayed(player: Player): ObsA_trials = read_csv('SI_Exp2_ObsB_TrainingSequence2/SI_Exp2_PageSequence_Training.csv', Player) #ObsB_trials = read_csv('SI_Exp2_AlgoPartner_MainExp/01_ParticipantFiles/SI_PageSequence_' + str(int(player.session.config['subject_number'])+1) + '.csv', Row) t = (player.round_number - 1) ObsA_this_trials_data = ObsA_trials[t] #ObsB_this_trials_data = ObsB_trials[t] return (int(ObsA_this_trials_data['choice_inference_query']) == 1) def vars_for_template(self): # THIS WILL JUST GIVE THE GRID NUMBERS TO HTML grid_numbers = np.empty((11, 11)) #grid_number = my_array.tolist() grid_data = [] for row_idx, row in enumerate(grid_numbers): grid_row = [] for col_idx, value in enumerate(row): cell = {'value': value, 'row_index': row_idx, 'column_index': col_idx} grid_row.append(cell) grid_data.append(grid_row) # IF I WANT TO INCLUDE DEMONSTRATOR: # This gets the reward from the current trial and shows it on screen demonstrator = read_csv('SI_Exp2_AlgoPartner_MainExp/01_ParticipantFiles/SI_Demonstrator_' + str(int(self.session.config['subject_number'])-1+self.id_in_group+3) + '.csv', Row) #str(int(self.session.config['subject_number'])) this_trials_demonstrator_data = demonstrator[self.round_number-1] ObserverA_PageSequence = read_csv('SI_Exp2_ObsB_TrainingSequence2/SI_Exp2_PageSequence_Training.csv', Row) ObserverB_PageSequence = read_csv('SI_Exp2_AlgoPartner_MainExp/01_ParticipantFiles/SI_PageSequence_' + str(int(self.session.config['subject_number'])+1) + '.csv', Row) # THIS IS A PLACEHOLDER FOR NOW t = (self.round_number - 1) ObsA_this_trials_data = ObserverA_PageSequence[t] ObsB_this_trials_data = ObserverB_PageSequence[t] # What is shown for Obs A if int(ObsA_this_trials_data['choice_inference_query']) == 1: ObsA_query_row1 = 'Which cell do you think the player selected to receive ' + str(int(this_trials_demonstrator_data['demonstrator_noisy_rescaled_reward'])) + ' points?' ObsA_query_row2 = '(Please click into the respective cell and then submit)' show_form_field = 1 demo_reward_for_html = {'value': this_trials_demonstrator_data['demonstrator_noisy_rescaled_reward']} else: ObsA_query_row1 = 'Wait' ObsA_query_row2 = '' show_form_field = 0 demo_reward_for_html = {'value': '?'} # What is shown for Obs B if int(ObsB_this_trials_data['choice_inference_query']) == 1: if (int(ObsA_this_trials_data['choice_inference_query']) == 1) or (int(ObsA_this_trials_data['choice_inference_query']) == 3): ObsB_query_row1 = 'Which cell do you think the player selected to receive ' + str(int(this_trials_demonstrator_data['demonstrator_noisy_rescaled_reward'])) + ' points?' else: ObsB_query_row1 = 'Which cell do you think the player selected to receive ? points?' ObsB_query_row2 = '(Please click into the respective cell and then submit)' # The following is a placerholder because I take the real demonstrators value and just add some small noise ObsB_inf_highlight_index_row = np.clip(int(np.random.normal(this_trials_demonstrator_data['demonstrator_choice_index_row'], scale=1)), 0, 10) ObsB_inf_highlight_index_column = np.clip(int(np.random.normal(this_trials_demonstrator_data['demonstrator_choice_index_column'], scale=1)), 0, 10) ObsB_show_guess_text = 'Observer B\'s prediction is shown in purple.' ObsB_show_form_field = 1 ObsB_time_to_decide = np.clip(np.random.lognormal(6000, 7000), 4000, 10000) else: ObsB_query_row1 = 'Wait' ObsB_query_row2 = '' ObsB_inf_highlight_index_row = '' ObsB_inf_highlight_index_column = '' ObsB_show_form_field = 0 ObsB_show_guess_text = '' ObsB_time_to_decide = 0 # Determine the background boxes. 1 full-inf trial, 2 choice only, 3 reward only # Should have background box if reward was presented as choice inference follows reward if int(ObsA_this_trials_data['trial_type']) == 2: ObsA_sees = False else: ObsA_sees = True if int(ObsB_this_trials_data['trial_type']) == 2: ObsB_sees = False else: ObsB_sees = True #return {'grid_number': grid_number, 'demo_reward_for_html':demo_reward_for_html, 'show_form_field':show_form_field, # 'ObsA_query_row1':ObsA_query_row1, 'ObsA_query_row2':ObsA_query_row2, # 'ObsB_query_row1':ObsB_query_row1, 'ObsB_query_row2':ObsB_query_row2} return {'grid_data': grid_data, 'demo_reward_for_html':demo_reward_for_html, 'ObsB_inf_highlight_index_row': ObsB_inf_highlight_index_row, 'ObsB_inf_highlight_index_column': ObsB_inf_highlight_index_column, 'ObsA_query_row1':ObsA_query_row1, 'ObsA_query_row2':ObsA_query_row2, 'ObsB_query_row1':ObsB_query_row1, 'ObsB_query_row2':ObsB_query_row2, 'show_form_field':show_form_field, 'ObsB_show_form_field':ObsB_show_form_field, 'ObsB_show_guess_text': ObsB_show_guess_text, 'ObsA_sees':ObsA_sees, 'ObsB_sees':ObsB_sees, 'ObsB_time_to_decide':ObsB_time_to_decide} @staticmethod def live_method(player: Player, data): if player.id_in_group == 1: if data["inferred_choice"] == 'NA,NA': return {1: {"inferred_choice": '', "inferred_choice_row": '', "inferred_choice_column": ''}} # else: strings = data["inferred_choice"].split(',') #print('livesend success', data["inferred_choice"], type(data["inferred_choice"])) # for only Obs B query, [0] and [1] will return an N and an A return {1: {"inferred_choice":data["inferred_choice"], "inferred_choice_row":int(strings[0]), "inferred_choice_column":int(strings[1])}} # if player.id_in_group == 2: if data["inferred_choice"] == 'NA,NA': return {2: {"inferred_choice": '', "inferred_choice_row": '', "inferred_choice_column": ''}} # else: strings = data["inferred_choice"].split(',') #print('livesend success', data["inferred_choice"], type(data["inferred_choice"])) # for only Obs B query, [0] and [1] will return an N and an A return {2: {"inferred_choice":data["inferred_choice"], "inferred_choice_row":int(strings[0]), "inferred_choice_column":int(strings[1])}} # if player.id_in_group == 3: if data["inferred_choice"] == 'NA,NA': return {3: {"inferred_choice": '', "inferred_choice_row": '', "inferred_choice_column": ''}} # else: strings = data["inferred_choice"].split(',') return {3: {"inferred_choice":data["inferred_choice"], "inferred_choice_row":int(strings[0]), "inferred_choice_column":int(strings[1])}} # if player.id_in_group == 4: if data["inferred_choice"] == 'NA,NA': return {4: {"inferred_choice": '', "inferred_choice_row": '', "inferred_choice_column": ''}} # else: strings = data["inferred_choice"].split(',') return {4: {"inferred_choice":data["inferred_choice"], "inferred_choice_row":int(strings[0]), "inferred_choice_column":int(strings[1])}} # class finished(Page): template_name = 'SI_Exp2_NoPartner_TrainingSequence/finished.html' # Define form fields form_model = 'player' def is_displayed(player: Player): if player.round_number == 10: return True page_sequence = [empty_grid, predict_choice, choice_phase, infer_reward, predict_reward, reward_phase, infer_choice, finished]