%_______________________________________________________________________
%
% Configuration for running dotsExperiment
%_______________________________________________________________________
%
% Output
%
% expInfo | configuration for state switch MAT (struct)

% Written by Julian Kosciessa (kosciessa@mpib-berlin.mpg.de)

% 170704    - incorporated thresholds
% 170809    - incorporated state dimensionality & accompanying
%               randomization changes
% 170814    - introduce run format; adapted timing
% 170816    - changed to expInfo format; fixed randomization
% 170823    - changed randomization to account for switch probability
% 170829    - included RT feedback

function expInfo = StateSwitch_createExpInfo_dynamic_170829

    expInfo.trialsPerAtt = 16;  % number of trials within state order & attribute (half of this for each choice) 
    expInfo.numOfAtt = 4;       % number of attributes to be included
    expInfo.numOrders = 4;
    expInfo.totalTrials = expInfo.trialsPerAtt*expInfo.numOfAtt*expInfo.numOrders;
    
    %expInfo.runAmount = 4;      % number of runs; each run should have each category x times
        
    expInfo.durBlockOnset = 5;  % duration of block onset
    expInfo.durFixCue = 2;      % duration of fixcross with cues
    expInfo.durCue = 0;         % duration of cue
    expInfo.durPres = 3;        % duration of presentation
    expInfo.durResp = 2;        % duration of question
    expInfo.durConf = 0;        % duration of confidence
    expInfo.durReward = 3;      % duration of reward
    expInfo.durITI = 2;         % duration of ITI
    
    expInfo.timing = 'relativeITI';

    expInfo.trialDuration.all = expInfo.durFixCue+expInfo.durPres+expInfo.durResp+expInfo.durConf+expInfo.durITI;
    expInfo.trialDuration.durFixCue = expInfo.durFixCue;
    expInfo.trialDuration.Pres = expInfo.durFixCue+expInfo.durPres;
    expInfo.trialDuration.Resp = expInfo.durFixCue+expInfo.durPres+expInfo.durResp;
    expInfo.trialDuration.Conf = expInfo.durFixCue+expInfo.durPres+expInfo.durResp+expInfo.durConf;
    
    expInfo.confOptions = '2';      % 2 or 4 confidence options
    expInfo.highlightChoice = 1;    % highlight choice by retaining only chosen option?
    
    expInfo.feedback = 0;   % no feedback
    
    expInfo.dirSet          = [180, 0];     % dots in left or right direction
    expInfo.numDotField     = 1;            % show a single dot patches on screen
    expInfo.apXYD           = [0 0 130];    % coordinates and diameter of aperture
    expInfo.speed           = [50];         % speed of dot motion
    expInfo.trialtype       = [2 1 1];      % reaction time, not relevant, keyboard
    expInfo.dotSize         = 3;            % dot size in pixels
    expInfo.maxDotTime      = 2;            % maximum duration of moving dots
    expInfo.fixXY           = [0 0];        % fixation coordinates
    expInfo.fixDiam         = 2;            % fixation diameter
    expInfo.fixColor        = [0 150 200];  % blue fixation dot
    expInfo.fixMinTime      = 0.75;         % minimum fixation
    expInfo.fixMaxTime      = 1.25;         % maximum fixation
    %expInfo.maxDotsPerFrame = 300;          % depends on graphics card
    expInfo.fixTime         = 2;            % JQK: fixed onset fixation time
    expInfo.DotsPerFrame    = 48*3;

    expInfo.breakTime = 60;                   % pause for 60 seconds between runs
    
    % update frequency of on-screen content
    
    expInfo.Hz_RDM  = 30; % kinematogram updates in Hz
    
    % multi-attribute task
    expInfo.MAT.percAtt1H = .60;
    expInfo.MAT.percAtt2H = .60;
    expInfo.MAT.percAtt3H = .65;
    expInfo.MAT.percAtt4H = .65;
    expInfo.MAT.percAtt1L = 1-expInfo.MAT.percAtt1H;
    expInfo.MAT.percAtt2L = 1-expInfo.MAT.percAtt2H;
    expInfo.MAT.percAtt3L = 1-expInfo.MAT.percAtt3H;
    expInfo.MAT.percAtt4L = 1-expInfo.MAT.percAtt4H; 
    
    %expInfo.MAT.color = [255 255 255; 255 0 0];                            % define dot color
    %expInfo.MAT.color = [177,213,57; 234,35,93];                           % define dot color
    
    % saturated & muted
    expInfo.MAT.color  = [174,205,96; 203,117,143];
    expInfo.MAT.color1 = [174,205,96; 203,117,143];                           % define dot color
    expInfo.MAT.color2 = [177,213,57; 234,35,93];                           % green first, then red
    
