00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "Component/ModelManager.H"
00039 #include "Image/Image.H"
00040 #include "Psycho/PsychoDisplay.H"
00041 #include "Psycho/EyeTrackerConfigurator.H"
00042 #include "Psycho/EyeTracker.H"
00043 #include "Psycho/PsychoOpts.H"
00044 #include "Component/EventLog.H"
00045 #include "Component/ComponentOpts.H"
00046 #include "Raster/Raster.H"
00047 #include "Util/MathFunctions.H"
00048 #include "Util/Types.H"
00049 #include "GameBoard/basic-graphics.H"
00050 #include <sys/types.h>
00051 #include <dirent.h>
00052 #include <errno.h>
00053 #include <vector>
00054 #include <string>
00055 #include <iostream>
00056 #include <SDL/SDL.h>
00057 #include <SDL/SDL_image.h>
00058 #include <stdio.h>
00059 #include <stdlib.h>
00060 #include <sstream>
00061 #include <time.h>
00062 #include "Image/DrawOps.H"
00063 #include "GameBoard/resize.h"
00064 #include <iostream>
00065 #include <fstream>
00066 #include <set>
00067 #include <algorithm>
00068 #include <ctime>
00069
00070 #ifndef INVT_HAVE_LIBSDL_IMAGE
00071 #include <cstdio>
00072 int main()
00073 {
00074 fprintf(stderr, "The SDL_image library must be installed to use this program\n");
00075 return 1;
00076 }
00077
00078 #else
00079
00080
00081
00082 using namespace std;
00083
00084
00085
00086 ModelManager manager("Psycho-WM");
00087 nub::soft_ref<PsychoDisplay> d(new PsychoDisplay(manager));
00088 map<uint,uint> testMap ;
00089 map<string,string> argMap ;
00090 map<string,vector<SDL_Rect*>*> clipsmap;
00091
00092
00093
00094
00095 template <class T> std::string stringify(T i)
00096 {
00097 ostringstream o ;
00098 o << i ;
00099 return o.str();
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 SDL_Surface* getButtonImage(string label , PixRGB<byte> txtcolor=PixRGB<byte>(0,0,0) , PixRGB<byte> bgcolor=PixRGB<byte>(255,255,255) ,Point2D<int> size = Point2D<int>(100,100) ,PixRGB<byte> bordercolor=PixRGB<byte>(0,0,0) , int border=3){
00112 Image<PixRGB<byte> > textIm(d->getWidth(),d->getHeight(),ZEROS);
00113 textIm.clear(bgcolor);
00114 writeText(textIm, Point2D<int>((size.i - label.length()*10)/2,(size.j-20) /2),label.c_str(),txtcolor,bgcolor);
00115 SDL_Surface *surf = d->makeBlittableSurface(textIm , true);
00116 Uint32 bc = d->getUint32color(bordercolor);
00117 drawRectangle(surf,bc,0,0,size.i -1,size.j -1 ,border);
00118 SDL_Surface* blank =getABlankSurface(size.i , size.j);
00119 SDL_Rect clip;
00120 clip.x = 0 ;
00121 clip.y = 0 ;
00122 clip.w = size.i ;
00123 clip.h = size.j ;
00124 apply_surface(0,0,*surf,*blank,clip);
00125 dumpSurface(surf) ;
00126 return blank ;
00127 }
00128
00129
00130
00131
00132
00133
00134 SDL_Surface* getKeyPad(string alphabet,map<string , SDL_Rect>& buttmap){
00135 SDL_Surface* pad= getABlankSurface(d->getWidth()/4,d->getHeight()/3);
00136 SDL_Rect clip;
00137 clip.x=0;
00138 clip.y=0;
00139 int numofrows = alphabet.size()/3 +1;
00140 if(alphabet.size()%3 != 0 ) numofrows++ ;
00141 int numofcolumns = 3 ;
00142 clip.w= pad->w / numofcolumns ;
00143 clip.h = pad->h / numofrows ;
00144
00145
00146 for( int i = 0 ; i < numofrows*3 ; i++){
00147 SDL_Surface* but ;
00148 if((uint)i < alphabet.size()){
00149 but = getButtonImage(alphabet.substr(i,1),PixRGB<byte>(0,0,0),PixRGB<byte>(255,255,255),Point2D<int>(pad->w / numofcolumns , pad->h / numofrows),PixRGB<byte>(255, 98 , 25),3);
00150 }else{
00151 but = getButtonImage(" ",PixRGB<byte>(0,0,0),PixRGB<byte>(255,255,255),Point2D<int>(pad->w / numofcolumns , pad->h / numofrows),PixRGB<byte>(255, 98 , 25),3);
00152 }
00153
00154 SDL_Rect cl ;
00155 cl.x = ((i)%numofcolumns)*(pad->w)/numofcolumns ; cl.y= ((i)/numofcolumns)*((pad->h)/numofrows) ;
00156 cl.w = clip.w ;
00157 cl.h = clip.h ;
00158 apply_surface( cl.x , cl.y ,*but,*pad,clip);
00159 if((uint)i < alphabet.size()) buttmap[alphabet.substr(i,1)] = cl ;
00160 dumpSurface(but);
00161 }
00162 SDL_Rect cl1 ;
00163 cl1.x = 0 ; cl1.y= (numofrows-1)*((pad->h)/numofrows) ;
00164 cl1.w = clip.w ;
00165 cl1.h = clip.h ;
00166 buttmap["!"] = cl1 ;
00167 SDL_Surface* but = getButtonImage(string("<-"),PixRGB<byte>(0,0,0),PixRGB<byte>(255,255,255),Point2D<int>(pad->w / numofcolumns , pad->h / numofrows),PixRGB<byte>(255, 98 , 25),3);
00168 apply_surface(0, (numofrows-1)*((pad->h)/numofrows),*but,*pad,clip);
00169 dumpSurface(but);
00170 SDL_Rect cl2 ;
00171 cl2.x = (pad->w)/numofcolumns ; cl2.y= (numofrows-1)*((pad->h)/numofrows) ;
00172 cl2.w = clip.w ;
00173 cl2.h = clip.h ;
00174 buttmap[" "] = cl2 ;
00175 but = getButtonImage(string("spc"),PixRGB<byte>(0,0,0),PixRGB<byte>(255,255,255),Point2D<int>(pad->w / numofcolumns , pad->h / numofrows),PixRGB<byte>(255, 98 , 25),3);
00176 apply_surface((pad->w)/numofcolumns, (numofrows-1)*((pad->h)/numofrows),*but,*pad,clip);
00177 dumpSurface(but);
00178 SDL_Rect cl3 ;
00179 cl3.x = 2*(pad->w)/numofcolumns ; cl3.y= (numofrows-1)*((pad->h)/numofrows) ;
00180 cl3.w = clip.w ;
00181 cl3.h = clip.h ;
00182 buttmap["*"] = cl3 ;
00183 but = getButtonImage(string("Ok"),PixRGB<byte>(0,0,0),PixRGB<byte>(255,255,255),Point2D<int>(pad->w / numofcolumns , pad->h / numofrows),PixRGB<byte>(255, 98 , 25),3);
00184 apply_surface(2*(pad->w)/numofcolumns, (numofrows-1)*((pad->h)/numofrows),*but,*pad,clip);
00185 dumpSurface(but);
00186 return pad ;
00187 }
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 string getPressedButtonCommand(map<string , SDL_Rect>& buttmap,Point2D<int> offset=Point2D<int>(0,0)){
00198 int quit = 0 ;
00199 string s ;
00200 SDL_Event event ;
00201 while( quit!=2 ){
00202 while( SDL_PollEvent( &event ) ) {
00203 if(event.type == SDL_MOUSEBUTTONDOWN && event.button.button == SDL_BUTTON_LEFT ){
00204 for( map<string , SDL_Rect>::iterator it = buttmap.begin() ; it!=buttmap.end() ; ++it){
00205 if(event.button.x >= (it->second).x + offset.i && event.button.x <= (it->second).x + (it->second).w + offset.i && event.button.y >= (it->second).y+ offset.j && event.button.y <= (it->second).y + (it->second).h + offset.j) {
00206 quit = 2 ;
00207 s = it->first ;
00208 break;
00209 }
00210
00211 }
00212 }
00213
00214 }
00215 }
00216 return s ;
00217
00218 }
00219
00220
00221
00222
00223
00224
00225
00226 string getDigitSequenceFromSubject(string alphabet="0123456789" , uint maxl = 7 ){
00227 d->showCursor(true) ;
00228
00229 map<string , SDL_Rect>* buttmap = new map<string , SDL_Rect>();
00230
00231 SDL_Surface * keypad = getKeyPad(alphabet,*buttmap);
00232
00233 SDL_Rect offset ;
00234 offset.x = (d->getWidth() - keypad->w) /2;
00235 offset.y = (d-> getHeight() - keypad->h) /2;
00236
00237 d->displaySDLSurfacePatch(keypad , &offset,NULL , -2,false, true);
00238
00239 string p = string("") ;
00240
00241 string tp = string("");
00242
00243 while( tp.compare("*")!=0 ){
00244
00245 SDL_Surface* dp = getButtonImage(p ,PixRGB<byte>(195,60,12) ,PixRGB<byte>(255,255,255) ,Point2D<int>(d->getWidth()/6,d->getHeight() /15) ,PixRGB<byte>(0,25,180) , 4) ;
00246 SDL_Rect offs ; offs.x = (d->getWidth() - dp->w) /2 ; offs.y = d->getHeight()/6 ;
00247 d->displaySDLSurfacePatch(dp , &offs , NULL , -2 , false ,true ) ;
00248
00249 tp = getPressedButtonCommand(*buttmap,Point2D<int>(offset.x,offset.y)) ;
00250 dumpSurface(dp) ;
00251 if(tp.compare("!")==0 && p.size()>=0 ) {
00252 if (p.size()>0) p = p.substr(0,p.size()-1) ;
00253 }else{
00254 if(p.size() < maxl && tp.compare("*")!=0) {
00255 p +=tp ;
00256 }
00257
00258 }
00259
00260 }
00261 buttmap = 0 ;
00262 dumpSurface(keypad) ;
00263 d->clearScreen() ;
00264 return p ;
00265
00266 }
00267
00268
00269
00270
00271 int addArgument(const string st,const string delim="="){
00272 int i = st.find(delim) ;
00273 argMap[st.substr(0,i)] = st.substr(i+1);
00274
00275 return 0 ;
00276 }
00277
00278 std::string getArgumentValue(string arg){
00279 return argMap[arg] ;
00280 }
00281
00282 std::string getUsageComment(){
00283
00284 string com = string("\nlist of arguments : \n");
00285
00286 com += "\nlogfile=[logfilename.psy] {default = psycho-wm-subtraction.psy}\n" ;
00287 com += "\nmemo=[a_string_without_white_space]\n";
00288 com += "\nrange=[x-y](the size of string){default=200-500} \n";
00289 com += "\nsubject=[subject_name] \n" ;
00290 com += "\ndelay=[>0] (number of micro seconds){default=30000000}\n";
00291 com += "\ntest-rounds=[>1] (number of tests ) {default=5}\n";
00292 com += "\ndigit-onset=[>1] (number of frames that the string will remain onset ){default=10}\n";
00293 com += "\nsubtraction-step=[>0] (the subtraction number){default=3} ";
00294 return com ;
00295 }
00296
00297
00298 extern "C" int main(const int argc, char** argv)
00299 {
00300
00301 MYLOGVERB = LOG_INFO;
00302
00303 argMap["experiment"]="subtraction-working-memory";
00304 argMap["logfile"]="psycho-wm-subtraction.psy" ;
00305 argMap["string-size"]="5" ;
00306 argMap["test-rounds"]="5";
00307 argMap["subject"]="" ;
00308 argMap["memo"]="" ;
00309 argMap["digit-onset"]="10" ;
00310 argMap["range"]="200-500";
00311 argMap["delay"]="30000000" ;
00312 argMap["subtraction-step"]="3" ;
00313 manager.addSubComponent(d);
00314 nub::soft_ref<EventLog> el(new EventLog(manager));
00315 manager.addSubComponent(el);
00316 d->setEventLog(el);
00317 nub::soft_ref<EyeTrackerConfigurator>
00318 etc(new EyeTrackerConfigurator(manager));
00319 manager.addSubComponent(etc);
00320
00321 if (manager.parseCommandLine(argc, argv,
00322 "at least one argument needed", 1, -1)==false){
00323 cout<<getUsageComment()<<endl;
00324 return(1);
00325 }
00326
00327 for(uint i = 0 ; i < manager.numExtraArgs() ; i++){
00328 addArgument(manager.getExtraArg(i),std::string("=")) ;
00329 }
00330
00331 manager.setOptionValString(&OPT_EventLogFileName, argMap["logfile"]);
00332 manager.setOptionValString(&OPT_EyeTrackerType, "ISCAN");
00333 nub::soft_ref<EyeTracker> eyet = etc->getET();
00334 d->setEyeTracker(eyet);
00335 eyet->setEventLog(el);
00336
00337
00338
00339 manager.start();
00340 for(map<string,string>::iterator it= argMap.begin(); it!= argMap.end() ; ++it) d->pushEvent("arg:"+ it->first+" value:"+it->second ) ;
00341
00342 d->clearScreen();
00343 d->displayISCANcalib();
00344 d->waitForMouseClick();
00345 d->displayText("Here the experiment starts! click to start!");
00346 d->waitForMouseClick();
00347 d->clearScreen();
00348
00349
00350 int numOfTests = atoi(argMap["test-rounds"].c_str()) ;
00351 int onsetDel = atoi(argMap["digit-onset"].c_str()) ;
00352 long opDelay = atol(argMap["delay"].c_str());
00353 int in = argMap["range"].find("-") ;
00354 int rangeU = atoi( argMap["range"].substr(in+1).c_str()) ;
00355 int rangeL = atoi(argMap["range"].substr(0,in).c_str()) ;
00356 int step = atoi(argMap["subtraction-step"].c_str());
00357
00358 d->displayText("CLICK LEFT button to calibrate; RIGHT to skip");
00359 int cl = d->waitForMouseClick();
00360 if (cl == 1) d->displayEyeTrackerCalibration(3,5,1 , true);
00361 d->clearScreen();
00362 int cr = 0 ;
00363 while( cr <numOfTests ){
00364
00365 cr++;
00366 d->pushEvent("**************************************") ;
00367 d->showCursor(true);
00368 d->displayText("click one of the mouse buttons to start!");
00369 d->waitForMouseClick() ;
00370 d->showCursor(false) ;
00371 int initialNum = rangeL+ random()%(rangeU-rangeL) ;
00372 d->clearScreen() ;
00373 d->pushEvent("the initial number is: "+stringify(initialNum)) ;
00374 d->displayFixationBlink();
00375 d->displayText(stringify(initialNum),true,0) ;
00376 d->waitFrames(onsetDel) ;
00377 d->clearScreen() ;
00378 d->displayFixationBlink(d->getWidth()/2,d->getHeight()/2,2,3);
00379 d->pushEvent(std::string("===== Showing image: def.mpg ====="));
00380 eyet->track(true);
00381 d->pushEvent("manupulation starts") ;
00382 long st = d->getTimerValue();
00383 long et = st ;
00384 while( et - st < opDelay ){
00385 et = d->getTimerValue();
00386 }
00387 usleep(50000);
00388 eyet->track(false);
00389 d->pushEvent("manipulation ends") ;
00390 string answer = getDigitSequenceFromSubject("0123456789" , 3);
00391 d->pushEvent("the reported number: "+answer);
00392 int finalNum = atoi(answer.c_str()) ;
00393 d->pushEvent("number of operations: "+stringify((initialNum-finalNum)/step));
00394 }
00395
00396 d->clearScreen();
00397 d->displayText("Experiment complete. Thank you!");
00398 d->waitForMouseClick();
00399
00400
00401 manager.stop();
00402
00403
00404
00405 return 0;
00406 }
00407
00408 #endif // INVT_HAVE_LIBSDL_IMAGE
00409