//Psychlops　実験用デモプログラム
//画像が左右に提示され、カーソルキーの左もしくは右を押しどちらかの画像を選択します。
//選択にかかった時間（反応時間）も記録されます。
//デモでは６枚の写真を読み込んだ上で提示しますが、左右に同じ写真が提示されることもあります。
//実験結果は.datファイルとして任意の場所に出力できます。

//注意事項
//画像を読み込む場所、名前はあらかじめ変更（設定）をお願いします。Img_load()内に指定する行があります。
//同様にData_save()内の、データファイルの出力場所、名前も任意のものに変更をお願いします。
//画面の解像度はdisplay_width = 1920, display_height = 1080;としています。ここも任意の大きさに変更可能です。
//フルスクリーン表示の場合にも、画面解像度を設定しておくと、文字の位置の設定が楽かと思います。

#include <psychlops.h>
using namespace Psychlops;

Psychlops::Rectangle fixation;

const int nFACE = 6;//使用する画像の種類

const int nFACE_R=6;//右側の画像の種類
const int nFACE_L=6;//左側の画像の種類

const int repetition = 2;//繰り返し数
const int trial_max = nFACE_R*nFACE_L*repetition;//全試行数

int number[trial_max], conditionR[trial_max], conditionL[trial_max];//試行番号、条件

int result_res[trial_max], result_rt[trial_max];//反応の格納用配列

Psychlops::Image face[nFACE];//画像を読み込みに必要な変数
char load_ch[128];

Psychlops::Clock start, end, timer;//時間の計測に必要な変数
double t1,t2;

//試行前のブランクのながさ(msec)
int blank_duration = 500;

//画面の解像度の指定
const int display_width = 1920, display_height = 1080;

//実験に必要な関数群
void Img_load();//画像の読み込み
void Exp_setting();//実験条件の設定
void Stimulus_display();//刺激の提示
void Response(int TrialNow);//反応の取得
void Data_save();//データの保存
void Halt_exp();//強制終了

//////////////////////////////////////////////////////////////////////////////////////////////
void psychlops_main()
{
    //Canvas display(display_width, display_height, Canvas::window);//ウィンドウで提示したい場合
    Canvas display(Canvas::fullscreen);//フルスクリーンで提示したい場合

    Img_load();
    Exp_setting();
    Stimulus_display();
}

//画像の読み込み
void Img_load()
{
    for (int i = 0; i<nFACE; i++)
    {
        //画像の名前、保存場所を任意のものに変更してください
        sprintf(load_ch, "C:\\Users\\NAKAJIMA\\Desktop\\exp_img\\img_t%d.png",i+1);
        face[i].load(load_ch);
    }
}

void Exp_setting()
{
    //条件の割り振り用の変数の準備//////////
    int conditions[trial_max], tmp_R[nFACE_R], tmp_L[nFACE_L];

    for (int i =0; i<nFACE_R;i++){tmp_R[ i ] = i;}
	for (int i =0; i<nFACE_L;i++){tmp_L[ i ] = i;}

    for (int i = 0; i<trial_max; i++){conditions[i] = i;}
    Math::shuffle(conditions, trial_max);//全ての試行番号をシャッフルする
    ////ここまで////////

    for (int i=0; i<trial_max; i++){
		conditionR[ i ] = tmp_R[ conditions[ i ] % nFACE_R];//シャッフルした試行番号を各条件に割り当てる
		conditionL[ i ] = tmp_L[ (conditions[ i ]/nFACE_R) % nFACE_L];
		//condition3[ i ] = tmp_3[ (conditions[ i ]/(nFACE_R*nFACE_L)) % nCOND_3];//三番目の独立変数を使う場合
		number[ i ] = i+1;
	}
}

//刺激の提示
void Stimulus_display() 
{

    while(!Keyboard::spc.pushed())
    {
        Display::clear(Color(0.8,0.8,0.8));
        Display::msg(L"スペースキーを押してください",display_width/2-200, display_height/2, Color::black);
        Display::flip();
    }

    for(int TrialNow = 0; TrialNow<trial_max; TrialNow++)
    {
        //試行前のブランクの表示
        Display::clear(Color(0.8,0.8,0.8));
        fixation.set(10,10).centering().draw(0.0);
        Display::flip();

        timer.update();t1 = timer.at_msec();
        while(t2-t1<blank_duration){timer.update();t2 = timer.at_msec();}

        //刺激の表示
        Display::clear(Color(0.8,0.8,0.8));
        fixation.set(10,10).centering().draw(0.0);
        face[ conditionL[TrialNow] ].centering().shift(400,0).draw();
        face[ conditionR[TrialNow] ].centering().shift(-400,0).draw();

        Display::msg(L"どちらの写真が好きですか？Left or Right",display_width/2-200, display_height/2+300, Color::black);
        Display::flip();

        start.update();
        Response(TrialNow);
    }
    Data_save();
}

//反応の取得
void Response(int TrialNow)
{
    Input::refresh();
    while(true)
    {
        if(Keyboard::left.pushed())
        {
            end.update();
            result_rt[TrialNow] = (end-start).at_msec();
            result_res[TrialNow] = conditionL[TrialNow];
            break;
        }
        if(Keyboard::right.pushed())
        {
            end.update();
            result_rt[TrialNow] = (end-start).at_msec();
            result_res[TrialNow] = conditionR[TrialNow];
            break;
        }
        if(Keyboard::esc.pushed())
        {
            Halt_exp();
        }
    }

}

//データの保存
void Data_save()
{
    Data::savearray("C:\\Users\\NAKAJIMA\\Desktop\\exp_data_%TIME_.dat","", trial_max, number, conditionR,conditionL,result_res,result_rt);

	while (!Keyboard::spc.pushed()){
		Display::clear(Color(0.8,0.8,0.8));
		Display::msg(L"ありがとうございました。", display_width/2-200, display_height/2, Color::white);
		Display::flip();
	}

    /*
    //名前を指定して保存することもできます
    char file_datasave[255];
    sprintf(file_datasave,"C:\\Users\\NAKAJIMA\\Desktop\\exp_data.dat");
    Data::savearray(file_datasave,"", trial_max, number, conditionR,conditionL,result_res,result_rt);
    */
}

//強制終了
void Halt_exp()
{
    Input::refresh();
	while (!Keyboard::esc.pushed()){
		Display::clear(Color(0.8,0.8,0.8));
		Display::msg(L"中断されました。escで終了します。", display_width/2-200, display_height/2, Color::red);
		Display::flip();
	}
	exit(1);
}