%_______________________________________________________________________
%
% Configuration for running dotsExperiment
%_______________________________________________________________________
%
% Output
%
% dotInfo | configuration for random dots experiment (struct)
%_______________________________________________________________________
%
function dotInfo = createDotInfo_JQK_170327

    dotInfo.trialsPerAtt = 32; % should be around 22 minutes with current timing (30 with confidence)
    dotInfo.numOfAtt = 4; % fixed in paradigm
    dotInfo.totalTrials = dotInfo.trialsPerAtt*dotInfo.numOfAtt;
    
    dotInfo.dirAttentionRate = .5; % ratio of directed attention vs. wholistic attention trials (same for each attribute)
    
    dotInfo.durCue = 2; % duration of cue
    dotInfo.durPres = .5; % duration of presentation
    dotInfo.durResp = 2.5; % duration of question
    dotInfo.durConf = 2; % duration of confidence
    
    dotInfo.feedback = 0; % don't give feedback

    %   dotInfo.introNumTrial = 10; % number of introduction trials per mode  
    %   dotInfo.winSize = 4; % number of trials for short-term average accuracy
    %   dotInfo.longWinSize = 8; % number of trials for mid-term average accuracy
    %   dotInfo.minCoh = 0; % minimum coherence value
    %   dotInfo.maxCoh = 800; %  maximum coherence value
    %   dotInfo.coh = 800; % coherence starting value for introduction
    %   dotInfo.targetAcc = 0.75; % targeted average accuracy for task
    
    dotInfo.dirSet          = [180, 0]; % dots in left or right direction
    dotInfo.numDotField     = 1; % show a single dot patches on screen
    dotInfo.apXYD           = [0 0 130]; % coordinates and diameter of aperture
    dotInfo.speed           = [50]; % speed of dot motion
    dotInfo.trialtype       = [2 1 1]; % reaction time, not relevant, keyboard
    dotInfo.dotSize         = 3; % dot size in pixels
    dotInfo.maxDotTime      = 2; % maximum duration of moving dots
    dotInfo.fixXY           = [0 0]; % fixation coordinates
    dotInfo.fixDiam         = 2; % fixation diameter
    dotInfo.fixColor        = [255 0 0]; % red fixation dot
    dotInfo.fixMinTime      = 0.75; % minimum fixation
    dotInfo.fixMaxTime      = 1.25; % maximum fixation
    dotInfo.maxDotsPerFrame = 300; % depends on graphics card
    dotInfo.fixTime         = 2; % JQK: fixed onset fixation time

    %dotInfo.ContrastLevels   = [0 .25 .5 1];
    %dotInfo.contrastBlocks   = 6;
    %dotInfo.breakTime        = 15; % break after blocks in seconds
  
    %dotInfo.cohLevels       = [250, 350, 500, 700];
    %dotInfo.timeTarget      = .3; % target time in s
    %dotInfo.timeNontarget   = [.3, .3, .3]; % target time in s
    %dotInfo.timeTarget      = 1.9; % target time in s
    %dotInfo.timeNontarget   = [3.6, 6.6, 8.4]; % target time in s
    %dotInfo.repPerStim      = 6;
    
    % BG info
    %dotInfo.percentOfBG = .001; % percentage of all display dots that are randomly replaced
    
    % update frequency of on-screen content
    
    dotInfo.Hz_BG   = 10; % background dots
    dotInfo.Hz_RDM  = 60; % kinematogram
    
    % multi-attribute task
    
    dotInfo.MAT.percAtt1 = .65;
    dotInfo.MAT.percAtt2 =  1-dotInfo.MAT.percAtt1; % For each attribute, the relative amount of dots for each attribute option is the same.
    dotInfo.MAT.color = [255 255 255; 255 215 0]; % define dot color
    dotInfo.MAT.coherence = 1;  % define dot movement (coherence) [useless now!]
    dotInfo.MAT.direction = [180 0]; % left and right
    dotInfo.MAT.size = [5 8]; % define dot size
    dotInfo.MAT.luminance = [.4 .8]; % define dot luminance
    dotInfo.MAT.attNames = {'color'; 'direction'; 'size'; 'luminance'};
    dotInfo.MAT.attNamesDE = {'Farbe'; 'Richtung'; 'Größe'; 'Helligkeit'};

    %% Keyboard responses
    % Use OS X keyboard naming scheme across all plattforms
    % Otherwise LeftControl/RightControl are not recognized
    KbName('UnifyKeyNames');

    if ismac % Mac keyboard
    dotInfo.keyLeft = KbName('LeftGUI'); % left cmd when dots moving to left
    dotInfo.keyRight = KbName('RightGUI'); % right cmd when dots moving to right
    else % PC keyboard
    dotInfo.keyLeft = KbName('LeftControl'); % left ctrl when dots moving to left
    dotInfo.keyRight = KbName('RightControl'); % right ctrl when dots moving to right
    end

    dotInfo.keyModifier = KbName('LeftAlt'); % to prevent accidental input
    dotInfo.keyEscape = KbName('Escape'); % exit experiment
    dotInfo.keyReturn = KbName('Return'); % continue experiment

    %% randomize stimuli and non-target duration
    
    % set random seed

    rseed = sum(100*clock);
    rng(rseed,'twister');
    [dotInfo.rngSetting] = rng;

    % pseudo-randomize target attribute (max. of 2 repetitions)
    
    distrib = repmat([1:dotInfo.numOfAtt],1,dotInfo.trialsPerAtt*2); % double amount of requested trials, so that trialsPerAtt is available within both cued and uncued condition
    tmp_rand = randperm(numel(distrib));
    tmp.random = distrib(tmp_rand);
    rep = diff(find(diff([-Inf tmp.random Inf])));
    while max(rep) > 3 % randomly switch numbers until criterion is reached
        tmp.switchInds = randi(length(tmp.random),1, 2);
        tmp.switch1 = tmp.random(tmp.switchInds(1));
        tmp.switch2 = tmp.random(tmp.switchInds(2));
        tmp.random(tmp.switchInds(1)) = tmp.switch2;
        tmp.random(tmp.switchInds(2)) = tmp.switch1;
        rep = diff(find(diff([-Inf tmp.random Inf])));
    end
    dotInfo.targetAtt = tmp.random;
    
    %% randomize directed attention trials & higher probability choice (within attribute)
    
    dotInfo.DirAttn = NaN(size(dotInfo.targetAtt));
    dotInfo.HighProbAtt = NaN(size(dotInfo.targetAtt));
    numSelAttn = ceil(dotInfo.dirAttentionRate*dotInfo.trialsPerAtt*2);
    for indAtt = 1:dotInfo.numOfAtt % retain relationships for each attribute
        tmp_trials = find(dotInfo.targetAtt == indAtt);
        tmp_rand = randperm(numel(tmp_trials));
        tmp_choice1 = tmp_trials(tmp_rand(1:numSelAttn));
        tmp_choice2 = tmp_trials(tmp_rand(numSelAttn+1:end));
        dotInfo.DirAttn(tmp_choice1) = 1;
        dotInfo.DirAttn(tmp_choice2) = 2;
        dotInfo.HighProbAtt(tmp_choice1(1:numel(tmp_choice1)/2)) = 1; % First half is designated highProb = 1;
        dotInfo.HighProbAtt(tmp_choice1((numel(tmp_choice1)/2)+1:end)) = 2; % Second half is deignated highProb = 2;
        dotInfo.HighProbAtt(tmp_choice2(1:numel(tmp_choice2)/2)) = 1;
        dotInfo.HighProbAtt(tmp_choice2((numel(tmp_choice2)/2)+1:end)) = 2;
    end
        
    % Note that within attribute high probability choice and directed attention are orthogonal.
    % They both depend on the same randomization step.
    
    % The high probability choices only refer to the target attribute. The
    % high probability options for the other attributes are randomly drawn
    % below.
    
    % Note that there is no check that the conjunction of different
    % attributes appears equally often. 
    
    %% get random choices for remaining attributes on each trial
    
    dotInfo.HighProbChoice = NaN(4,size(dotInfo.targetAtt,2));
    
    for indTrial = 1:dotInfo.totalTrials
        for indAtt = 1:dotInfo.numOfAtt
            if dotInfo.targetAtt(indTrial) == indAtt % for target attribute, select the previously identified option
                dotInfo.HighProbChoice(indAtt,indTrial) = dotInfo.HighProbAtt(1,indTrial);
            else 
                tmp_rand = randperm(2);
                dotInfo.HighProbChoice(indAtt,indTrial) = tmp_rand(1);
            end
        end
    end
    