%     % light & dark
%     expInfo.MAT.color  = [222,235,151; 241,147,186];
%     expInfo.MAT.color1 = [222,235,151; 241,147,186];                        % define dot color
%     expInfo.MAT.color2 = [125,155,64; 160,26,67];
%     
    %expInfo.MAT.coherence = 1;                                             % define dot movement (coherence)
    expInfo.MAT.coherence = .65;                                            % define dot movement (coherence)
    expInfo.MAT.direction = [180 0];                                        % left and right
    expInfo.MAT.size = [5 8];                                               % define dot size
    expInfo.MAT.saturation = [1,2];                                          % define dot luminance
    expInfo.MAT.attNames = {'color'; 'direction'; 'size'; 'saturation'};
    expInfo.MAT.attNamesDE = {'Farbe'; 'Richtung'; 'Größe'; 'Sättigung'};
    
    %% feedback
    
    expInfo.RTfeedback.reward = 20;
    expInfo.RTfeedback.loss = 0;
    expInfo.RTfeedback.slack = .2; % seconds allowed below median RT
    expInfo.RTfeedback.type = 'fixed'; % 'fixed' vs. 'RT'
    expInfo.RTfeedback.fixedFeedback = [ones(1,25), zeros(1,7)];
    expInfo.RTfeedback.fixedFeedback = expInfo.RTfeedback.fixedFeedback(randperm(32));
    expInfo.RTfeedback.fixedFeedback = reshape(expInfo.RTfeedback.fixedFeedback, [], 4)';

    %% specify keys
    % Use OS X keyboard naming scheme across all plattforms
    % Otherwise LeftControl/RightControl are not recognized
    KbName('UnifyKeyNames');
    expInfo.keyLeft     = [KbName('LeftControl'), KbName('LeftAlt'), KbName('LeftArrow'), KbName('1!'),KbName('2@')];    % left response
    expInfo.keyRight    = [KbName('RightControl'), KbName('RightAlt'), KbName('RightArrow'),KbName('6^'),KbName('7&')];  % right response
    expInfo.keyConf1    = [KbName('LeftControl'), KbName('LeftArrow'), KbName('1!')];       % lowest confidence
    expInfo.keyConf2    = [KbName('LeftAlt'), KbName('2@')];                                % intermediate confidence low
    expInfo.keyConf3    = [KbName('RightAlt'),KbName('6^')];                                % intermediate confidence high
    expInfo.keyConf4    = [KbName('RightControl'), KbName('RightArrow'),KbName('7&')];      % highest confidence
    expInfo.keyModifier = KbName('LeftAlt'); % to prevent accidental input
    expInfo.keyEscape   = KbName('Escape'); %
    expInfo.keyReturn   = [KbName('Return'), KbName('7&')]; % continue experiment
    expInfo.keyPause    = KbName('p');

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

    rseed = sum(100*clock);
    rng(rseed,'twister');
    [expInfo.rngSetting] = rng;
    
    %% Here we need to decide the following settings:
    
    %  1. How many attribute dimensions (i.e. state manipulation)? [block-wise to avoid 'meta-four state']
    %  2. Which attributes to be chosen? Same in each block?
    %  3. Which target in each trial?
    %  4. Which option of the attribute is winning?
    
    %% decide cueing state order (1/2/3/4) & higher probability choice (within attribute)
    
    expInfo.blockLengthDim = 8; % amount of consecutive trials belonging to the same state dimension block; needs to be a multiple of 4
    
    expInfo.blockAmount     = (expInfo.trialsPerAtt*expInfo.numOfAtt*expInfo.numOrders)/expInfo.blockLengthDim; % amount of blocks (i.e. determined by total trial count and block length) 
    expInfo.blocksPerOrd    = expInfo.blockAmount/expInfo.numOrders;                        % amount of blocks per state dimension
    expInfo.StateOrder      = NaN(expInfo.blockAmount, expInfo.blockLengthDim);             % prelim. matrix for state dimension order
    expInfo.AttCues         = cell(expInfo.blockAmount, expInfo.blockLengthDim);            % prelim. cell struc for attribute cues
    expInfo.targetAtt       = NaN(expInfo.blockAmount, expInfo.blockLengthDim);             % prelim. matrix for target attribute
    expInfo.targetOption    = NaN(expInfo.blockAmount, expInfo.blockLengthDim);             % prelim. matrix for target option
    expInfo.HighProbChoice  = cell(expInfo.blockAmount, expInfo.blockLengthDim);            % prelim. cell struc for winning options
    
    expInfo.blockTime = expInfo.durBlockOnset+expInfo.blockLengthDim*...
        (expInfo.durCue+expInfo.durPres+expInfo.durResp+expInfo.durConf+expInfo.durReward+expInfo.durITI);
    
    % get amounts of runs to achieve approx. 10 min per run
    
    %expInfo.runAmount = ceil(expInfo.blockAmount*expInfo.blockTime/60/10);
    expInfo.runAmount = expInfo.blocksPerOrd/2; % now 4 runs! rather go for many runs vs. not including many breaks
    expInfo.blocksPerRun = 8;
    
    % Pseudo-randomize the block order, i.e. allowing for repeting dimension blocks.
    % This is performed run-wise, such that each run contains a single
    % block of each state order. We also make sure that there are no
    % adjacent repeats of dimension blocks.
    
    criterion = 0;
    while criterion == 0
        allCombsBlocks = perms([1,2,3,4]);
        chosenBlockOrders = randperm(size(allCombsBlocks,1),expInfo.blocksPerRun); % have two dimension blocks each iteration
        blockDimOrder = reshape(allCombsBlocks(chosenBlockOrders,:)',[],1);
        if min(abs(diff(blockDimOrder))) ~= 0 % check that there are no repeats
            criterion = 1;
        end
    end
    expInfo.StateOrder = repmat(blockDimOrder,1,expInfo.blockLengthDim); % final state order output for presentation
    
%     blockDimOrder = repmat(1:4,1,16); tmp_rand = randperm(expInfo.blockAmount);   
%     blockDimOrder = blockDimOrder(tmp_rand);
%     expInfo.StateOrder = repmat(blockDimOrder', 1, expInfo.blockLengthDim);            % final state order output for presentation
    
    % get combinatorials for attribute cues for each dimension order
    
    for indOrd = 1:expInfo.numOrders
        combsDim{indOrd} = nchoosek([1:expInfo.numOfAtt], indOrd); % 4, 6, 4, 1
    end
    
    for indOrd = 1:expInfo.numOrders
        tmp_blocks = find(blockDimOrder == indOrd);
        tmp_blockCues = repmat(combsDim{indOrd},floor(numel(tmp_blocks)/size(combsDim{indOrd},1)),1);
        if indOrd == 2 % there are 6 options, hence add two more; important: add all attributes 1-4!
            tmp_blockCues = [tmp_blockCues; combsDim{indOrd}(1,:); combsDim{indOrd}(end,:)]; 
        end
        rand.blockCues(indOrd,:) = randperm(size(tmp_blockCues,1));
        for indBlock = 1:numel(tmp_blocks)
            expInfo.AttCues(tmp_blocks(indBlock),:) = {tmp_blockCues(rand.blockCues(indOrd,indBlock),:)}; % encode attribute cues
        end
    end
    
    %% determine target attribute
    
    % The logic here is the following: We now have blocks, in which the
    % same state order and the same attribute targets are presented. Now,
    % wihtin those attribute options, but across blocks, we choose trials
    % such that each target attribute will occur the same number of times
    % within-order (but not necessarily within-cue combination or block).
    % Then we also choose half of the target attribute trials randomly and
    % allocate them to the target option (i.e. red/white), such that these
    % are also matched in amount within-attribute. The target attribute
    % matching is done based on the groups of cue conjunctions.
    
    % Note that the current procedure does no make sure, that e.g. every
    % option occurs within each cue block.
    
    indCatch = [];
    for indOrd = 1:4
        
        disp(num2str(indOrd));
        
        Splits = [];
        
        % for all attributes, get location of the dimension trials among all trials
        % trial attributes are assigned among these
        for indAtt = 1:4
            index = cellfun(@(x) ismember(indAtt,x), expInfo.AttCues(blockDimOrder==indOrd,:), 'UniformOutput', 0);
            indCatch{indOrd, indAtt} = find(cell2mat(index));
        end
        
        if indOrd == 1
            idxCurrentOrder = find(expInfo.StateOrder == indOrd); % indexes trials of current state order
            [row, ~] = ind2sub(size(expInfo.targetAtt),idxCurrentOrder); row = unique(row);
            expInfo.targetAtt(row,:) = repmat(cell2mat(expInfo.AttCues(row,1)),1,8);
        end
        
        if indOrd == 2
            Splits{1} = intersect(indCatch{indOrd, 1}, indCatch{indOrd, 2}); % 1 1 0 0
            Splits{2} = intersect(indCatch{indOrd, 2}, indCatch{indOrd, 3}); % 0 1 1 0
            Splits{3} = intersect(indCatch{indOrd, 2}, indCatch{indOrd, 4}); % 0 1 0 1
            Splits{4} = intersect(indCatch{indOrd, 3}, indCatch{indOrd, 4}); % 0 0 1 1
            Splits{5} = intersect(indCatch{indOrd, 1}, indCatch{indOrd, 3}); % 1 0 1 0
            Splits{6} = intersect(indCatch{indOrd, 1}, indCatch{indOrd, 4}); % 1 0 0 1
            extractMat = [1 1 0 0; 0 1 1 0; 0 1 0 1; 0 0 1 1; 1 0 1 0; 1 0 0 1];
        end
            
        if indOrd == 3
            Splits{1} = intersect(intersect(indCatch{indOrd, 1}, indCatch{indOrd, 2}), indCatch{indOrd, 3}); % 1 2 1 0
            Splits{2} = intersect(intersect(indCatch{indOrd, 2}, indCatch{indOrd, 3}), indCatch{indOrd, 4}); % 0 1 2 1
            Splits{3} = intersect(intersect(indCatch{indOrd, 1}, indCatch{indOrd, 3}), indCatch{indOrd, 4}); % 1 0 1 2
            Splits{4} = intersect(intersect(indCatch{indOrd, 1}, indCatch{indOrd, 2}), indCatch{indOrd, 4}); % 2 1 0 1
            % split into four groups to distribute (unequally)
            extractMat = [1,2,1,0; 0,1,2,1; 1,0,1,2; 2,1,0,1]; % amount of quartets to be extracted; row: triplet, column: attribute
            % Note that due to the fixed allocation, there will always be
            % an imbalance of the attributes within each cue condition.
        end % 3 state dimension
        
        if indOrd == 4
            splitVec = [1:64/4:numel(indCatch{indOrd, 1}), 65]; % create artificial splits to help pseudo-randomisation
            for indSplit = 1:4
                selectTrials = sub2ind(size(expInfo.AttCues(blockDimOrder==indOrd,:)), ...
                    [repmat(((indSplit-1)*2+1),8,1); repmat(((indSplit-1)*2+2),8,1)], [1:8, 1:8]');
                Splits{indSplit} = selectTrials;
                extractMat = [1,1,1,1; 1,1,1,1; 1,1,1,1; 1,1,1,1];
            end;
        end
                
        %% fix switch probability & select attribute targets
                
        if ismember(indOrd, [2:4])
            for indSplit = 1:numel(Splits)
                check = 0;
                while check == 0 % try to find pseudo-randomization that works
                    try
                        % pseudo-randomize to start block with no-switch
                        % have a maximum of 3 repetitions (i.e. 4 identical trials)
                        while check == 0
                            switchVec = [zeros(1,.5*numel(Splits{indSplit})),ones(1,.5*numel(Splits{indSplit}))];
                            switchVec_rand = randperm(numel(switchVec));
                            switchVec = switchVec(switchVec_rand);
                            % check for repetitions
                            A = switchVec';
                            J = find(diff([A(1)-1; A]));
                            if max(diff([J; numel(A)+1])) <= 3 & A(1:8:end)==0
                                check = 1;
                            end
                        end
                        % fill with attributes: 
                        % sequential allocation without replacement
                        % start with most numerous option
                        if indOrd == 4
                            availableOptions = repelem([1:4], 4.*extractMat(indSplit,:));
                            mostCommon = find(extractMat(indSplit,:)==1);
                            mostCommon = mostCommon(1);
                        elseif indOrd == 3
                            availableOptions = repelem([1:4], 4.*extractMat(indSplit,:));
                            mostCommon = find(extractMat(indSplit,:)==2);
                        elseif indOrd == 2
                            availableOptions = repelem([1:4], numel(Splits{indSplit})/2.*extractMat(indSplit,:));
                            mostCommon = find(extractMat(indSplit,:)==1);
                            mostCommon = mostCommon(1);
                        end
                        tmp_availableCats = unique(availableOptions);
                        switchVec_atts = NaN(1,numel(availableOptions));
                        for indTrial = 1:numel(switchVec)
                            if switchVec(indTrial) == 0 & indTrial == 1
                                switchVec_atts(indTrial) = mostCommon;
                            elseif switchVec(indTrial) == 0
                                switchVec_atts(indTrial) = switchVec_atts(indTrial-1);
                            elseif switchVec(indTrial) == 1
                                lastAnwer = switchVec_atts(indTrial-1);
                                nextItem = find(tmp_availableCats>lastAnwer);
                                if isempty(nextItem)
                                    nextItem = tmp_availableCats(1);
                                else nextItem = tmp_availableCats(nextItem(1));
                                end
                                switchVec_atts(indTrial) = nextItem;
                            end
                            % remove last encoded from list (i.e. choose without replacement)
                            tmp_cur = find(availableOptions == switchVec_atts(indTrial));
                            availableOptions(tmp_cur(1)) = [];
                        end
                    catch % if randomization does not work out, start again ...
                        check = 0;
                    end % try
                end % while
                % randomize order of chunks within each block
                tmp_randBlocks = reshape(switchVec_atts,8,[])';
                for rowInd = 1:size(tmp_randBlocks,1)
                    tmp_split = SplitVec(tmp_randBlocks(rowInd,:));
                    tmp_split_length = sort(SplitVec(tmp_randBlocks(rowInd,:), 'equal','length'),'ascend');
                    check = 0;
                    while check == 0 % make sure nothing changes to the number of chunks
                        tmp_split2 = tmp_split(randperm(numel(tmp_split)));                        
                        tmp_split2_length = sort(SplitVec([cell2mat(tmp_split2)], 'equal','length'),'ascend');
                        if isequal(tmp_split_length, tmp_split2_length)
                            check = 1;
                            tmp_randBlocks(rowInd,:) = [cell2mat(tmp_split2)];
                        end
                    end
                end
                % allocate attributes to trials
                idxCurrentOrder = find(expInfo.StateOrder == indOrd); % indexes trials of current state order
                [row, ~] = ind2sub(size(expInfo.targetAtt),idxCurrentOrder(Splits{indSplit}));
                row = unique(row);
                expInfo.targetAtt(row,:) = tmp_randBlocks;
            end % split loop
        end
            
        %% determine target choice
        
        % for each attribute, randomize within-order, which option will be the winner
        for indAttribute = 1:4
            idxCurrentOrder = find(expInfo.StateOrder == indOrd);
            tmp_curTrials = find(expInfo.targetAtt(idxCurrentOrder) == indAttribute);
            tmp_curTrialsPerm = reshape(tmp_curTrials(randperm(numel(tmp_curTrials))),2,[]);
            expInfo.targetOption(idxCurrentOrder(tmp_curTrialsPerm(1,:))) = 1;
            expInfo.targetOption(idxCurrentOrder(tmp_curTrialsPerm(2,:))) = 2;
        end; clear tmp*
        
    end % state order loop
        
    %% make sure that each block has all cue options occuring
    % This would mess up the transition probability slightly, but it is
    % rare that a correction is necessary anyways.
        
    check = zeros(size(expInfo.targetAtt,1),2);                             % index, whether block fulfills requirements
    while min(check(:,1)) == 0                                              % while matching is not done, go through all blocks again
        for indBlock = 1:size(expInfo.targetAtt,1)
           % check whether all cued trials are available
           TransProb.cuedOptions = expInfo.AttCues{indBlock,1};
           while check(indBlock,1) == 0
               TransProb.availOptions = unique(expInfo.targetAtt(indBlock,:));
               TransProb.missingOptions = setdiff(TransProb.cuedOptions, TransProb.availOptions);
               if isempty(TransProb.missingOptions)                             % all options available
                   check(indBlock,1) = 1;
               else                                                             % not all options available
                   disp('Not all options occur. Readjusting ...')
                   warning('You should re-check transition probabilities.')
                   check(indBlock,1) = 0;
                   % exchange most frequent option with another trial
                   % sort available options in their order of frequency
                   [tmp_histn,~]=histcounts(expInfo.targetAtt(indBlock,:));
                   [~, tmp_sort_histn] = sort(tmp_histn(tmp_histn~=0), 'descend');
                   TransProb.availOptions = TransProb.availOptions(tmp_sort_histn);
                   % get trials of current state order (only exchange within
                   % order!!!) & missing attribute
                   TransProb.relevantTrials = expInfo.StateOrder == expInfo.StateOrder(indBlock,1) & expInfo.targetAtt == TransProb.missingOptions(1);
                   % buffer targetAtt & targetOption of the to-be-swapped trials
                   TransProb.tAttGo_avail = find(expInfo.targetAtt(indBlock,:)==TransProb.availOptions(1));
                   TransProb.tAttGoIdx = TransProb.tAttGo_avail(randperm(numel(TransProb.tAttGo_avail),1));
                   TransProb.tAttGoIdx = sub2ind(size(expInfo.targetAtt), indBlock, TransProb.tAttGoIdx); % convert to linear index
                   TransProb.tAttGoAtt = expInfo.targetAtt(TransProb.tAttGoIdx);
                   TransProb.tAttGoOpt = expInfo.targetOption(TransProb.tAttGoIdx);
                   TransProb.tAttGet_avail = find(TransProb.relevantTrials);
                   TransProb.tAttGetIdx = TransProb.tAttGet_avail(randperm(numel(TransProb.tAttGet_avail),1));
                   TransProb.tAttGetAtt = expInfo.targetAtt(TransProb.tAttGetIdx);
                   TransProb.tAttGetOpt = expInfo.targetOption(TransProb.tAttGetIdx);
                   % do the switch
                   expInfo.targetAtt(TransProb.tAttGoIdx) = TransProb.tAttGetAtt;
                   expInfo.targetAtt(TransProb.tAttGetIdx) = TransProb.tAttGoAtt;
                   expInfo.targetOption(TransProb.tAttGoIdx) = TransProb.tAttGetOpt;
                   expInfo.targetOption(TransProb.tAttGetIdx) = TransProb.tAttGoOpt;
               end
           end
        end
    end; clear TransProb tmp*;
    
    % figure; subplot(1,2,1); imagesc(expInfo.targetAtt); subplot(1,2,2); imagesc(expInfo.StateOrder);
    
    %% sanity check transition probability, number of presented attributes
    
	for indDim = 1:4
        idxCurrentOrder = find(expInfo.StateOrder(:,1) == indDim);
        idxCurrentOrder_mat = find(expInfo.StateOrder == indDim);
        % check number of presented attributes
        for indAtt = 1:4
            PresentedAttNum(indDim, indAtt) = numel(find(expInfo.targetAtt(idxCurrentOrder,:)==indAtt));
            PresentedAttNum_low(indDim, indAtt) = numel(find(expInfo.targetOption(idxCurrentOrder_mat(expInfo.targetAtt(idxCurrentOrder,:)==indAtt))==1));
            PresentedAttNum_high(indDim, indAtt) = numel(find(expInfo.targetOption(idxCurrentOrder_mat(expInfo.targetAtt(idxCurrentOrder,:)==indAtt))==2));
        end
        % check switching probability
        SwitchProb_no(indDim) = numel(find(abs(diff([expInfo.targetAtt(idxCurrentOrder,1), expInfo.targetAtt(idxCurrentOrder,:)],[],2))==0));
        SwitchProb_yes(indDim) = numel(find(abs(diff([expInfo.targetAtt(idxCurrentOrder,1), expInfo.targetAtt(idxCurrentOrder,:)],[],2))> 0));
    end
    [PresentedAttNum, [NaN; NaN; NaN; NaN], PresentedAttNum_low,[NaN; NaN; NaN; NaN], PresentedAttNum_high, [NaN; NaN; NaN; NaN], SwitchProb_no', SwitchProb_yes']
    
    %% select parameters of remaining attributes one each trial
    
    % these are chosen such that within each dimension and attribute, all
    % other parameter constellations are presented (i.e. the 16 combinations 
    % should be presented in each category of the design)
    
    combs = allcomb([1,2],[1,2],[1,2],[1,2]); % Note that 1 & 2 refer to the higher/lower prob option here.
    
    % The target option is always already fixed as done above. This leaves
    % eight remaining combinations for each multi-attribute display that
    % should be allocated within-order, within-target-attribute.
    
    % 1. get current state dim order
    % 2. get current attribute
    % 3. get high/low option
    % 4. distribute the remaining categories
    
    for indOrd = 1:4
        for indAtt = 1:4
            for indChoice = 1:2
                idxCurrentOrder_l1 = find(expInfo.StateOrder == indOrd); % indexes trials of current state order
                idxCurrentAtt_l2 =  find(expInfo.targetAtt(idxCurrentOrder_l1) == indAtt);
                indCurrentChoice_l3 = find(expInfo.targetOption(idxCurrentOrder_l1(idxCurrentAtt_l2)) == indChoice);
                indCombined = idxCurrentOrder_l1(idxCurrentAtt_l2(indCurrentChoice_l3));
                % get combinations with current parameters (regarding target attribute & choice)
                curCombs = combs(combs(:,indAtt)==indChoice,:);
                % randomize trials
                indRecomb = indCombined(randperm(numel(indCombined)));
                % repeat to match amount of trials
                curCombs = repmat(curCombs, numel(indRecomb)/size(curCombs,1),1);
                for indTrial = 1:numel(indRecomb)
                    indTargetTrial = indRecomb(indTrial);
                    expInfo.HighProbChoice{indTargetTrial} = curCombs(indTrial,:);
                end
            end % choice
        end % attribute
    end % order
    
    %% put everything into block wrappers
    
    edges = 1:expInfo.blocksPerRun:32+1;
    for indRun = 1:expInfo.runAmount
        expInfo.StateOrderRun{indRun} = expInfo.StateOrder(edges(indRun):edges(indRun+1)-1,:);
        expInfo.AttCuesRun{indRun} = expInfo.AttCues(edges(indRun):edges(indRun+1)-1,:);
        expInfo.targetAttRun{indRun} = expInfo.targetAtt(edges(indRun):edges(indRun+1)-1,:);
        expInfo.targetOptionRun{indRun} = expInfo.targetOption(edges(indRun):edges(indRun+1)-1,:);
        expInfo.HighProbChoiceRun{indRun} = expInfo.HighProbChoice(edges(indRun):edges(indRun+1)-1,:);
    end
    
    
end
