annotate eventLogger.mm @ 52:89944ab3e129 tip

fix oF linker errors ios8
author Robert Tubb <rt300@eecs.qmul.ac.uk>
date Tue, 03 Feb 2015 13:18:23 +0000
parents 3af380769779
children
rev   line source
rt300@0 1 //
rt300@0 2 // eventLogger.mm
rt300@0 3 // oscSenderExample
rt300@0 4 //
rt300@0 5 // Created by Robert Tubb on 05/11/2012.
rt300@0 6 //
rt300@0 7 //
rt300@0 8
rt300@0 9 //---------------------------------------------------------------------------
rt300@0 10 #include "eventLogger.h"
rt300@0 11
rt300@0 12 EventLogger eventLogger;
rt300@0 13
rt300@0 14 //---------------------------------------------------------------------------
rt300@0 15 EventLogger::EventLogger(){
rt300@0 16
rt300@0 17 consentGiven = true; // unless told otherwise firstAppOpen
rt300@0 18 loggingEnabled = true;
rt300@0 19 serverConnectionOK = false;
rt300@0 20 questionnaireCompleted = false;
rt300@0 21 questionnaireUploaded = false;
rt300@0 22 logUploadInProgress = false;
rt300@0 23
rt300@0 24 nextUploadQty = UPLOAD_CHUNK_SIZE; // amount of data uploaded is always more than UPLOAD_CHUNK_SIZE events
rt300@0 25 serverComms = [[ServerComms alloc] init];
rt300@0 26
rt300@0 27 }
rt300@18 28 // for RIFTATHON this replaces startLoadAll
rt300@18 29 // because we can't look at logs or presets until we know user
rt300@18 30
rt300@18 31 void EventLogger::onUsernameEntered(){
rt300@18 32 sessionStartTime = ofGetSystemTime();
rt300@18 33 // userName = name; done already by dialog
rt300@18 34 // check for eventlog with this name
rt300@18 35
rt300@18 36
rt300@18 37 string path = ofxiPhoneGetDocumentsDirectory();
rt300@18 38 ofDirectory dir(path);
rt300@18 39 //only show png files
rt300@18 40 dir.allowExt("json");
rt300@18 41 //populate the directory object
rt300@18 42 dir.listDir();
rt300@18 43
rt300@18 44 //chek for username's logs
rt300@18 45 bool userHasLogs = false;
rt300@18 46 int numExistingLogs = 0;
rt300@18 47 for(int i = 0; i < dir.numFiles(); i++){
rt300@18 48 string fname = dir.getName(i);
rt300@18 49 if( 0 == fname.compare(0, userName.length() + 10, userName + "_eventlog_" )){
rt300@18 50 numExistingLogs++;
rt300@18 51 userHasLogs = true;
rt300@18 52 }
rt300@18 53
rt300@18 54 }
rt300@18 55 // if found, load other details such as device id
rt300@18 56 loadUserDetailsFromLastLogFile(numExistingLogs);
rt300@18 57 nextLogFileIndex = numExistingLogs+1;
rt300@18 58
rt300@18 59 }
rt300@18 60
rt300@0 61 //---------------------------------------------------------------------------
rt300@0 62 void EventLogger::startLoadAll(){
rt300@0 63
rt300@0 64 // TODO pilot doesn't check existing
rt300@0 65 //loadExistingLogFile(ofxiPhoneGetDocumentsDirectory() + EVENT_LOG_FILENAME);
rt300@0 66
rt300@0 67
rt300@0 68 sessionStartTime = ofGetSystemTime();
rt300@0 69
rt300@0 70 // TODO pilot
rt300@0 71 // testConnection();
rt300@0 72
rt300@0 73 // if we have a back log of events upload them
rt300@0 74 if(theEvents.size() > nextUploadQty && ! logUploadInProgress){
rt300@0 75 //try to upload
rt300@0 76
rt300@0 77 // TODO pilot doesn't upload
rt300@0 78 //uploadEventLog(true);
rt300@0 79 }
rt300@0 80
rt300@0 81 if(questionnaireCompleted && !questionnaireUploaded){
rt300@0 82 uploadQuestionnaire();
rt300@0 83 }
rt300@0 84
rt300@0 85 //TODO if questionnaire wasn't reached but still opened then set the timer to something sensible
rt300@0 86
rt300@0 87 //timer.setInteractionTime(savedInteractionTime);
rt300@0 88 //timer.setOrderFromPrevious(interfaceOrder);
rt300@0 89
rt300@0 90 // for now sod it, start from scratch
rt300@0 91 if(!questionnaireCompleted){
rt300@0 92 cout<<"Questionnaire NOT completed - first APP open called\n";
rt300@0 93 firstEverAppOpen();
rt300@0 94 }
rt300@0 95
rt300@0 96 }
rt300@0 97 //---------------------------------------------------------------------------
rt300@0 98 void EventLogger::testConnection(){
rt300@0 99 Json::Value root;
rt300@0 100 root["x"] = "y";
rt300@0 101 cout << "testConnection\n";
rt300@0 102 sendToServer("testConnection", root, true);
rt300@0 103
rt300@0 104 }
rt300@0 105 //---------------------------------------------------------------------------
rt300@18 106
rt300@18 107 void EventLogger::loadUserDetailsFromLastLogFile(int numExistingLogs){
rt300@18 108
rt300@18 109
rt300@18 110 }
rt300@18 111 //---------------------------------------------------------------------------
rt300@18 112
rt300@18 113
rt300@0 114 // this reads the persistent log file , checks if we've used the app before and
rt300@0 115 // if we've answered questionnaire or not
rt300@0 116
rt300@0 117 // should just store stuff. the start up state should be handled by testAPp
rt300@0 118
rt300@0 119 void EventLogger::loadExistingLogFile(const string &jsonFile){
rt300@0 120 Json::Value root;
rt300@0 121 Json::Reader reader;
rt300@0 122
rt300@0 123 /////////////
rt300@0 124 // read file
rt300@0 125
rt300@0 126 ifstream theFile(jsonFile.c_str());
rt300@0 127 stringstream fileText;
rt300@0 128 string line;
rt300@0 129 if(!theFile){
rt300@0 130 cout<<"No event log file found - first APP open called\n";
rt300@0 131 firstEverAppOpen();
rt300@0 132 return;
rt300@0 133 }else{
rt300@0 134 while(theFile){
rt300@0 135 theFile >> line;
rt300@0 136 // cout << line; // lots!!!!
rt300@0 137 fileText << line;
rt300@0 138 }
rt300@0 139 theFile.close();
rt300@0 140 }
rt300@0 141
rt300@0 142 cout << "size of log JSON string:" << fileText.str().length() << "BYTES \n";
rt300@0 143
rt300@0 144 bool parsingSuccessful = reader.parse( fileText.str(), root );
rt300@0 145
rt300@0 146 if ( !parsingSuccessful )
rt300@0 147 {
rt300@0 148 // report to the user the failure and their locations in the document.
rt300@0 149 std::cout << "Failed to parse event log JSON: \n"
rt300@0 150 << reader.getFormattedErrorMessages();
rt300@0 151 return;
rt300@0 152 }
rt300@0 153
rt300@0 154 /////////////////
rt300@0 155 // now put user deets into variables
rt300@0 156
rt300@0 157 userName = root["userName"].asString();
rt300@0 158 deviceID = root["deviceID"].asLargestInt();
rt300@0 159 nextUploadNumber = root["uploadNumber"].asInt();
rt300@0 160 savedInteractionTime = root["savedInteractionTime"].asLargestInt();
rt300@0 161 questionnaireCompleted = root["questionnaireCompleted"].asBool();
rt300@0 162 questionnaireUploaded = root["questionnaireUploaded"].asBool();
rt300@0 163
rt300@0 164 // check for unuploaded evts
rt300@0 165 const Json::Value jlogs = root["events"];
rt300@0 166
rt300@0 167 for ( int index = 0; index < jlogs.size(); ++index ) theEvents.push_back(lEvent(jlogs[index]));
rt300@0 168
rt300@0 169
rt300@0 170 //////////////
rt300@0 171
rt300@0 172 if(questionnaireCompleted && !questionnaireUploaded){
rt300@0 173 // then read it in and upload it
rt300@0 174 Json::Value JQ = root["questionnaire"];
rt300@0 175 Json::Value JArray = JQ["qAnswers"];
rt300@0 176 if(JArray.size() < 2){
rt300@0 177 cout << "Error - status of questionnaire is wierd\n";
rt300@0 178 }
rt300@0 179 for ( unsigned int i = 0; i < JArray.size(); i++ )
rt300@0 180 {
rt300@0 181 questionnaireAnswers.push_back(JArray[i].asInt());
rt300@0 182 }
rt300@0 183 questionnaireComments = JQ["comments"].toStyledString();
rt300@0 184 //uploadQuestionnaire();
rt300@0 185 }
rt300@0 186
rt300@0 187 // TODO interaction time seems to be balls
rt300@0 188 cout << "Total interaction time: " << savedInteractionTime << '\n';
rt300@0 189
rt300@0 190 }
rt300@0 191
rt300@0 192 //---------------------------------------------------------------------------
rt300@0 193
rt300@0 194 void EventLogger::firstEverAppOpen(){
rt300@0 195
rt300@0 196 nextUploadNumber = 0;
rt300@0 197 deviceID = ofGetSystemTimeMicros();
rt300@0 198 savedInteractionTime = 0;
rt300@0 199 questionnaireCompleted = false;
rt300@0 200 questionnaireUploaded = false;
rt300@0 201
rt300@0 202 }
rt300@0 203
rt300@0 204
rt300@0 205 //---------------------------------------------------------------------------
rt300@0 206 void EventLogger::questionnaireAnswersObtained(vector<int> answers, const char* userComments){
rt300@0 207
rt300@0 208 questionnaireCompleted = true;
rt300@0 209 questionnaireAnswers = answers;
rt300@0 210 questionnaireComments = userComments;
rt300@0 211 uploadQuestionnaire();
rt300@0 212 logEvent(QUESTIONNAIRE_COMPLETED);
rt300@0 213
rt300@0 214 }
rt300@0 215 //---------------------------------------------------------------------------
rt300@0 216 void EventLogger::uploadQuestionnaire(){
rt300@0 217 // show indicator
rt300@0 218 cout << "^^^^^^^^ UPLOADING QUESTIONNAIRE ^^^^^^^^ \n";
rt300@0 219 cout << questionnaireToJson() << "\n";
rt300@0 220 sendToServer("questionnaire", questionnaireToJson(), true);
rt300@0 221
rt300@0 222 }
rt300@0 223 //---------------------------------------------------------------------------
rt300@0 224 bool EventLogger::sendToServer(string functionName, Json::Value jsonData, bool async = false){
rt300@0 225
rt300@0 226 Json::FastWriter writer;
rt300@0 227 string jsontext = writer.write( jsonData );
rt300@0 228
rt300@0 229 // remove newline
rt300@0 230 if (!jsontext.empty() && jsontext[jsontext.length()-1] == '\n') {
rt300@0 231 jsontext.erase(jsontext.length()-1);
rt300@0 232 }
rt300@0 233 ostringstream jd;
rt300@0 234 jd << jsontext;
rt300@0 235 NSString *theData = [NSString stringWithUTF8String:jd.str().c_str()];
rt300@0 236 NSString *theType = [NSString stringWithUTF8String:functionName.c_str()];
rt300@0 237
rt300@0 238 if(async){
rt300@0 239 [serverComms doPostRequest:theType withData:theData];
rt300@0 240 }else{
rt300@0 241 bool success = [serverComms doSyncPostRequest:theType withData:theData];
rt300@0 242 return success;
rt300@0 243 }
rt300@0 244
rt300@0 245 }
rt300@0 246 //-----------------------------
rt300@0 247 void EventLogger::questionnaireOK(){
rt300@0 248 questionnaireUploaded = true;
rt300@0 249 questionnaireComments = "";
rt300@0 250 }
rt300@0 251 //-----------------------------
rt300@0 252 void EventLogger::eventlogOK(){
rt300@0 253 // COMMENT THIS IF UPLAODING FROM IPAD TO XCODE
rt300@0 254
rt300@0 255 // it's a bad idea to do this in another thread...
rt300@0 256 theEvents.clear();
rt300@0 257 cout << "EVENT LOG UPLOAD SUCCESS\n";
rt300@0 258 nextUploadNumber++;
rt300@0 259 logUploadInProgress = false;
rt300@0 260 }
rt300@0 261 //-----------------------------
rt300@0 262 void EventLogger::testConnectionOK(){
rt300@0 263 cout << "^^^^^^^^ server connection OK ^^^^^^^^ \n";
rt300@0 264 serverConnectionOK = true;
rt300@0 265 }
rt300@0 266 //-----------------------------
rt300@0 267 void EventLogger::questionnaireNotOK(){
rt300@0 268 cout << "XXXXX questionnaire NOT OK XXXXXXX \n";
rt300@0 269 questionnaireUploaded = false;
rt300@0 270 }
rt300@0 271 //-----------------------------
rt300@0 272 void EventLogger::eventlogNotOK(){
rt300@0 273 // try later
rt300@0 274 cout << "XXXXX event log NOT OK XXXXXXX \n";
rt300@0 275 nextUploadQty += UPLOAD_CHUNK_SIZE;
rt300@0 276 logUploadInProgress = false;
rt300@0 277 }
rt300@0 278 //-----------------------------
rt300@0 279 void EventLogger::testConnectionNotOK(){
rt300@0 280 cout << "XXXXX server connection NOT OK XXXXXXX \n";
rt300@0 281 serverConnectionOK = false;
rt300@0 282 // alert?
rt300@0 283
rt300@0 284 }
rt300@0 285
rt300@0 286
rt300@0 287 //---------------------------------------------------------------------------
rt300@0 288
rt300@0 289 bool EventLogger::uploadEventLog(bool async){
rt300@0 290
rt300@0 291 // show indicator
rt300@0 292 logUploadInProgress = true;
rt300@0 293 cout << "^^^^^^^^ ATTEMPTING TO UPLOAD " << theEvents.size() << " EVENTS ^^^^^^^^ .\n";
rt300@0 294 if(!async){
rt300@0 295 bool success = sendToServer("eventlog", logsToJson(), async);
rt300@0 296 if(!success){
rt300@0 297 // try later
rt300@0 298 nextUploadQty += UPLOAD_CHUNK_SIZE;
rt300@0 299 // increment upload number?
rt300@0 300 }else{
rt300@0 301
rt300@0 302 // if success - clear memory
rt300@0 303 // IF UPLAODING FROM IPAD TO XCODE COMMENT OUT
rt300@0 304 theEvents.clear();
rt300@0 305 cout << "UPLOAD SUCCESS\n";
rt300@0 306 nextUploadNumber++;
rt300@0 307 }
rt300@0 308 logUploadInProgress = false;
rt300@0 309 return success;
rt300@0 310 }else{
rt300@0 311 sendToServer("eventlog", logsToJson(), async);
rt300@0 312 }
rt300@0 313 }
rt300@0 314 //---------------------------------------------------------------------------
rt300@0 315 // only called when doing supervised tests
rt300@0 316 void EventLogger::newUser(){
rt300@0 317 // store old stuff
rt300@0 318
rt300@0 319 saveSessionToFile();
rt300@0 320 cout<<"setup new user\n";
rt300@0 321 deleteLogs();
rt300@0 322 nextUploadNumber = 0;
rt300@0 323 deviceID = ofGetSystemTimeMicros();
rt300@0 324 savedInteractionTime = 0;
rt300@0 325 totalInteractionTime = 0;
rt300@0 326 sessionStartTime = ofGetSystemTime();
rt300@0 327 questionnaireCompleted = false;
rt300@0 328 questionnaireUploaded = false;
rt300@0 329
rt300@0 330 //((testApp *)ofGetAppPtr())->showIntro();
rt300@0 331
rt300@0 332 }
rt300@0 333 //---------------------------------------------------------------------------
rt300@0 334 // called from alertView OK in iViewController
rt300@0 335 void EventLogger::setUsername(const char *u){
rt300@0 336 userName = u;
rt300@0 337
rt300@0 338 }
rt300@0 339 //---------------------------------------------------------------------------
rt300@0 340 //new tweakathlon event logger with vector
rt300@0 341 void EventLogger::logEvent(const leventType& evtType, const vector<int> eventData){
rt300@0 342 Poco::Mutex::ScopedLock lock(_mutex);
rt300@0 343 if(!loggingEnabled) return;
rt300@0 344
rt300@0 345 switch ( evtType ) {
rt300@0 346
rt300@0 347 // case CANDIDATE_PARAM_ADJUSTED:
rt300@0 348 // // TODO thinning here. maybe. was a pain in the butt.
rt300@0 349 // thinnedSliderEvent(lEvent(evtType,eventData));
rt300@0 350 // break;
rt300@0 351 default:
rt300@0 352 // default is just an event type with vector of ints. matlab will know what they are.
rt300@0 353
rt300@0 354
rt300@0 355 theEvents.push_back(lEvent(evtType, eventData));
rt300@0 356
rt300@0 357 break;
rt300@0 358 }
rt300@0 359
rt300@18 360 // new riftathon save as we go
rt300@18 361 if (theEvents.size() > SAVE_CHUNK_SIZE){
rt300@18 362 saveSessionToFile();
rt300@18 363 theEvents.clear();
rt300@0 364 }
rt300@18 365
rt300@0 366 //TODO thiswrong?
rt300@0 367 totalInteractionTime = savedInteractionTime + (ofGetSystemTime() - sessionStartTime); // milliseconds
rt300@0 368
rt300@0 369 }
rt300@0 370 //---------------------------------------------------------------------------
rt300@0 371 // OLD SONIC ZOOM EVT - still used for simple events with no data
rt300@0 372 void EventLogger::logEvent(const leventType& evtType){
rt300@0 373 Poco::Mutex::ScopedLock lock(_mutex);
rt300@0 374 if(!loggingEnabled) return;
rt300@0 375
rt300@0 376 switch ( evtType ) {
rt300@0 377 // data thinning here
rt300@0 378 case APP_LOADED:
rt300@0 379 theEvents.push_back(lEvent(evtType));
rt300@0 380 default:
rt300@0 381 // default is just an event type with vector of ints. matlab will know what they are.
rt300@0 382
rt300@0 383
rt300@0 384 theEvents.push_back(lEvent(evtType));
rt300@0 385
rt300@0 386 }
rt300@0 387
rt300@0 388 if(theEvents.size() > nextUploadQty && !logUploadInProgress){
rt300@0 389 //try to upload asynchronously
rt300@0 390 // TODO pilot doesn't upload
rt300@0 391 //uploadEventLog(true);
rt300@0 392 }
rt300@18 393
rt300@34 394 // new riftathon save as we go NEVER REACHES HERE?
rt300@18 395 if (theEvents.size() > SAVE_CHUNK_SIZE){
rt300@18 396 saveSessionToFile();
rt300@18 397 }
rt300@18 398
rt300@0 399 //TODO thiswrong?
rt300@0 400 totalInteractionTime = savedInteractionTime + (ofGetSystemTime() - sessionStartTime); // milliseconds
rt300@0 401
rt300@0 402 }
rt300@0 403 // UnaryPredicate
rt300@0 404 template <class T>
rt300@0 405 bool EventLogger::matchID(T thing){
rt300@0 406 return true;
rt300@0 407 }
rt300@0 408 bool EventLogger::matchID2(){
rt300@0 409 return true;
rt300@0 410 }
rt300@0 411 //---------------------------------------------------------------------------
rt300@0 412 void EventLogger::thinnedSliderEvent(lEvent newEvent){
rt300@0 413 static vector<lEvent> unloggedEventsCache; // list of all different slider events
rt300@0 414 static int eventCounter = 0;
rt300@0 415
rt300@0 416 // if first event then log it.
rt300@0 417 if(theEvents.size() == 0){
rt300@0 418 theEvents.push_back(newEvent);
rt300@0 419 }
rt300@0 420
rt300@0 421 // look for last event in the cache that had this mappingID
rt300@0 422 cout << unloggedEventsCache.size() << endl;
rt300@0 423
rt300@0 424 vector<lEvent>::iterator lastMatching;
rt300@0 425 for(lastMatching = unloggedEventsCache.begin();
rt300@0 426 lastMatching != unloggedEventsCache.end() && ( (*lastMatching).eventData[0] != newEvent.eventData[0]);
rt300@0 427 lastMatching++);
rt300@0 428
rt300@0 429
rt300@0 430 if (lastMatching != unloggedEventsCache.end()){
rt300@0 431 //cout << "matching id logevent: " << (*lastMatching).eventData[0] << " " << newEvent.eventData[0] << endl;
rt300@0 432 // we have another, check gap
rt300@0 433 int gap = newEvent.eventTime - (*lastMatching).eventTime;
rt300@0 434 if(gap > 300){
rt300@0 435 theEvents.push_back((*lastMatching));
rt300@0 436
rt300@0 437 // also log new slider evt
rt300@0 438 theEvents.push_back(newEvent);
rt300@0 439 eventCounter = 0;
rt300@0 440
rt300@0 441 }else if(eventCounter >= EVENT_THIN_FACTOR){ // otherwise only record every Nth event
rt300@0 442 theEvents.push_back(newEvent);
rt300@0 443 eventCounter = 0;
rt300@0 444 // DELETE THAT PREVIOUS EVENT
rt300@0 445 unloggedEventsCache.erase(lastMatching);
rt300@0 446
rt300@0 447 }else{
rt300@0 448 // ignore for now but put in unlogged
rt300@0 449 unloggedEventsCache.push_back(newEvent);
rt300@0 450 }
rt300@0 451
rt300@0 452 }else{
rt300@0 453 // this event type wasnt in the cache
rt300@0 454 if(eventCounter >= EVENT_THIN_FACTOR){ // otherwise only record every Nth event
rt300@0 455 theEvents.push_back(newEvent);
rt300@0 456 eventCounter = 0;
rt300@0 457 }else{
rt300@0 458 unloggedEventsCache.push_back(newEvent);
rt300@0 459 }
rt300@0 460
rt300@0 461 }
rt300@0 462 // always count the new one
rt300@0 463 eventCounter++;
rt300@0 464
rt300@0 465
rt300@0 466
rt300@0 467 }
rt300@0 468
rt300@0 469 //--------------------------------------------------------------------
rt300@0 470 // called from newUser
rt300@0 471 void EventLogger::deleteLogs(){
rt300@18 472 return;
rt300@0 473 // the
rt300@0 474 theEvents.clear();
rt300@0 475 string fname = ofxiPhoneGetDocumentsDirectory() + EVENT_LOG_FILENAME;
rt300@0 476 ofFile logFile(fname,ofFile::WriteOnly);
rt300@0 477 logFile << "";
rt300@0 478 logFile.close();
rt300@0 479 }
rt300@0 480
rt300@0 481 //---------------------------------------------------------------------------
rt300@0 482
rt300@0 483 Json::Value EventLogger::logsToJson(){
rt300@0 484 // put all logged events into Json formatted string
rt300@0 485 Json::Value root;
rt300@0 486
rt300@0 487 vector<lEvent>::iterator eventIter;
rt300@0 488
rt300@0 489 root["programVersion"] = PROGRAM_VERSION;
rt300@0 490 root["userName"] = userName;
rt300@0 491 root["deviceID"] = deviceID;
rt300@0 492 root["uploadNumber"] = nextUploadNumber;
rt300@0 493 root["savedInteractionTime"] = savedInteractionTime;
rt300@0 494 root["questionnaireCompleted"] = questionnaireCompleted;
rt300@0 495 root["questionnaireUploaded"] = questionnaireUploaded;
rt300@0 496
rt300@0 497 // this can mess up matlab script if it doesn't find this field
rt300@0 498 root["questionnaire"] = questionnaireToJson();
rt300@0 499
rt300@0 500
rt300@0 501 int i = 0;
rt300@0 502 for(eventIter = theEvents.begin(); eventIter < theEvents.end(); eventIter++){
rt300@0 503 root["events"][i] = (*eventIter).eventToJson();
rt300@0 504 i++;
rt300@0 505 }
rt300@0 506 root["numEventsHere"] = i;
rt300@0 507 return root;
rt300@0 508 }
rt300@0 509
rt300@0 510 //---------------------------------------------------------------------------
rt300@0 511
rt300@0 512 Json::Value EventLogger::questionnaireToJson(){
rt300@0 513 // put all answers into Json formatted string
rt300@0 514 Json::Value root;
rt300@0 515
rt300@0 516 vector<int>::iterator aIter;
rt300@0 517
rt300@0 518 Json::Value questionnaire;
rt300@0 519
rt300@0 520 int i = 0;
rt300@0 521 for(aIter = questionnaireAnswers.begin(); aIter < questionnaireAnswers.end(); aIter++){
rt300@0 522 questionnaire[i] = (*aIter);
rt300@0 523 i++;
rt300@0 524 }
rt300@0 525
rt300@0 526 root["qAnswers"] = questionnaire;
rt300@0 527 root["comments"] = questionnaireComments;
rt300@0 528 root["userName"] = userName;
rt300@0 529 root["deviceID"] = deviceID;
rt300@0 530 root["programVersion"] = PROGRAM_VERSION;
rt300@0 531
rt300@0 532 return root;
rt300@0 533 }
rt300@0 534
rt300@0 535 //---------------------------------------------------------------------------
rt300@0 536 void EventLogger::printAll(){
rt300@0 537 cout << "-----------------ALL LOGGED EVENTS----------------- \n";
rt300@0 538 vector<lEvent>::iterator evIter;
rt300@0 539 cout << logsToJson() << "\n";
rt300@0 540 cout << "---------------------QUESTIONNAIRE---------------- \n";
rt300@0 541 cout << questionnaireToJson() << "\n";
rt300@0 542 };
rt300@0 543 //---------------------------------------------------------------------------
rt300@0 544
rt300@0 545 void EventLogger::saveSessionToFile(){
rt300@0 546 stringstream fn;
rt300@18 547 fn << ofxiPhoneGetDocumentsDirectory() << userName << "_eventlog_" << nextLogFileIndexString() << ".json";
rt300@0 548
rt300@0 549 string fname = fn.str(); //ofxiPhoneGetDocumentsDirectory() + userName + '_' + "TESTSAVE.json";
rt300@0 550
rt300@0 551 // write to file
rt300@18 552
rt300@0 553 Json::Value jlogs = logsToJson();
rt300@0 554 ofFile logFile(fname,ofFile::WriteOnly);
rt300@0 555 logFile << jlogs;
rt300@0 556 logFile.close();
rt300@18 557 nextLogFileIndex++;
rt300@34 558 theEvents.clear();
rt300@18 559 }
rt300@18 560
rt300@18 561 string EventLogger::nextLogFileIndexString(){
rt300@18 562 string num = ofToString(nextLogFileIndex);
rt300@18 563 string zero = ofToString(0);
rt300@18 564 int numzeros = 4 - num.length();
rt300@18 565 for (int i=0; i< numzeros;i++){
rt300@18 566 num = zero + num;
rt300@18 567 }
rt300@18 568 return num;
rt300@0 569
rt300@0 570 }
rt300@0 571 //----------------------------------------------------------------------------
rt300@0 572
rt300@0 573 // this builds up a file incrementally, which can be recovered on crash
rt300@0 574 //void EventLogger::appendToFile(){
rt300@0 575 //
rt300@0 576 //
rt300@0 577 //}
rt300@32 578
rt300@32 579 //---------------------------------------------------------------------------
rt300@32 580
rt300@32 581 void EventLogger::exitAndSave(){
rt300@32 582
rt300@32 583 saveSessionToFile();
rt300@32 584 return;
rt300@32 585
rt300@32 586 if(!consentGiven){
rt300@32 587 Json::Value jlogs = logsToJson();
rt300@32 588 // try to upload TODO (no - might hang and prevent exit???)
rt300@32 589
rt300@32 590 // TODO pilot doesn't upload
rt300@32 591 // uploadEventLog(true);
rt300@32 592 return;
rt300@32 593 }
rt300@32 594
rt300@32 595 savedInteractionTime = savedInteractionTime + (ofGetSystemTime() - sessionStartTime);
rt300@32 596 // save user details
rt300@32 597 string fname = ofxiPhoneGetDocumentsDirectory() + userName + '_' + EVENT_LOG_FILENAME;
rt300@32 598
rt300@32 599 // try to upload
rt300@32 600 // do it sync because event list needs to be cleared to prevent saving on device
rt300@32 601
rt300@32 602 // TODO for pilot store to ipad
rt300@32 603 // uploadEventLog(false);
rt300@32 604
rt300@32 605 // write to file
rt300@32 606 // json without the logs that were uploaded!
rt300@32 607 Json::Value jlogs = logsToJson();
rt300@32 608 ofFile logFile(fname,ofFile::WriteOnly);
rt300@32 609 logFile << jlogs;
rt300@32 610 cout << jlogs;
rt300@32 611 logFile.close();
rt300@32 612
rt300@32 613 }