clear all; close all;

rng('shuffle'); % Randomize seed of random number generator

%% Set up general parameters
Gparams = [];
Gparams = setupGParams(Gparams);

%% Hide Cursor and set priority
HideCursor;
priorityLevel = MaxPriority(Gparams.pWindow);
Priority(priorityLevel);
RestrictKeysForKbCheck([KbName('Space')]);

%% --------- Instructions Dots and Coherence --------- %% 

%% Generate block and trial structure
nBlocks         = 1;

for iBlock = 1:nBlocks   
    trialMatrix.relative_coherence(iBlock,:) = [30 25 25 20 -30 -25 -25 -20] / 100;
    
    % Directions of the standard and test stimuli
    trialMatrix.direction(iBlock,:) = [100 250 350 30 170 320 210 130];
    
    % Response mapping is dependent on subject number
    trialMatrix.responseMapping(iBlock,:) = ones(size(trialMatrix.relative_coherence(iBlock,:))) * (mod(Gparams.subjectNumber,2) + 1);   
       
end

nTrials = length(trialMatrix.relative_coherence);

%% run blocks
for iBlock = 1:nBlocks
    
    DrawFormattedText(Gparams.pWindow, 'Loading stimuli...', 'center', 'center', 255);
    Screen('Flip', Gparams.pWindow);
    
    % preload all the dot coordinates - overwrite this block!
    testStimCoord = nan(nTrials, Gparams.timing.nframes, 2, Gparams.dots.nDots);
    standardStimCoord = nan(nTrials, Gparams.timing.nframes, 2, Gparams.dots.nDots);
    
    for iTrial = 1:nTrials
        testStimCoord(iTrial, :, :, :) = dots(iTrial,iBlock,trialMatrix,0,Gparams);
        standardStimCoord(iTrial, :, :, :) = dots(iTrial,iBlock,trialMatrix,1,Gparams);
    end
    
    text = ['Welcome to the experiment.\n\n\n\n' ...
        'We will start with a series of instructions.\n\n'...
        'Please read the instructions carefully.\n\n'...
        'If anything is unclear, you can ask the experimenter for help at all times.\n\n\n\n' ...
        'Press "space" to start the instructions.'];
    showtext(text,Gparams);
    
    text = ['In this experiment you will see clouds of white dots on the screen.\n\n' ...
    'In the center of the screen you will see a red fixation dot.\n\n' ...
    'It is very important that you keep your eyes fixated on this dot\n\n' ...
    'and do not make eye movements to the white dots.\n\n\n\nPress "space" to see an example.'];
    showtext(text,Gparams);
    
    drawDots(squeeze(standardStimCoord(1,1, :, :)),Gparams);
    drawFixation(Gparams);
    Screen('Flip', Gparams.pWindow);
    WaitSecs(.1); KbWait(); WaitSecs(.1);
    
    text = ['The dots you see will move, on average, in a particular direction.\n\n\n\n' ...
        'Press "space" to see different examples of the dots moving in a particular direction.'];
    showtext(text,Gparams);
    
    for iTrial = 1:length(trialMatrix.relative_coherence)/2
        
        %% Fixation
        drawFixation(Gparams);
        Screen('Flip', Gparams.pWindow);
        WaitSecs(1.5);
               
        %% Stimulus        
        for iFrame = 1:Gparams.timing.nframes
            
            drawDots(squeeze(standardStimCoord(iTrial,iFrame, :, :)), Gparams);
            drawFixation(Gparams);
            Screen('Flip', Gparams.pWindow);
            
        end     
                   
    end    

    %% Fixation
    drawFixation(Gparams);
    Screen('Flip', Gparams.pWindow);
    WaitSecs(1.5);
    
    Screen('Flip', Gparams.pWindow); WaitSecs(2);
    
    text = ['We call what you just saw "dot clouds".\n\n' ...
        'Dot clouds can have different coherence levels. \n\n' ...
        'Coherence refers to how clearly the dots are moving together. \n\n\n' ...
        'High coherence means the dots are clearly moving together. \n\n' ...
        'Low coherence means the dots are not clearly moving together. \n\n\n\n' ...
        'All the examples you saw just had the same coherence level. \n\n' ...
        'We will call the coherence level you just saw the "standard". \n\n\n\n' ...
        'Press "space" to continue with the instructions.'];
    showtext(text,Gparams);
    
    WaitSecs(0.5);
    
    text = ['You will now see 4 examples of high coherence.\n\n' ...
        'Press "space" to see the examples.'];
    showtext(text,Gparams);
    
    for iTrial = 1:length(trialMatrix.relative_coherence)
                   
        %% Fixation
        drawFixation(Gparams);
        Screen('Flip', Gparams.pWindow);
        WaitSecs(1.5);
               
        %% Stimulus        
        for iFrame = 1:Gparams.timing.nframes
            drawDots(squeeze(testStimCoord(iTrial,iFrame, :, :)), Gparams);
            drawFixation(Gparams);
            Screen('Flip', Gparams.pWindow);
        end
        
        if iTrial == 4
            Screen('Flip', Gparams.pWindow); WaitSecs(1.5);
            text = ['These were the examples of high coherence.\n\n\n\n' ...
                'You will now see 4 examples of low coherence.\n\n' ...
                'Press "space" to see the examples.'];
            showtext(text,Gparams);
        end
            
    end
    
    %% Fixation
    drawFixation(Gparams);
    Screen('Flip', Gparams.pWindow);
    WaitSecs(1.5);
    
    Screen('Flip', Gparams.pWindow); WaitSecs(2);
    
