% function hyperscanCooperation
% arguments: 
% atNIRS (0,1)
% subjectName (string)
% istest (4 trial, 5 real)
% switch nargin
%     case 0
%         atNIRS = 0;
%         subjectName = 'noname';
%         istest=5;
%     case 1
%         subjectName= 'noname';
%         istest=5;
%     case 2
%         istest=5;
% end
function subjectData = hyperscanCooperation(atNIRS, subjectName, istest)

switch nargin
    case 0
        atNIRS = 0;
        subjectName = 'noname';
        istest=5;
    case 1
        subjectName= 'noname';
        istest=5;
    case 2
        istest=5;
end
    
timedistribution = 1;

% In each trial, a gray circle appears and stays on the screen for
% designated amount of time via the variable 'interval' which can be
% between (.5-12s). Then it changes to green until the correct key press or
% after 'duration' (4 seconds). Participants are supposed to press button
% 'z' and '/' as close together as possible when the gray circle is filled with green. If there
% is no button press, the reaction time will equal 0 and they will both
% lose. they only win when the reaction time is less than
% [(rt1+rt2)/2]*alpha.  together they start with 100 points and every time
% they get their targeted reaction time they gain a point, otherwise they
% lose a point. they also lose a point if one of them does not press a
% button or if they both do not press their buttons. Reaction time will
% remain 0 if they do not press a button.
%
% Usage: subjectData = Gauthier_2player(subjectName, istest, timedistribution)
%
%
% If istest = 1 or 4, then only 5 trials, otherwise 40 trials in 20 trial blocks
% (2 blocks total) with 30 seconds rest between each block and at the beginning and end.
%
% If timedistribution = 1, it means flat distribution over 4, 6, 8, 10, 12s
% If timedistribution = 0, it means non flat distribution w/  10     8
% 4     8    10 for 4, 6, 8, 10, 12s
% If timedistribution = -1, it means iso-response distribution w/  12
% 10 8 6 4 for 4, 6, 8, 10, 12s
% if istest = 5, there are 40 trials where the timedistribution ins
% shuffled randomly between .5 and 1.5 seconds.
%
% Example:
%   readygo('chris_dan', 5, 1)
%
% interval, intertrialinterval, and keyname calculations by Xu Cui
% Author: Chris Gauthier. August, 2010


%KbName('UnifyKeyNames');

% makes room for 16 decimal points
format long;

marksignal = 0;

                %10s Prescan
if atNIRS ==1
    com1 = serial('COM1','BaudRate',9600,'DataBits',8,'Parity','none','StopBits',1);
    fopen(com1);
    st   = sprintf('ST\r\n');% Start
    mark1 = sprintf('F1\r\n');% Mark 1 Tapping Onset/Offset
    mark2 = sprintf('F2\r\n');% Mark 1 Tapping Onset/Offset
    ed   = sprintf('ED\r\n');% End


    %/////////// Send to Commands for OT /////////////
    fwrite(com1,st);disp('Send ST');    %Start
    pause(10);                          %10s Prescan
end
%addpath(genpath('C:\Documents and Settings\nirs\My Documents\MATLAB\cgauthie'));

if istest
    numRepeat = [1];
else
    numRepeat = [10];
end



reaction1 = []; %when user1 presses the button after they see green
reaction2 = []; %when user2 presses the button after they see green
eventready = []; %when it is gray
eventgo = []; %when it becomes green
eventwarning = [];
eventWrong = []; %reaction time of a wrong key press
difference = [];
winthreshold = [];
rt1 = 0;
rt2 = 0;
points = 100;
exit = 0;
w =0;
x= 0;
zarray =[];
slasharray =[];
small1=0;
small2=0;
block = 0;
restbreak = 20;





% This is a set of 40 trials with a progressbar(via line 36) and a flat
% distribution. 'interval' is a 1x40 matrix of numbers 4,6,8,10,12.
% intertrialinterval is a 1x40 matrix of numbers such as 3.220 up to 12.992
% in random order. The matrix is saved as a .mat file
if istest == 0 && knowwhentopress == 0 && timedistribution == 1
    interval = 2*(Shuffle(repmat([1:4],1,numRepeat))+1); % unit is seconds and numRepeat is = 10
    intertrialinterval = 2*(Shuffle(repmat([1:4],1,numRepeat))+1); % unit is seconds
    intertrialinterval = intertrialinterval + 2*rand(size(intertrialinterval))-1;
    save([subjectName 'sequence.mat'], 'interval', 'intertrialinterval'); % ex chrissequence.mat
    % this contains the matricies 'interval' and 'intertrialinterval'
    