%     %% frequency flicker for distractor
%             
%     displayList = Screen('screens');
%     displayIdx = displayList(1);
%     PsychDebugWindowConfiguration(0, 0);
%     screenInfo = openExperiment(50,50,displayIdx); clc; % open drawing canvas
%     ifi = Screen('GetFlipInterval', screenInfo.curWindow);
%     closeExperiment;
%     
%     % set flicker frequency
%     checkFlipTimeSecs = 1/dotInfo.Hz_BG;
% 
%     % jitter frequency
% 
%     for indBlock = 1
%         
%         checkerDuration = sum(dotInfo.presTime{indBlock}); % length of checkerboard presentation is the total duration of the stimuli
%         checkerDuration = ceil(checkerDuration+.1*checkerDuration); % pad a bit so that slight timing problems do not become an issue; NOTE that this may slightly affect the average flicker frequency, but shouldn't be too bad.
%         flipsAtMeanFreq = checkFlipTimeSecs/ifi; 
%         rangeOfUpdates = flipsAtMeanFreq-2:1:flipsAtMeanFreq+2; % range of refresh intervals
%         repPerUpdate = checkerDuration/sum(rangeOfUpdates.*ifi); % round up checker duration to be safe and to make repmat work
%         Updates = repmat(rangeOfUpdates, 1, repPerUpdate);
%         
%         randUpdate = [];
%         randUpdate = randperm(numel(Updates));
%         dotInfo.UpdatesJitter{indBlock} = Updates(randUpdate); % contains the frame numbers at which an inversion occurs
%     end
    
end