end

%% --------- Instructions Coherence Difference --------- %% 

%% Generate block and trial structure

clear trialMatrix iBlock

for iBlock = 1:nBlocks   
    trialMatrix.relative_coherence(iBlock,:) = [30 25 20 10 5 5 -30 -25 -20 -10 -5 -5] / 100;
    
    % Directions of the standard and test stimuli
    trialMatrix.direction(iBlock,:) = [340 110 200 280 140 50 310 10 220 100 300 190];
       
end

nTrials = length(trialMatrix.relative_coherence);

%% run blocks
for iBlock = 1:nBlocks
    
    DrawFormattedText(Gparams.pWindow, 'Loading stimuli...', 'center', 'center', 255);
    Screen('Flip', Gparams.pWindow);
    
    % preload all the dot coordinates - overwrite this block!
    testStimCoord = nan(nTrials, Gparams.timing.nframes, 2, Gparams.dots.nDots);
    standardStimCoord = nan(nTrials, Gparams.timing.nframes, 2, Gparams.dots.nDots);
    
    for iTrial = 1:nTrials
        testStimCoord(iTrial, :, :, :) = dots(iTrial,iBlock,trialMatrix,0,Gparams);
        standardStimCoord(iTrial, :, :, :) = dots(iTrial,iBlock,trialMatrix,1,Gparams);
    end
   
    text = ['In each round of the experiment, you will see two clouds of dots. \n\n' ...
        'These clouds of dots appear one after the other. \n\n' ...
        'They move in the same direction. \n\n\n' ...
        'Importantly, the two clouds of dots have different coherence levels. \n\n' ...
        'The first cloud of dots has the standard coherence level that you have seen before. \n\n' ...
        'The second cloud of dots has either a HIGHER or LOWER coherence level than the standard. \n\n\n\n' ...
        'Press "space" to continue with the instructions.'];
    showtext(text,Gparams);
    
    WaitSecs(0.5);
               
    for iTrial = 1:length(trialMatrix.relative_coherence)
        
        if iTrial == 1
            text = ['You will now see 3 example rounds. \n\n' ...
                'In these 3 example rounds, the second cloud of dots \n\n' ...
                'has HIGHER coherence level than the standard. \n\n' ...
                'A HIGHER coherence level means the dots are more clearly moving in the average direction. \n\n' ...
                'Watch closely to see if you can detect the difference. \n\n\n\n' ...
                'Press "space" to see the first 3 examples.'];
            showtext(text,Gparams);
        elseif iTrial == 4
            text = ['In these examples the difference was big and therefore easy to see. \n\n' ...
                'It can also happen that the difference is smaller and more difficult to see. \n\n\n' ...
                'You will now see 3 example rounds that are more difficult. \n\n' ...
                'In these 3 example rounds, the second cloud of dots \n\n' ...
                'has HIGHER coherence level than the standard. \n\n' ...
                'Watch closely to see if you can detect the difference. \n\n\n\n' ...
                'Press "space" to proceed to the next screen.'];
            showtext(text,Gparams);
        elseif iTrial == 7
            text = ['These were examples where the second cloud has higher coherence.\n\n\n\n' ...
                'You will now see 3 more example rounds. \n\n' ...
                'In these 3 example rounds, the second cloud of dots \n\n' ...
                'has LOWER coherence level than the standard. \n\n' ...
                'A LOWER coherence level means the dots are less clearly moving in the average direction. \n\n\n\n' ...
                'Watch closely to see if you can detect the difference. \n\n\n\n' ...
                'Press "space" to see the next 3 examples.']; 
            showtext(text,Gparams);
        elseif iTrial == 10
            text = ['In these examples the difference was big and therefore easy to see. \n\n' ...
                'It can also happen that the difference is smaller and more difficult to see. \n\n\n' ...
                'You will now see 3 more example rounds that are more difficult. \n\n' ...
                'In these 3 example rounds, the second cloud of dots \n\n' ...
                'has LOWER coherence level than the standard. \n\n' ...
                'Watch closely to see if you can detect the difference. \n\n\n\n' ...
                'Press "space" to proceed to the next screen.'];
            showtext(text,Gparams);
        end
        
        %% ITI
        drawFixation(Gparams);
        Screen('Flip', Gparams.pWindow);
        WaitSecs(1.5);
        
        %% Standard stimulus
        
        for iFrame = 1:Gparams.timing.nframes    
            drawDots(squeeze(standardStimCoord(iTrial,iFrame, :, :)),Gparams);
            drawFixation(Gparams);
            Screen('Flip', Gparams.pWindow);  
        end
        
        %% ISI

        drawFixation(Gparams);
        Screen('Flip', Gparams.pWindow);
        WaitSecs(Gparams.timing.isi);
        
        %% Test Stimulus
        
        for iFrame = 1:Gparams.timing.nframes
            drawDots(squeeze(testStimCoord(iTrial,iFrame, :, :)), Gparams);
            drawFixation(Gparams);
            Screen('Flip', Gparams.pWindow);
        end
        
        %% Fixation
        
        drawFixation(Gparams);
        Screen('Flip', Gparams.pWindow); 
        WaitSecs(1); 
        
    end
      
    WaitSecs(0.5);
   