end


% The set is 40 trials and the distribution is a 10, 8, 4, 8, 10 for the 4,
% 6, 8, 10, 12 second delays
if timedistribution == 0 && istest == 0
    interval = [4*ones(1, 10), 6*ones(1, 8), 8*ones(1, 4), 10*ones(1, 8), 12*ones(1, 10)];
    interval = Shuffle(interval); % after this line there is a 1x50 matrix with
    % a shuffled set of 14 fours, 8 sixes, 6 eights, 8 tens and 14 twelves.
    intertrialinterval = 2*(Shuffle(repmat([1:4],1,numRepeat))+1); % unit is seconds
    intertrialinterval = intertrialinterval + 2*rand(size(intertrialinterval))-1;
end

% iso-response distribution so it completes a 1x40 matrix with 14 fours
% 10 sixes, 8 eights, 6 tens and 2 twelves.
if timedistribution == -1 && istest == 0
    interval = [4*ones(1, 14), 6*ones(1, 10), 8*ones(1, 8), 10*ones(1, 6), 12*ones(1, 2)];
    interval = Shuffle(interval);
    intertrialinterval = 2*(Shuffle(repmat([1:6],1,numRepeat))+1); % unit is seconds and numRepeat = 10
    intertrialinterval = intertrialinterval + 2*rand(size(intertrialinterval))-1;
    % this is a second matrix of 1x40 which has values from 2.xxxx to
    % 12.xxxx in a random order
end

% this is a 5 trial test.
if istest == 1
    interval = 2*(Shuffle(repmat([1:6],1,numRepeat))+1); % unit is seconds and numRepeat = 1
    intertrialinterval = 2*(Shuffle(repmat([1:6],1,numRepeat))+1); % unit is seconds
    disp ('Time between gray circles:');
    disp (intertrialinterval);
    disp('Time between green circles:');
    disp(interval);
end

%programmer error check - its really short intervals.
if istest == 4
    interval = 2*ones(1,5);
    intertrialinterval = ones(1,5);
elseif istest == 5
    interval = 2*ones(1,40);
    %intertrialinterval = ones(1,40);
    intertrialinterval = Shuffle(repmat([6:15],1,4)/10);
end

%matrix of trials to access for trials with 'index'
trials = [interval', intertrialinterval'];
whichTrial = [1:length(trials)];


%window colors
frontcolor = 255; % white
readycolor = 100;
window=Screen('OpenWindow', 0, 0);
duration = 4; %gray circle is on screen for this time before turning green
rect = Screen('Rect',window);

% window locations
xcenter = .5*rect(3);
ycenter = .5*rect(4);
playerdisplayY = ycenter - 50;
player1displayX = xcenter - 350;
player2displayX = xcenter + 300;

radius = 90;
outline = [xcenter-radius ycenter-radius xcenter+radius ycenter+radius];
greencircle = [xcenter-(radius-20) ycenter-(radius-20) xcenter+(radius-20) ycenter+(radius-20)];
gocolor = [0 255 0]; %green color
losecolor = [255 0 0];

%escape codes
[keyIsDown, seconds, keyCode] = KbCheck;
%escapeKey = KbName('ESCAPE'); %use for mac
%escapeKey = KbName('escape'); % use for windows
escapeKey =27;
%while KbCheck; end
%escapeMac = keyCode(41);
%escapeWin = keyCode(54);

%Hide the cursor
HideCursor;
bgcolor =0;
Screen('FillRect', window, bgcolor);
if keyIsDown
    b = KbName(keyCode);
    disp(b)
    if keyCode(escapeKey)
        exit = 1;
        Screen ('CloseAll');
        ShowCursor;
    end
end

%Key Press
targetKey1 = KbName('z');
targetScan1 = KbName('z');
targetKey2 = KbName('/');
targetScan2 = KbName('/?');
%for the error message if they press the wrong key when there is a green
%circle:
target1 = 'z';
target2 = '/?';



