function DATA = test_exp(subject)
% Cogent demo experimental script
% expects the input 'subject' (string variable),
% runs an experiment,
% and returns the data in the strucure DATA
% written by christian ruff december 2006

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% change into directory containing experimental files
cd('C:\test_experiment\exp_files');
format bank;            % this improves readability of matlab number outputs

% This program can be run from the command line, specifying the subject's name:
% e.g.  >> test_exp( 'Elliot' )
% Alternatively it can be run without parameters, just by hitting F5 (RUN).
% In this case, data are saved to a default file 'TEST.MAT' and 'TEST.log'.
%
if nargin == 0          % 'nargin' returns the number of parameters specified by the user
    subject = 'TEST';   % if there were no parameters, just use a default subject name

elseif exist( subject ,'file')~=0;    % otherwise (if there was a subject specified)...
                                      % check whether a file with that name exists already
    disp('file for this subject exists already! aborting...')
    clear all; return;  % abort experiment, rather than overwrite existing data!!!
end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Set up data structure for control and logging of experiment
% This structure should contain every detail necessary to reconstruct the
% sequence and timing of the experiment, and the responses.
% It's convenient to keep all the relevant experimental parameters together near
% the top of the script.

% subject details
DATA.subject    = subject;

% when was the script started?
DATA.when_start = datestr(now,30);

% location of input file containing list of stimuli
DATA.inputList = 'C:\test_experiment\exp_files\inputList.txt';

% timing of trials
DATA.dur_pict   = 1000; % presentation time of stimulus (ms)
DATA.dur_resp   = 2000; % duration after offset of stimulus in which subject has time to respond (ms)
DATA.ITI        = 1000; % inter-trial interval (ms)

% read in input file containing a list of stimuli
% TEXTREAD reads from the inputList file. Here it expects to find two columns:
% ('%d') one column of decimal condition codes -> read into condition_codes variable, then
% ('%s') a column of strings indicating the filenames of pictures -> stimulusFile variable
[DATA.condition_codes DATA.stimulus] = textread( DATA.inputList , '%d%s');

% the total number of pictures to be presented determines the number of trials
DATA.n_trials = length(DATA.condition_codes);

% initialise random number generator
% It is absolutely crucial to do this before calling any other randomizing
% functions (otherwise you get the same sequence each time you start MATLAB) !!!!!!
rand('seed',sum(100*clock));    % seeds the random number generator with the clock time

% create a randomized vector specifying the order of stimuli
DATA.random_order = randperm(DATA.n_trials);    % randperm generates a random sequence of 1 to n non-repeating digits

% create data strucure for experiment, used in storing data for each trial
DATA.exp_data = zeros(DATA.n_trials,7);            % initialize data array
DATA.exp_data_columns = {'condition','stimulus','time_present','time_keypress','key','RT','corr'};
% this helps remember what the data mean!

% update the randomised condition codes and picture codes in the DATA
DATA.exp_data(:,1) = DATA.condition_codes(DATA.random_order);
DATA.exp_data(:,2) = DATA.random_order;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% COGENT: CONFIGURATION
% display parameters
screenMode = 0;                 % 0 for small window, 1 for full screen, 2 for second screen if attached
screenRes = 2;                  % 800 x 600 resolution
white = [1 1 1];                % foreground colour (optional)
black = [0 0 0];                % background colour (optional)
fontName = 'Helvetica'; fontSize = 20; % font parameters (optional)
number_of_buffers = 5;          % how many offscreen buffers to create

% call config_... to set up cogent environment, before starting cogent
config_display(screenMode, screenRes, black ,white, fontName, fontSize, number_of_buffers);   % open graphics window
config_log( subject );          % open log file with subject's name
config_sound(2,16,44100,10);    % sound configuration: stereo/mono, number of bits, sample frequency, number of buffers
config_keyboard;                % this enables collection of keyboard responses

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% START COGENT MODE: this hands control to cogent, and starts cogent timing
start_cogent; % time is now on zero

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% EXECUTE COGENT COMMANDS

% load feedback sounds
loadsound('correct.wav',1);                 % load correct wav file into buffer 1
loadsound('wrong.wav',2);                   % load wrong wav file into buffer 2

