from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range ) import string import random import numpy as np import collections import pandas as pd author = 'Michael Rojek-Giffin' doc = """ Your app description """ class Constants(BaseConstants): name_in_url = 'my_Nback' players_per_group = None N = 2 # these parameters are from Kale et al., 2007 num_rounds = 48 N_stream = ('B', 'F', 'K', 'H', 'M', 'Q', 'R', 'X') class Subsession(BaseSubsession): pass # N_target = models.CharField() # def before_session_starts(self): # ## This is where I create the array for the N-back that has # ## each letter used as target exactly once # # This stuff assigns each letter as a target # self.N_target = np.repeat(Constants.N_stream, 6, axis=0) # random.shuffle(self.N_target) # my_count = -1 # N_range = list(range(Constants.N, len(self.N_target))) # N_range_tracker = [] # for NN in Constants.N_stream: # my_count = my_count + 1 # # choose random trial to have the target # temp_idx = random.choice(N_range) # # make sure that I don't overwrite any random target indices # while (temp_idx in N_range_tracker) or (temp_idx - Constants.N in N_range_tracker): # temp_idx = random.choice(N_range) # else: # N_range_tracker.extend([temp_idx, (temp_idx - Constants.N)]) # # self.N_target[[temp_idx, (temp_idx - Constants.N)]] = NN # # print(NN) # # # Because the above loop randomly assigns letters wherever no target is indexed, some duplicates may randomly occur. # # This loops counts how many duplicates I have and collects their indices in N_targets # my_count = -1 # one_timer = pd.DataFrame(columns=['Letter', 'row']) # indx_count = -1 # for NN in self.N_target: # my_count = my_count + 1 # # runs through each row up until end - Nth row # if my_count < (len(self.N_target) - Constants.N): # if self.N_target[my_count] == NN and self.N_target[my_count + Constants.N] == NN: # indx_count = indx_count + 1 # one_timer.loc[indx_count] = [NN, my_count] # # # This loop removes all duplicates so that I have exactly one target per letter # for NN in Constants.N_stream: # tar_idx = one_timer[one_timer['Letter'] == NN]["row"] # for ii in range(0, len(tar_idx) - 1): # idx_to_change = int(one_timer.loc[tar_idx.index[ii], 'row']) # while self.N_target[idx_to_change] == self.N_target[idx_to_change + Constants.N] or self.N_target[idx_to_change] == \ # self.N_target[idx_to_change - Constants.N]: # self.N_target[idx_to_change] = random.choice(Constants.N_stream) # # N_target_copy = self.N_target # N_temporary = [] # for NN in N_target_copy: # N_temporary = N_temporary + list(NN) # # self.N_target = N_temporary # for p in self.get_players(): # if self.round_number == 1: # p.N_count = p.round_number+1 # else: # p.N_count = p.in_round(self.round_number - 1).N_count + 4 # if self.round_number <= Constants.N: # for p in self.get_players(): # p.N_now = random.choice(Constants.N_stream) ## This is where I create the array for the N-back that has ## each letter used as target exactly once # This stuff assigns each letter as a target N_target = np.repeat(Constants.N_stream, 6, axis=0) random.shuffle(N_target) my_count = -1 N_range = list(range(Constants.N,len(N_target))) N_range_tracker = [] for NN in Constants.N_stream: my_count = my_count+1 # choose random trial to have the target temp_idx = random.choice(N_range) # make sure that I don't overwrite any random target indices while (temp_idx in N_range_tracker) or (temp_idx-Constants.N in N_range_tracker): temp_idx = random.choice(N_range) else: N_range_tracker.extend([temp_idx, (temp_idx - Constants.N)]) N_target[[temp_idx, (temp_idx-Constants.N)]] = NN # print(NN) # Because the above loop randomly assigns letters wherever no target is indexed, some duplicates may randomly occur. # This loops counts how many duplicates I have and collects their indices in N_targets my_count = -1 one_timer = pd.DataFrame(columns = ['Letter', 'row']) indx_count = -1 for NN in N_target: my_count = my_count + 1 # runs through each row up until end - Nth row if my_count < (len(N_target)-Constants.N): if N_target[my_count] == NN and N_target[my_count+Constants.N] == NN: indx_count = indx_count+1 one_timer.loc[indx_count] = [NN, my_count] # This loop removes all duplicates so that I have exactly one target per letter for NN in Constants.N_stream: tar_idx = one_timer[one_timer['Letter'] == NN]["row"] for ii in range(0, len(tar_idx)-1): idx_to_change = int(one_timer.loc[tar_idx.index[ii], 'row']) while N_target[idx_to_change] == N_target[idx_to_change + Constants.N] or N_target[idx_to_change] == N_target[idx_to_change - Constants.N]: N_target[idx_to_change] = random.choice(Constants.N_stream) # class Group(BaseGroup): pass class Player(BasePlayer): N_answer = models.BooleanField() N_correct = models.CharField() N_now = models.CharField() N_back = models.CharField() N_target = models.CharField() N_count = models.IntegerField() def N_now_now(self): # this was commented out after I wrote the above stuff under subsession for exact targets # self.N_now = random.choice(Constants.N_stream) # # Here I had to get creative, don't need it anymore # if self.round_number == 1 or self.round_number == 2: # self.N_count = self.round_number+1 # else: # self.N_count = self.in_round(self.round_number - 1).N_count + 4 self.N_now = N_target[(self.round_number - 1)] # def N_now(self): # return random.choice(Constants.N_stream[0:2]) def prev_N(self): self.N_back = self.in_round(self.round_number - Constants.N).N_now def N_correct_giver(self): if self.N_now == self.in_round(self.round_number - Constants.N).N_now and self.N_answer == True: self.N_correct = 'Correct_Accept' elif self.N_now != self.in_round(self.round_number - Constants.N).N_now and self.N_answer == False: self.N_correct = 'Correct_Reject' elif self.N_now != self.in_round(self.round_number - Constants.N).N_now and self.N_answer == True: self.N_correct = 'Incorrect_Accept' elif self.N_now == self.in_round(self.round_number - Constants.N).N_now and self.N_answer == False: self.N_correct = 'Incorrect_Reject' # def get_N_back(self): # self.N_back = self.in_round(self.round_number - N).N_now