%%% INSTRUCTIONS %%%
sz = Screen('Rect', window); %gets a measurement of monitor
%how to escape program
%Screen(window,'TextSize',50);
%Screen (window, 'DrawText', 'To exit, press the escape key. We will begin in 3 seconds.', 0, ycenter, frontcolor);
%Screen(window, 'Flip');
%tic
%while toc <3
%    ;
%end
%show the instructions for three seconds
showinstruction(window, frontcolor, sz);
clearscreen(window);

if istest ~= 4
rest(window, xcenter, playerdisplayY, frontcolor);
end


%%% TRIALS %%%
% This code will show a blank screen for a designated amount of time, then
% move to a gray hollowed circle for a designated amount of time (4, 6, 8,
% 10, 12 seconds via variable 'interval' and then that will fill in with
% green for up to 4 seconds or until the participant presses the correct
% key.
%

for i=1:length(trials)
    
    selectedrow = whichTrial(i);
    index = trials(selectedrow,:);
    x = 1;
    
    %clears the screen for the specified time (in seconds)
    %via the intertrialinterval
    timerSecs = GetSecs;
    while GetSecs < timerSecs + index(1)
        [keyIsDown, seconds, keyCode] = KbCheck;
        while KbCheck; end
        %warning if they hit a key too early
        if keyIsDown
            if keyCode(escapeKey)
                exit = 1;
                break;
            end
            
            %flashes warning
            eventwarning = [eventwarning GetSecs];
            warning(eventwarning, timerSecs, window, frontcolor, xcenter, ycenter);
            FlushEvents(['keyDown']);
            timerSecs = GetSecs;
        end
        
        %show a blank screen
        clearscreen(window);
    end
    
    if      exit == 1
        break;
    end
    % Put Gray Circle on
    timerSecs = GetSecs; % start timer
    eventready = [eventready timerSecs];
    while GetSecs < timerSecs + index(2)
        [keyIsDown, seconds, keyCode] = KbCheck;
        while KbCheck; end
        %warning if they hit a key too early
        if keyIsDown
            if keyCode(escapeKey)
                exit = 1;
                break;
            end
            eventwarning = [eventwarning GetSecs];
            warning(window, frontcolor, xcenter, ycenter);
            timerSecs = GetSecs;
        end
        %show the gray circle
        Screen(window,'FrameOval', readycolor, outline, 12);
        Screen(window, 'Flip');
        marksignal = marksignal + 1;
        if marksignal == 1
        if atNIRS ==1
        fwrite(com1, mark1);
        end
        
        end
    end
    if      exit == 1
        break;
    end
    
    % Green Circle on
    rt1 = 0;
    rt2 = 0;
    startTime = GetSecs;
    eventgo = [eventgo startTime];
    a = 0;
    b = 0;
    marksignal = 0;
    while GetSecs < startTime + duration
        % Check the state of the keyboard.
        [ keyIsDown, seconds, keyCode ] = KbCheck;
        
        % If the user is pressing a key, then display its code number and name.
        if keyIsDown
            format long
            % Note that we use find(keyCode) because keyCode is an array.
            % See 'help KbCheck'
            nowTime = GetSecs - startTime;
            
            keyname = KbName(keyCode);
            %key = find(keyCode);
            
            if keyCode(escapeKey)
                break;
            end
            
            if iscell(keyname)
                keyname = [keyname{1} keyname{2}];
            end
            
              % If the user holds down a key, KbCheck will report multiple
            % events. This is why we put them in an array and then choose
            % the smallest one.
            
                if strfind(keyname, 'z')
                zarray = [zarray nowTime];
                a=1;
                end
                
                if strfind(keyname, '/')
                slasharray = [slasharray nowTime];
                b = 1;
                end
% fixxx 

            %if test ~= targetKey1 && test ~= targetKey2
            %    wrong(eventWrong, seconds, window, target1, target2, frontcolor, readycolor, outline, gocolor, greencircle);
            %end

            
            %begin error check:
            %if(iscell(keyname))
                %fprintf('%f %i  %s%s\n', nowTime, find(keyCode), keyname{1}, keyname{2});
            %    disp([num2str(nowTime) ' ' keyname{1} ' ' keyname{2}]);
            %else
           %     disp([num2str(nowTime) ' ' keyname]);
                %fprintf('%f %i  %s\n', nowTime, find(keyCode), keyname);
            %end
            %end error check. 
        end
        
        %after two correct button presses, the program moves on.
        if a ==1 && b ==1
            break;
        end
        marksignal = marksignal + 1;
        if atNIRS==0
            com1=0;
            mark2=0;
        end
        greenCircle(window, readycolor, outline, gocolor, greencircle, atNIRS, marksignal, com1, mark2);
       
    end
            marksignal = 0;
    if  exit == 1
        break;
    end
    
    
    %search for first reaction time
    if isempty(zarray) ~=1
    small1 = zarray(1);
   % disp(length(zarray));
    for i = 1:length(zarray)
        if small1 > zarray(i)
            small1 = zarray(i);
        end
    end
        rt1 = small1;
    end
    
    if isempty(slasharray) ~=1
    small2 = slasharray(1);
    for i = 1:length(slasharray)
        if small2 > slasharray(i)
            small2 = slasharray(i);
        end
    end
    rt2 = small2;
    end
    
    
    %calculate difference
    diff = abs(rt1 - rt2);
    alpha = .25;
    win = ((rt1+rt2)/2)*alpha;
    winthreshold = [winthreshold win];
    difference = [difference diff];
    %diffdisplay = diff*1000;
    %screen that displays difference and reaction times
    Screen(window,'TextSize',90);
    if rt1<rt2
        if rt1 == 0
        Screen (window, 'DrawText', sprintf('*'), player1displayX,playerdisplayY, frontcolor);%player 1
        Screen (window, 'DrawText', sprintf('+'), player2displayX,playerdisplayY, gocolor); %player 2
        else
        Screen (window, 'DrawText', sprintf('+'), player1displayX,playerdisplayY, gocolor); %player 1
        Screen (window, 'DrawText', sprintf('-'), player2displayX,playerdisplayY, frontcolor);%player 2
        end
    elseif rt1>rt2
        if rt2==0
        Screen (window, 'DrawText', sprintf('+'), player1displayX,playerdisplayY, gocolor); %player 1
        Screen (window, 'DrawText', sprintf('*'), player2displayX,playerdisplayY, frontcolor);%player 2
        else
        Screen (window, 'DrawText', sprintf('-'), player1displayX,playerdisplayY, frontcolor);%player 1
        Screen (window, 'DrawText', sprintf('+'), player2displayX,playerdisplayY, gocolor); %player 2
        end
    elseif rt1 == rt2
        if rt1 == 0 && rt2 == 0
        Screen (window, 'DrawText', sprintf('*'), player1displayX,playerdisplayY, frontcolor); %player1
        Screen (window, 'DrawText', sprintf('*'), player2displayX,playerdisplayY, frontcolor);% player 2
        else
        Screen (window, 'DrawText', sprintf('+'), player1displayX,playerdisplayY, gocolor); %player1
        Screen (window, 'DrawText', sprintf('+'), player2displayX,playerdisplayY, gocolor);% player 2
        end
    end
    format long
    reaction1 = [reaction1 rt1];
    reaction2 = [reaction2 rt2];
    %Screen (window, 'DrawText', sprintf('%.1f ms', diffdisplay), xcenter-130,ycenter+50, frontcolor);
    Screen(window,'TextSize',90);
    if diff <= win && rt1 ~=0 && rt2 ~= 0
        points = points + 1;
        Screen (window, 'DrawText', sprintf('Win! %d', points), xcenter-190,90, gocolor);
    elseif diff>win || rt1 ==0 || rt2 ==0 || rt1 ==0 && rt2 ==0 && diff ==0
        points = points - 1;
        Screen (window, 'DrawText', sprintf('Lose %d', points), xcenter-210,90, losecolor);
        
    end
    Screen(window, 'Flip');
    tic
    while toc < 4
        ;
    end
    zarray = [];
    slasharray = [];
    block = block + 1;
     if block == restbreak 
        rest(window, xcenter, playerdisplayY, frontcolor);
    end
end





%ending screen
if exit ==1
    Screen(window,'TextSize',30);
    Screen(window,'DrawText',sprintf('Ok, goodbye! Total: %d', points), 100, 100, frontcolor);
else
    if istest ~=4
    %rest for 30 seconds to get back to baseline
rest(window, xcenter, playerdisplayY, frontcolor);
    end
    % Thank you Screen
    Screen(window,'TextSize',30);
    Screen(window,'DrawText',sprintf('Experiment Complete! Thank You. Total: %d', points), 100, 100, frontcolor);
end
tic
Screen(window, 'Flip');
while toc < 1
    ;
end

% If they pressed the escape key, the program exits
if exit ==1
    Screen('CloseAll');
    ShowCursor;
end


%%% Saving Data in a Struct %%%
subjectData.reaction1 = reaction1;
subjectData.reaction2 = reaction2;
subjectData.difference = difference;
subjectData.eventgo = eventgo;
subjectData.eventready = eventready;
subjectData.eventwarning = eventwarning;
%subjectData.eventWrong = eventWrong;
subjectData.winthreshold = winthreshold;
c = clock;
date = datestr(now, 'mm_dd_yy');
hour = num2str(c(4));
minute = num2str(c(5));
seconds = num2str(round(c(6)));

save(['readygo_collaboration_' '_' subjectName '_' date '_' hour '_' minute '_' seconds], 'subjectData', 'intertrialinterval', 'interval');

%RestrictKeysForKbCheck([]);
Screen('CloseAll'); %close all windows
ShowCursor;

if atNIRS == 1
    fwrite(com1,ed);disp('Send ED');    %End
    %//////////// Close Serial Port ///////////////// 
    fclose(com1);%END NIRS
    clear com1;%delete(com1);
    clear st;clear mark;clear ed;
end
return



%%%%%%%%%%%%   FUNCTIONS   %%%%%%%%%%%%%


function showinstruction(window, color, screensize)
% This function puts the instructions on the screen
%   sz = screensize;
%   Screen(window,'DrawText',sprintf('Press the button as quickly as possible when you see'), 100, sz(4)/2, color);
% 	rect = [sz(3)/2-100 sz(4)/2-100 sz(3)/2+100 sz(4)/2+100] - [200 0 200 0];
% 	Screen(window,'FrameOval', 100, rect, 20);
% 	rect = [sz(3)/2-100+20 sz(4)/2-100+20 sz(3)/2+100-20 sz(4)/2+100-20] - [200 0 200 0];
% 	Screen(window,'FillOval', [0 255 0], rect);
%   Screen(window, 'DrawLine', color, 0, 0, 100, 100);
qq = imread('instruction1.jpg');
Screen(window, 'putimage', qq);
Screen(window, 'Flip');
tic
while toc < 1.5
    ;
end
return

% Screen goes blank
function clearscreen(window)
Screen(window,'FillRect', 0);
Screen(window, 'Flip');
return

%if they hit a wrong key
function [eventWrong] = wrong(eventWrong, seconds, window, target1, target2, frontcolor, readycolor, outline, gocolor, greencircle)

eventWrong = [eventWrong seconds];
Screen(window,'TextSize',50);
Screen (window, 'DrawText', sprintf('You are supposed to press "%s" and "%s"! Hurry, try again', target1, target2), 0,0, frontcolor);
Screen(window,'FrameOval', readycolor, outline, 12);
Screen(window,'FillOval', gocolor, greencircle);
Screen(window, 'Flip');
tic
while toc < .5
    ;
end
return

%flashes warning
function warning(window, frontcolor, xcenter, playerdisplayY)
Screen(window,'TextSize',40);
clearscreen(window);
Screen (window, 'DrawText', 'Too Early', xcenter - 100, playerdisplayY, frontcolor);
Screen(window, 'Flip');
tic
while toc <.5
    ;
end
return

%flashes green circle
function greenCircle(window, readycolor, outline, gocolor, greencircle, atNIRS, marksignal, com1, mark2)
Screen(window,'FrameOval', readycolor, outline, 12);
Screen(window,'FillOval', gocolor, greencircle);
Screen(window, 'Flip');
if marksignal == 1
if atNIRS ==1
fwrite(com1, mark2);
end
end
return

function rest(window, xcenter, playerdisplayY, frontcolor)
Screen(window,'TextSize',40);
Screen(window,'DrawText',sprintf('Rest'), xcenter - 50, playerdisplayY, frontcolor);
Screen(window, 'Flip');
tic
while toc < 30
    ;
end
return