end

text = ['You have now seen some example rounds with differences in coherence level.\n\n\n\n'...
        'Press "space" to continue with the next part of the instructions.'];
showtext(text,Gparams);

%% --------- Instructions AFC --------- %% 

clear trialMatrix iBlock

%% Generate block and trial structure
nBlocks         = 1;

for iBlock = 1:nBlocks   
    trialMatrix.relative_coherence(iBlock,:) = [30 -25 -20 20 -15 15] / 100;
    
    % Directions of the standard and test stimuli
    trialMatrix.direction(iBlock,:) = [340 40 160 70 300 250];
    
     % Response mapping depends on subject number
    trialMatrix.responseMapping(iBlock,:) = ones(size(trialMatrix.relative_coherence(iBlock,:))) * (mod(Gparams.subjectNumber,2) + 1);
       
end

nTrials = length(trialMatrix.relative_coherence);

for iBlock = 1:nBlocks
    
    DrawFormattedText(Gparams.pWindow, 'Loading stimuli...', 'center', 'center', 255);
    Screen('Flip', Gparams.pWindow);
    
    % preload all the dot coordinates - overwrite this block!
    testStimCoord = nan(nTrials, Gparams.timing.nframes, 2, Gparams.dots.nDots);
    standardStimCoord = nan(nTrials, Gparams.timing.nframes, 2, Gparams.dots.nDots);
    
    for iTrial = 1:nTrials
        testStimCoord(iTrial, :, :, :) = dots(iTrial,iBlock,trialMatrix,0,Gparams);
        standardStimCoord(iTrial, :, :, :) = dots(iTrial,iBlock,trialMatrix,1,Gparams);
    end
    
    WaitSecs(1);
     
    if mean(trialMatrix.responseMapping(iBlock,:)) == 1
        
        text = ['During the task, for each pair of clouds, you will decide whether\n\n' ...
            'the second cloud of dots has a LOWER or HIGHER coherence than the first cloud.\n\n' ...
            'On some rounds this will be more difficult to see than on others.\n\n\n\n' ...
            'Press "space" to proceed to the next screen.'];
        showtext(text,Gparams);
    
        text = ['You will indicate your decision about LOWER or HIGHER coherence with your right hand.\n\n'...
            'If your answer is LOWER, use your index finger to press the "j" button.\n\n'...
            'If your answer is HIGHER, use your middle finger to press the "k" button.\n\n\n\n'...
            'Press "space" to see a visual representation.'];
        showtext(text,Gparams);
    
        DrawFormattedText(Gparams.pWindow, 'LOWER (j)                     HIGHER (k)', 'center', 'center', 255);
        drawFixation(Gparams);
        Screen('Flip', Gparams.pWindow);
        
        WaitSecs(5);
    
    elseif mean(trialMatrix.responseMapping(iBlock,:)) == 2
        
        text = ['During the task, for each pair of clouds, you will decide whether\n\n' ...
            'the second cloud of dots has a HIGHER or LOWER coherence than the first cloud.\n\n' ...
            'On some rounds this will be more difficult to see than on others.\n\n\n\n' ...
            'Press "space" to proceed to the next screen.'];
        showtext(text,Gparams);
        
        text = ['You will indicate HIGHER or LOWER coherence using two buttons.\n\n\n\n'...
            'If your answer is HIGHER, use your index finger to press the "j" button.\n\n'...
            'If your answer is LOWER, use your middle finger to press the "k" button.\n\n\n\n'...
            'Press "space" to see a visual representation.'];
        showtext(text,Gparams);
    
        DrawFormattedText(Gparams.pWindow, 'HIGHER (j)                     LOWER (k)', 'center', 'center', 255);
        drawFixation(Gparams);
        Screen('Flip', Gparams.pWindow);
        
        WaitSecs(5);
        
    end
        
    text = ['You will now see a few example rounds.\n\n' ...
    'NOTE: please do not press any buttons during this example round.\n\n' ...
    'Instead, just observe.\n\n' ...
    'The correct answers will be highlighted with a white frame.\n\n\n\n' ...
    'Press "space" to see some examples...'];
    showtext(text,Gparams);        
    
    
    for iTrial = 1:length(trialMatrix.relative_coherence)
        
        %% Fixation
        drawFixation(Gparams);
        Screen('Flip', Gparams.pWindow);
        
        WaitSecs(1);
       
        
        %% Standard stimulus
        
        for iFrame = 1:Gparams.timing.nframes
            
            drawDots(squeeze(standardStimCoord(iTrial,iFrame, :, :)),Gparams);
            drawFixation(Gparams);
            Screen('Flip', Gparams.pWindow);
                        
        end
        
        %% ISI
        drawFixation(Gparams);
        Screen('Flip', Gparams.pWindow);
        
        WaitSecs(Gparams.timing.isi);
         
        %% Test Stimulus
        
        for iFrame = 1:Gparams.timing.nframes
            
            drawDots(squeeze(testStimCoord(iTrial,iFrame, :, :)),Gparams);
            drawFixation(Gparams);
            Screen('Flip', Gparams.pWindow);
            
        end
        
        drawFixation(Gparams);
        Screen('Flip', Gparams.pWindow);
        WaitSecs(0.5);
         
        if mean(trialMatrix.responseMapping(iBlock,:)) == 1
            DrawFormattedText(Gparams.pWindow, 'LOWER (j)                     HIGHER (k)', 'center', 'center', 255);
        elseif mean(trialMatrix.responseMapping(iBlock,:)) == 2
            DrawFormattedText(Gparams.pWindow, 'HIGHER (j)                     LOWER (k)', 'center', 'center', 255);
        end
        drawFixation(Gparams);
        Screen('Flip', Gparams.pWindow);
        
        WaitSecs(1.5);
        
        % Compute location of frame
        if (sign(trialMatrix.relative_coherence(iBlock,iTrial)) > 0 && trialMatrix.responseMapping(iBlock,iTrial) == 1)...
                || (sign(trialMatrix.relative_coherence(iBlock,iTrial)) < 0 && trialMatrix.responseMapping(iBlock,iTrial) == 2)
            
            frameBaseRect = [0, 0, 200, 50];
            dstRectFrame = CenterRectOnPointd(frameBaseRect, Gparams.center(1) + 150, Gparams.center(2) + 10);
            
        else
            
            frameBaseRect = [0, 0, 200, 50];
            dstRectFrame = CenterRectOnPointd(frameBaseRect, Gparams.center(1) - 150, Gparams.center(2) + 10);
            
        end
        
        Screen('FrameRect', Gparams.pWindow, 255, dstRectFrame);
        if mean(trialMatrix.responseMapping(iBlock,:)) == 1
            DrawFormattedText(Gparams.pWindow, 'LOWER (j)                     HIGHER (k)', 'center', 'center', 255);
        elseif mean(trialMatrix.responseMapping(iBlock,:)) == 2
            DrawFormattedText(Gparams.pWindow, 'HIGHER (j)                     LOWER (k)', 'center', 'center', 255);
        end
        drawFixation(Gparams);
        Screen('Flip', Gparams.pWindow);
        
        WaitSecs(2);         
       
    end
    
    drawFixation(Gparams);
    Screen('Flip', Gparams.pWindow);
    WaitSecs(1);
    
    Screen('Flip', Gparams.pWindow);
    WaitSecs(0.5);
    
    if mean(trialMatrix.responseMapping(iBlock,:)) == 1
        text = ['In the real task, the words LOWER and HIGHER will not appear on the screen.\n\n'...
            'Even though the words do not appear, you still have to indicate your answer\n\n' ...
            'using the "j" and "k" keys.\n\n' ...
            'Make sure you remember which button is which:\n\n' ...
            '"j" = LOWER       "k" = HIGHER.\n\n\n\n' ...       
            'Press "space" to continue.'];
    elseif mean(trialMatrix.responseMapping(iBlock,:)) == 2
        text = ['In the real task, the words HIGHER and LOWER will not appear on the screen.\n\n'...
            'Even though the words do not appear, you still have to indicate your answer\n\n' ...
            'using the "j" and "k" keys.\n\n' ...
            'Make sure you remember which button is which:\n\n' ...
            '"j" = HIGHER       "k" = LOWER.\n\n\n\n' ...       
            'Press "space" to continue.'];
    end
    showtext(text,Gparams);
    
    text = ['Please try to answer as FAST and ACCURATELY as possible.\n\n\n\n'...
        'Tip: you can give you answer as soon as the second cloud comes on the screen.\n\n' ...
        'You do not have to wait for the second cloud to disappear before you can answer.\n\n' ...
        'Instead, press the button as soon as you have made your decision.\n\n\n\n' ...  
        'Press "space" to continue.'];
    showtext(text,Gparams);

    WaitSecs(0.5);
    
    % Feedback instructions
    
    text = ['During training, after you have responded, you will receive feedback\n\n'...
        'about whether the direction you responded was correct or incorrect.\n\n'...
        'If you gave a correct response, you will hear a high pitch tone.\n\n' ...
        'If you gave an incorrect response, you will hear a low pitch tone.\n\n\n\n'...
        'Press "space" to hear the tone for correct responses...'];
    showtext(text,Gparams);

    WaitSecs(0.5);
    
    PsychPortAudio('SetLoop',Gparams.audio.h, Gparams.sound.tonepos(1,1), Gparams.sound.tonepos(1,2));
    PsychPortAudio('Start', Gparams.audio.h); 

    WaitSecs(1);

    text = ['Now press "space" to hear the tone for incorrect responses...'];
    showtext(text,Gparams);

    WaitSecs(0.5);

    PsychPortAudio('SetLoop',Gparams.audio.h, Gparams.sound.tonepos(2,1), Gparams.sound.tonepos(2,2));
    PsychPortAudio('Start', Gparams.audio.h); 

    WaitSecs(1);

    text = ['Importantly, you have only limited time to respond.\n\n'...
            'Try to always respond within the time limit!\n\n'...
            'If you should exceed the time limit,\n\n'...
            'you will hear a longer low pitch tone as a warning.\n\n\n\n'...
            'Press "space" once again to hear the warning tone for a timeout...'];
    showtext(text,Gparams);

    WaitSecs(0.5);

    PsychPortAudio('SetLoop',Gparams.audio.h, Gparams.sound.tonepos(3,1), Gparams.sound.tonepos(3,2));
    PsychPortAudio('Start', Gparams.audio.h); 

    WaitSecs(1);

    text = ['You have finished the instructions!\n\n' ...
        'Please report to the experimenter now.'];
    showtext(text,Gparams);

    %% Cleaning up
    Screen('CloseAll');
    ShowCursor;
    ListenChar(0);
    Priority(0);
    
end

%% Cleaning up
Screen('CloseAll');
ShowCursor;
ListenChar(0);
Priority(0);