% put instruction text into the screen buffer 1 (this doesn't display it yet)
preparestring('Hello - Welcome to the experiment!',1,0,100);
preparestring('Press <space> to start or <esc> to abort!',1,0,0);

% prepare fixation cross in middle of buffer 2  (this doesn't display it yet)
preparestring('+',2);

% now show buffer 1 with instruction text
DATA.t_first_screen = drawpict(1);

% define the keys for the subject's responses
keys         = getkeymap;                   % getkeymap command outputs a list of codes assigned to each key by cogent
DATA.controlKeys = [keys.Space keys.Escape];     % define key codes for space and escape for controlling program
DATA.key_famous     = keys.F;               % key for Famous
DATA.key_nonfamous  = keys.N;               % key for Non-famous
[k,t,n] = waitkeydown(inf, DATA.controlKeys);    % wait for ever ('inf') until one of the control keys is pressed
if k(1) == keys.Escape                      % if escape is pressed, abort experiment
   logstring('...aborted');                 % print out error message and write to log
   stop_cogent;                             % exits Cogent mode
   clear all;
   return;                                  % exit from this function
end


% now start trial loop
DATA.t_start_experiment = time;             % record the time of the beginning of the trial sequence

% trial loop: continue until maximum number of trials is reached
for trial = 1 : DATA.n_trials

    trial_start             = time;             % record the current time for trial timing

    % trial starts with a fixation cross, from buffer 2
    drawpict(2);

    % pick the next value from the randomized sequence defined previously
    which_row = DATA.random_order(trial);

    % this value is then used as an index to select the stimuli and their corresponding condition codes
    condition = DATA.condition_codes(which_row);      % pick the condition code for this trial using the randomized index
    stimulus = DATA.stimulus{which_row};              % get the stimulus for this trial using the randomized index.
    % NOTE the use of braces {which_trial} ...
    % The next statement (loadpict) expects a character array as input. But DATA.stimulus contains a cell array. Indexing this with normal
    % brackets will just return one of the cells in this array:
    % DATA.stimulus(which_trial) -> 'stimulusName'. This will generate an error if used in loadpict.
    % To actually extract the string inside the cell, use braces instead
    % DATA.stimulus{which_trial} -> stimulusName

   % load picture and fixation cross on top of it into buffer 3
   loadpict(stimulus, 3);
   preparestring('+',3);

   % wait for the Inter-Trial Interval to end
   wait(DATA.ITI)
   % we could also use 'waituntil( current_time + DATA.ITI )'; this would take into
   % account the delay of loading the pictures etc. since the trial began

   % clear keyboard buffer to avoid garbage from previous keypresses
   clearkeys;   % cogent will store all keypresses from now on until 'readkeys' below

   % show picture in buffer 3
   time_present = drawpict(3);  % put up picture and record the time at which this happens

   % COGENT logging
   logstring(['trial ' num2str(trial) ', condition ' num2str(condition) ', picture ' stimulus]);

   % wait until end of presentation time, then remove picture
   wait( DATA.dur_pict );
   % We could also use waituntil( time_present + DATA.dur_pict ) if exact timing mattered;

   drawpict(4); % put up blank display created by default in buffer 4

   % wait a period for subjects to respond, then read responses and log them
   wait( DATA.dur_resp );
   % here we could also use waituntil( time_present + DATA.dur_pict + DATA.dur_resp) if exact timing mattered;

   readkeys;    % this command retrieves all keyboard events since the last call to clear keys above
   [k,t,n] = getkeydown([DATA.key_famous DATA.key_nonfamous 52]);   % this command outputs all keydown events for the specified keys
   % -> k: key value, t: time, n: number of keypresses

   % logging: columns 'condition','stimulus','time_present','time_keypress','key','RT','corr'
   DATA.exp_data(trial,1) = condition;                              % condition code
   DATA.exp_data(trial,2) = which_row;                              % which row of the input file
   DATA.exp_data(trial,3) = time_present;                           % time at which stimulus was presented

   if isempty(k)    % if there was no key response record dummy values
       DATA.exp_data(trial,[4:7]) = -99; % no response
       logstring('---'); % cogent log

   else             % if there was a key response record data
       DATA.exp_data(trial,4) = t(1);                               % time of first key onset
       DATA.exp_data(trial,5) = k(1);                               % key code of first keypress
       DATA.exp_data(trial,6) = t(1) - DATA.exp_data(trial,3);      % Response Time

       % determine if response was correct
       if (condition == 1 & DATA.exp_data(trial,5) == DATA.key_famous) | ...        % "if we're in the first condition and the famous key was pressed... or...
               (condition == 2 & DATA.exp_data(trial,5) == DATA.key_nonfamous) ...  % ... if we're in the second condition and the non-famous key was pressed ... then
           DATA.exp_data(trial,7) = 1;                                              % ... set the value in the 'correct' column to 1"
       end
       % write out response values to cogent log and also command window
       logstring(['response ' num2str(k(1)) ', RT ' num2str(DATA.exp_data(trial,6)) ', corr ' num2str(DATA.exp_data(trial,7))]);
   end

   % check for abort
   if any( k==52 )                          % "are any of the key-codes recorded in k equal to 52 (escape key)?"
       logstring('... aborted');            % write error to log
       stop_cogent; clear all;              % if so, abort
       return;                              % exit this program
   end


   % give feedback
   if DATA.exp_data(trial,7) == 1           % if this trial was correct
       playsound(1);                        % play 'correct' sound
   else
       playsound(2);                        % else play 'error' sound
   end

   % save data
   save( subject, 'DATA' );            % save the whole structure to the subject's data file

end
n_correct = sum( DATA.exp_data(:,end)==1 ); % counts up the correct trials while ignoring -99 dummies
p_correct = ( n_correct / DATA.n_trials ) * 100;    % calculate percentage of correct out of the total number of trials
logstring(['Percent Correct ' num2str(p_correct)]);  % log this

% end of block message to subject
preparestring('Thank you',5,0,100);
preparestring(['You were correct on ' num2str(p_correct) ' percent of trials!'],5,0,0);
drawpict(5);
wait(3000);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Return to MATLAB mode
stop_cogent;

clear all;

return