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@4
|
8
|
rt300@8
|
9 //---------------------------------------------------------------------------
|
rt300@0
|
10 #include "eventLogger.h"
|
rt300@1
|
11
|
rt300@1
|
12 EventLogger eventLogger;
|
rt300@32
|
13 extern PresetManager presetManager;
|
rt300@29
|
14
|
rt300@8
|
15 //---------------------------------------------------------------------------
|
rt300@1
|
16 EventLogger::EventLogger(){
|
rt300@8
|
17
|
rt300@31
|
18 consentGiven = true; // unless told otherwise firstAppOpen
|
rt300@8
|
19 loggingEnabled = true;
|
rt300@22
|
20 serverConnectionOK = false;
|
rt300@22
|
21 questionnaireCompleted = false;
|
rt300@22
|
22 questionnaireUploaded = false;
|
rt300@27
|
23 logUploadInProgress = false;
|
rt300@22
|
24 ofxiPhoneDeviceType iOSdeviceType = ofxiPhoneGetDeviceType();
|
rt300@22
|
25 cout << "Device: " << iOSdeviceType << '\n';
|
rt300@22
|
26
|
rt300@25
|
27 nextUploadQty = UPLOAD_CHUNK_SIZE; // amount of data uploaded is always more than UPLOAD_CHUNK_SIZE events
|
rt300@27
|
28
|
rt300@8
|
29 }
|
rt300@8
|
30 //---------------------------------------------------------------------------
|
rt300@24
|
31 // draw() - show path of last N scroll events - can be scrubbed along?
|
rt300@24
|
32 //
|
rt300@24
|
33 //---------------------------------------------------------------------------
|
rt300@29
|
34
|
rt300@8
|
35 void EventLogger::init(){
|
rt300@4
|
36
|
rt300@30
|
37 checkExistingLogFile(ofxiPhoneGetDocumentsDirectory() + EVENT_LOG_FILENAME);
|
rt300@8
|
38 sessionStartTime = ofGetSystemTime();
|
rt300@31
|
39
|
rt300@31
|
40 logEvent(APP_STARTED);
|
rt300@31
|
41
|
rt300@31
|
42 serverComms = [[ServerComms alloc] init];
|
rt300@9
|
43
|
rt300@9
|
44 testConnection();
|
rt300@7
|
45
|
rt300@31
|
46 }
|
rt300@31
|
47 //---------------------------------------------------------------------------
|
rt300@31
|
48 bool EventLogger::testConnection(){
|
rt300@31
|
49 Json::Value root;
|
rt300@31
|
50 root["x"] = "y";
|
rt300@31
|
51 cout << "testConnection\n";
|
rt300@31
|
52 sendToServer("testConnection", root, true);
|
rt300@31
|
53
|
rt300@30
|
54 }
|
rt300@30
|
55 //---------------------------------------------------------------------------
|
rt300@30
|
56 // this reads the persistent log file , checks if we've used the app before and
|
rt300@30
|
57 // if we've answered questionnaire or not
|
rt300@30
|
58 void EventLogger::checkExistingLogFile(const string &jsonFile){
|
rt300@30
|
59 Json::Value root;
|
rt300@30
|
60 Json::Reader reader;
|
rt300@30
|
61
|
rt300@30
|
62 /////////////
|
rt300@30
|
63 // read file
|
rt300@30
|
64
|
rt300@30
|
65 ifstream theFile(jsonFile.c_str());
|
rt300@30
|
66 stringstream fileText;
|
rt300@30
|
67 string line;
|
rt300@30
|
68 if(!theFile){
|
rt300@30
|
69
|
rt300@30
|
70 firstEverAppOpen();
|
rt300@30
|
71 return;
|
rt300@30
|
72 }else{
|
rt300@30
|
73 while(theFile){
|
rt300@30
|
74 theFile >> line;
|
rt300@30
|
75 // cout << line; // lots!!!!
|
rt300@30
|
76 fileText << line;
|
rt300@30
|
77 }
|
rt300@30
|
78 theFile.close();
|
rt300@30
|
79 }
|
rt300@30
|
80
|
rt300@30
|
81 // otherwise, we've been in here before
|
rt300@30
|
82
|
rt300@30
|
83 /////////////
|
rt300@30
|
84 // Parse json
|
rt300@30
|
85 cout << "size of log JSON string:" << fileText.str().length() << "BYTES \n";
|
rt300@30
|
86
|
rt300@30
|
87 bool parsingSuccessful = reader.parse( fileText.str(), root );
|
rt300@30
|
88
|
rt300@30
|
89 if ( !parsingSuccessful )
|
rt300@30
|
90 {
|
rt300@30
|
91 // report to the user the failure and their locations in the document.
|
rt300@30
|
92 std::cout << "Failed to parse event log JSON: \n"
|
rt300@30
|
93 << reader.getFormattedErrorMessages();
|
rt300@30
|
94 return;
|
rt300@30
|
95 }
|
rt300@30
|
96
|
rt300@30
|
97 /////////////////
|
rt300@30
|
98 // now put user deets into variables
|
rt300@30
|
99
|
rt300@30
|
100 userName = root["userName"].asString();
|
rt300@30
|
101 deviceID = root["deviceID"].asLargestInt();
|
rt300@30
|
102 nextUploadNumber = root["uploadNumber"].asInt();
|
rt300@30
|
103 savedInteractionTime = root["savedInteractionTime"].asLargestInt();
|
rt300@30
|
104 questionnaireCompleted = root["questionnaireCompleted"].asBool();
|
rt300@30
|
105 questionnaireUploaded = root["questionnaireUploaded"].asBool();
|
rt300@30
|
106 interfaceOrder = root["interfaceOrder"].asInt();
|
rt300@30
|
107
|
rt300@29
|
108
|
rt300@30
|
109 // check for unuploaded evts
|
rt300@30
|
110 const Json::Value jlogs = root["events"];
|
rt300@29
|
111
|
rt300@30
|
112 for ( int index = 0; index < jlogs.size(); ++index ) theEvents.push_back(lEvent(jlogs[index]));
|
rt300@30
|
113 if(theEvents.size() > nextUploadQty && ! logUploadInProgress){
|
rt300@30
|
114 //try to upload
|
rt300@30
|
115 uploadEventLog(true);
|
rt300@30
|
116 }
|
rt300@30
|
117
|
rt300@30
|
118 //////////////
|
rt300@30
|
119 // what stage is the experiment at??
|
rt300@30
|
120
|
rt300@30
|
121 if(questionnaireCompleted && !questionnaireUploaded){
|
rt300@30
|
122 // then read it in and upload it
|
rt300@30
|
123 Json::Value JQ = root["questionnaire"];
|
rt300@30
|
124 Json::Value JArray = JQ["qAnswers"];
|
rt300@30
|
125 if(JArray.size() < 2){
|
rt300@30
|
126 cout << "Error - status of questionnaire is wierd\n";
|
rt300@30
|
127 }
|
rt300@30
|
128 for ( unsigned int i = 0; i < JArray.size(); i++ )
|
rt300@30
|
129 {
|
rt300@30
|
130 questionnaireAnswers.push_back(JArray[i].asInt());
|
rt300@30
|
131 }
|
rt300@30
|
132 questionnaireComments = JQ["comments"].toStyledString();
|
rt300@30
|
133 uploadQuestionnaire();
|
rt300@30
|
134 }
|
rt300@30
|
135 //TODO if questionnaire wasn't reached but still opened then set the timer to something sensible
|
rt300@30
|
136
|
rt300@30
|
137 if(!questionnaireCompleted){
|
rt300@30
|
138 // for now sod it, start from scratch
|
rt300@30
|
139 firstEverAppOpen();
|
rt300@30
|
140 return;
|
rt300@30
|
141 }
|
rt300@30
|
142 cout << "Total interaction time: " << savedInteractionTime << '\n';
|
rt300@30
|
143
|
rt300@30
|
144 //timer.setInteractionTime(savedInteractionTime);
|
rt300@30
|
145 //timer.setOrderFromPrevious(interfaceOrder);
|
rt300@30
|
146
|
rt300@8
|
147 }
|
rt300@29
|
148
|
rt300@8
|
149 //---------------------------------------------------------------------------
|
rt300@30
|
150
|
rt300@30
|
151 void EventLogger::firstEverAppOpen(){
|
rt300@30
|
152 cout<<"no event log file - first APP open\n";
|
rt300@30
|
153 nextUploadNumber = 0;
|
rt300@30
|
154 deviceID = ofGetSystemTimeMicros();
|
rt300@30
|
155 savedInteractionTime = 0;
|
rt300@30
|
156 questionnaireCompleted = false;
|
rt300@30
|
157 questionnaireUploaded = false;
|
rt300@30
|
158
|
rt300@30
|
159 ((testApp *)ofGetAppPtr())->showIntro();
|
rt300@30
|
160 consentGiven = false;
|
rt300@30
|
161
|
rt300@30
|
162 }
|
rt300@30
|
163
|
rt300@30
|
164
|
rt300@30
|
165 //---------------------------------------------------------------------------
|
rt300@28
|
166 void EventLogger::questionnaireAnswersObtained(vector<int> answers, const char* userComments){
|
rt300@22
|
167
|
rt300@22
|
168 questionnaireCompleted = true;
|
rt300@22
|
169 questionnaireAnswers = answers;
|
rt300@28
|
170 questionnaireComments = userComments;
|
rt300@22
|
171 uploadQuestionnaire();
|
rt300@31
|
172 logEvent(QUESTIONNAIRE_COMPLETED);
|
rt300@22
|
173
|
rt300@22
|
174 }
|
rt300@22
|
175 //---------------------------------------------------------------------------
|
rt300@27
|
176 void EventLogger::uploadQuestionnaire(){
|
rt300@22
|
177 // show indicator
|
rt300@22
|
178 cout << "^^^^^^^^ UPLOADING QUESTIONNAIRE ^^^^^^^^ \n";
|
rt300@31
|
179 cout << questionnaireToJson() << "\n";
|
rt300@27
|
180 sendToServer("questionnaire", questionnaireToJson(), true);
|
rt300@27
|
181
|
rt300@22
|
182 }
|
rt300@22
|
183 //---------------------------------------------------------------------------
|
rt300@27
|
184 bool EventLogger::sendToServer(string functionName, Json::Value jsonData, bool async = false){
|
rt300@22
|
185
|
rt300@22
|
186 Json::FastWriter writer;
|
rt300@22
|
187 string jsontext = writer.write( jsonData );
|
rt300@22
|
188
|
rt300@27
|
189 // remove newline
|
rt300@22
|
190 if (!jsontext.empty() && jsontext[jsontext.length()-1] == '\n') {
|
rt300@22
|
191 jsontext.erase(jsontext.length()-1);
|
rt300@22
|
192 }
|
rt300@30
|
193 ostringstream jd;
|
rt300@30
|
194 jd << jsontext;
|
rt300@30
|
195 NSString *theData = [NSString stringWithUTF8String:jd.str().c_str()];
|
rt300@30
|
196 NSString *theType = [NSString stringWithUTF8String:functionName.c_str()];
|
rt300@22
|
197
|
rt300@30
|
198 if(async){
|
rt300@30
|
199 [serverComms doPostRequest:theType withData:theData];
|
rt300@30
|
200 }else{
|
rt300@30
|
201 bool success = [serverComms doSyncPostRequest:theType withData:theData];
|
rt300@30
|
202 return success;
|
rt300@30
|
203 }
|
rt300@29
|
204
|
rt300@27
|
205 }
|
rt300@27
|
206 //-----------------------------
|
rt300@30
|
207 void EventLogger::questionnaireOK(){
|
rt300@30
|
208 questionnaireUploaded = true;
|
rt300@30
|
209 }
|
rt300@30
|
210 //-----------------------------
|
rt300@30
|
211 void EventLogger::eventlogOK(){
|
rt300@31
|
212 // IF UPLAODING FROM IPAD TO XCODE
|
rt300@32
|
213 theEvents.clear();
|
rt300@30
|
214 cout << "EVENT LOG UPLOAD SUCCESS\n";
|
rt300@30
|
215 nextUploadNumber++;
|
rt300@30
|
216 logUploadInProgress = false;
|
rt300@30
|
217 }
|
rt300@30
|
218 //-----------------------------
|
rt300@30
|
219 void EventLogger::testConnectionOK(){
|
rt300@30
|
220 cout << "^^^^^^^^ server connection OK ^^^^^^^^ \n";
|
rt300@30
|
221 serverConnectionOK = true;
|
rt300@30
|
222 }
|
rt300@30
|
223 //-----------------------------
|
rt300@30
|
224 void EventLogger::questionnaireNotOK(){
|
rt300@32
|
225 cout << "XXXXX questionnaire NOT OK XXXXXXX \n";
|
rt300@30
|
226 questionnaireUploaded = false;
|
rt300@30
|
227 }
|
rt300@30
|
228 //-----------------------------
|
rt300@30
|
229 void EventLogger::eventlogNotOK(){
|
rt300@30
|
230 // try later
|
rt300@32
|
231 cout << "XXXXX event log NOT OK XXXXXXX \n";
|
rt300@30
|
232 nextUploadQty += UPLOAD_CHUNK_SIZE;
|
rt300@30
|
233 logUploadInProgress = false;
|
rt300@30
|
234 }
|
rt300@30
|
235 //-----------------------------
|
rt300@30
|
236 void EventLogger::testConnectionNotOK(){
|
rt300@32
|
237 cout << "XXXXX server connection NOT OK XXXXXXX \n";
|
rt300@30
|
238 serverConnectionOK = false;
|
rt300@30
|
239 // alert?
|
rt300@30
|
240
|
rt300@30
|
241 }
|
rt300@27
|
242
|
rt300@27
|
243
|
rt300@9
|
244 //---------------------------------------------------------------------------
|
rt300@9
|
245
|
rt300@27
|
246 bool EventLogger::uploadEventLog(bool async){
|
rt300@28
|
247
|
rt300@22
|
248 // show indicator
|
rt300@27
|
249 logUploadInProgress = true;
|
rt300@25
|
250 cout << "^^^^^^^^ ATTEMPTING TO UPLOAD " << theEvents.size() << " EVENTS ^^^^^^^^ .\n";
|
rt300@27
|
251 if(!async){
|
rt300@27
|
252 bool success = sendToServer("eventlog", logsToJson(), async);
|
rt300@27
|
253 if(!success){
|
rt300@29
|
254 // try later : NOPE has maximum size
|
rt300@27
|
255 nextUploadQty += UPLOAD_CHUNK_SIZE;
|
rt300@27
|
256 }else{
|
rt300@27
|
257
|
rt300@27
|
258 // if success - clear memory
|
rt300@31
|
259 // IF UPLAODING FROM IPAD TO XCODE COMMENT OUT
|
rt300@32
|
260 theEvents.clear();
|
rt300@27
|
261 cout << "UPLOAD SUCCESS\n";
|
rt300@27
|
262 nextUploadNumber++;
|
rt300@27
|
263 }
|
rt300@27
|
264 logUploadInProgress = false;
|
rt300@27
|
265 return success;
|
rt300@9
|
266 }else{
|
rt300@27
|
267 sendToServer("eventlog", logsToJson(), async);
|
rt300@9
|
268 }
|
rt300@1
|
269 }
|
rt300@8
|
270 //----------------------------------------------------------------------------
|
rt300@27
|
271
|
rt300@27
|
272 //----------------------------------------------------------------------------
|
rt300@8
|
273
|
rt300@28
|
274 //---------------------------------------------------------------------------
|
rt300@28
|
275 // only called when doing supervised tests
|
rt300@27
|
276 void EventLogger::newUser(){
|
rt300@32
|
277 // store old stuff
|
rt300@32
|
278
|
rt300@32
|
279 saveSessionToFile();
|
rt300@32
|
280 presetManager.saveSessionToFile(userName);
|
rt300@27
|
281 cout<<"setup new user\n";
|
rt300@29
|
282 deleteLogs();
|
rt300@27
|
283 nextUploadNumber = 0;
|
rt300@27
|
284 deviceID = ofGetSystemTimeMicros();
|
rt300@27
|
285 savedInteractionTime = 0;
|
rt300@28
|
286 totalInteractionTime = 0;
|
rt300@28
|
287 sessionStartTime = ofGetSystemTime();
|
rt300@27
|
288 questionnaireCompleted = false;
|
rt300@29
|
289 questionnaireUploaded = false;
|
rt300@29
|
290
|
rt300@29
|
291 ((testApp *)ofGetAppPtr())->showIntro();
|
rt300@27
|
292
|
rt300@27
|
293 }
|
rt300@8
|
294 //---------------------------------------------------------------------------
|
rt300@8
|
295 // called from alertView OK in iViewController
|
rt300@8
|
296 void EventLogger::setUsername(const char *u){
|
rt300@8
|
297 userName = u;
|
rt300@28
|
298 // start interaction clock
|
rt300@29
|
299
|
rt300@29
|
300 //timer.startInteractionClock();
|
rt300@29
|
301 [((testApp *)ofGetAppPtr())->tsc startTimer];
|
rt300@28
|
302 }
|
rt300@28
|
303 //---------------------------------------------------------------------------
|
rt300@28
|
304 void EventLogger::thinnedLogEvent(lEvent newEvent){
|
rt300@28
|
305 static lEvent previousEvent(APP_STARTED); // initialised as whatever. hopefully won't log
|
rt300@28
|
306 static int eventCounter = 0;
|
rt300@28
|
307
|
rt300@28
|
308 // if first event then log it. it won't be, but still.
|
rt300@28
|
309 if(theEvents.size() == 0){
|
rt300@28
|
310 theEvents.push_back(newEvent);
|
rt300@28
|
311 previousEvent = newEvent;
|
rt300@28
|
312 return;
|
rt300@28
|
313 }
|
rt300@28
|
314
|
rt300@31
|
315 // if previous event is more than 300ms ago, or event type has changed, log both of them (lots of events on move+zoom combinations!!)
|
rt300@28
|
316 int gap = newEvent.eventTime - previousEvent.eventTime;
|
rt300@28
|
317 if(gap > 300 || newEvent.eventType != previousEvent.eventType){
|
rt300@28
|
318 // if prev event not logged, log it
|
rt300@31
|
319 if(theEvents.back().eventTime != previousEvent.eventTime){
|
rt300@28
|
320 theEvents.push_back(previousEvent);
|
rt300@28
|
321 }
|
rt300@28
|
322 theEvents.push_back(newEvent);
|
rt300@7
|
323
|
rt300@28
|
324 }
|
rt300@28
|
325
|
rt300@28
|
326 // otherwise only record every Nth event
|
rt300@28
|
327 if(eventCounter >= EVENT_THIN_FACTOR){
|
rt300@28
|
328 theEvents.push_back(newEvent);
|
rt300@28
|
329 eventCounter = 0;
|
rt300@28
|
330
|
rt300@28
|
331 }
|
rt300@28
|
332 eventCounter++;
|
rt300@28
|
333 previousEvent = newEvent;
|
rt300@7
|
334 }
|
rt300@8
|
335 //---------------------------------------------------------------------------
|
rt300@5
|
336 void EventLogger::logEvent(const leventType& evtType,const TwoVector& centre, const double& scale, const int& sliderID, const double& sliderVal){
|
rt300@3
|
337 //cout << "log: " << evtType << "\n";
|
rt300@1
|
338
|
rt300@1
|
339 // scroll has 2 double coords
|
rt300@1
|
340 // zoom has 1 double scale
|
rt300@1
|
341 // save preset has 2 coords
|
rt300@1
|
342 // switch view has view type
|
rt300@9
|
343 // slider change has int slider index and 1 float value
|
rt300@1
|
344
|
rt300@4
|
345 // get time for key index
|
rt300@4
|
346
|
rt300@5
|
347 // thinFactor
|
rt300@5
|
348 if(!loggingEnabled) return;
|
rt300@4
|
349 switch ( evtType ) {
|
rt300@28
|
350 // data thinning here
|
rt300@28
|
351 case SCROLL:
|
rt300@28
|
352 thinnedLogEvent(lEvent(evtType,centre.x,centre.y));
|
rt300@28
|
353 break;
|
rt300@28
|
354 case ZOOM:
|
rt300@28
|
355 thinnedLogEvent(lEvent(evtType,scale));
|
rt300@28
|
356 break;
|
rt300@28
|
357 case CHANGE_SLIDER:
|
rt300@28
|
358 thinnedLogEvent(lEvent(evtType,sliderVal , 0.0 , sliderID));
|
rt300@28
|
359 break;
|
rt300@29
|
360 // non thinned data
|
rt300@4
|
361 case SAVE_PRESET:
|
rt300@5
|
362 theEvents.push_back(lEvent(evtType,centre.x,centre.y));
|
rt300@4
|
363 // Code
|
rt300@4
|
364 break;
|
rt300@4
|
365 case SAVE_DESET:
|
rt300@5
|
366 theEvents.push_back(lEvent(evtType,centre.x,centre.y));
|
rt300@4
|
367 break;
|
rt300@28
|
368
|
rt300@5
|
369 case SCROLL_STOPPED:
|
rt300@5
|
370 theEvents.push_back(lEvent(evtType,centre.x,centre.y));
|
rt300@22
|
371 cout << "SCROLL STOPPED EVENT\n";
|
rt300@22
|
372 break;
|
rt300@22
|
373 case SNAPPED_TO_PRESET:
|
rt300@22
|
374 theEvents.push_back(lEvent(evtType,centre.x,centre.y,sliderID));
|
rt300@22
|
375 cout << "SCROLL STOPPED EVENT\n";
|
rt300@4
|
376 break;
|
rt300@25
|
377 case SWAP_VIEW:
|
rt300@25
|
378 theEvents.push_back(lEvent(evtType,0.0 , 0.0 , sliderID)); // slider ID is which view
|
rt300@25
|
379 break;
|
rt300@4
|
380 default:
|
rt300@25
|
381 // default is just an event type with no values
|
rt300@25
|
382 theEvents.push_back(lEvent(evtType));
|
rt300@4
|
383 break;
|
rt300@1
|
384 }
|
rt300@27
|
385 if(theEvents.size() > nextUploadQty && !logUploadInProgress){
|
rt300@27
|
386 //try to upload asynchronously
|
rt300@27
|
387 uploadEventLog(true);
|
rt300@7
|
388 }
|
rt300@9
|
389 //sessionTime = (ofGetSystemTime() - sessionStartTime);
|
rt300@28
|
390 totalInteractionTime = savedInteractionTime + (ofGetSystemTime() - sessionStartTime); // milliseconds
|
rt300@28
|
391
|
rt300@1
|
392 }
|
rt300@29
|
393 //--------------------------------------------------------------------
|
rt300@29
|
394 // called from newUser
|
rt300@29
|
395 void EventLogger::deleteLogs(){
|
rt300@29
|
396 // the
|
rt300@29
|
397 theEvents.clear();
|
rt300@29
|
398 string fname = ofxiPhoneGetDocumentsDirectory() + EVENT_LOG_FILENAME;
|
rt300@29
|
399 ofFile logFile(fname,ofFile::WriteOnly);
|
rt300@29
|
400 logFile << "";
|
rt300@29
|
401 logFile.close();
|
rt300@29
|
402 }
|
rt300@8
|
403 //---------------------------------------------------------------------------
|
rt300@7
|
404
|
rt300@7
|
405 void EventLogger::exitAndSave(){
|
rt300@25
|
406
|
rt300@25
|
407 if(!consentGiven){
|
rt300@25
|
408 logEvent(CONSENT_DENIED);
|
rt300@25
|
409 Json::Value jlogs = logsToJson();
|
rt300@25
|
410 // try to upload TODO (no - might hang and prevent exit???)
|
rt300@27
|
411 uploadEventLog(true);
|
rt300@25
|
412 return;
|
rt300@25
|
413 }
|
rt300@25
|
414 logEvent(APP_EXITED);
|
rt300@25
|
415 savedInteractionTime = savedInteractionTime + (ofGetSystemTime() - sessionStartTime);
|
rt300@7
|
416 // save user details
|
rt300@8
|
417 string fname = ofxiPhoneGetDocumentsDirectory() + EVENT_LOG_FILENAME;
|
rt300@8
|
418
|
rt300@31
|
419 // try to upload
|
rt300@31
|
420 // do it sync because event list needs to be cleared to prevent saving on device
|
rt300@27
|
421 uploadEventLog(false);
|
rt300@7
|
422
|
rt300@8
|
423 // write to file
|
rt300@25
|
424 // json without the logs that were uploaded!
|
rt300@25
|
425 Json::Value jlogs = logsToJson();
|
rt300@8
|
426 ofFile logFile(fname,ofFile::WriteOnly);
|
rt300@8
|
427 logFile << jlogs;
|
rt300@29
|
428 logFile.close();
|
rt300@8
|
429
|
rt300@8
|
430 }
|
rt300@8
|
431 //---------------------------------------------------------------------------
|
rt300@8
|
432
|
rt300@8
|
433 Json::Value EventLogger::logsToJson(){
|
rt300@8
|
434 // put all logged events into Json formatted string
|
rt300@8
|
435 Json::Value root;
|
rt300@8
|
436
|
rt300@8
|
437 vector<lEvent>::iterator eventIter;
|
rt300@8
|
438
|
rt300@22
|
439 root["programVersion"] = PROGRAM_VERSION;
|
rt300@8
|
440 root["userName"] = userName;
|
rt300@8
|
441 root["deviceID"] = deviceID;
|
rt300@25
|
442 root["uploadNumber"] = nextUploadNumber;
|
rt300@22
|
443 root["iOSdeviceType"] = iOSdeviceType;
|
rt300@25
|
444 root["savedInteractionTime"] = savedInteractionTime;
|
rt300@22
|
445 root["questionnaireCompleted"] = questionnaireCompleted;
|
rt300@22
|
446 root["questionnaireUploaded"] = questionnaireUploaded;
|
rt300@30
|
447 root["questionnaire"] = questionnaireToJson();
|
rt300@30
|
448
|
rt300@8
|
449
|
rt300@8
|
450 int i = 0;
|
rt300@8
|
451 for(eventIter = theEvents.begin(); eventIter < theEvents.end(); eventIter++){
|
rt300@8
|
452 root["events"][i] = (*eventIter).eventToJson();
|
rt300@8
|
453 i++;
|
rt300@7
|
454 }
|
rt300@25
|
455 root["numEventsHere"] = i;
|
rt300@8
|
456 return root;
|
rt300@8
|
457 }
|
rt300@22
|
458
|
rt300@8
|
459 //---------------------------------------------------------------------------
|
rt300@22
|
460
|
rt300@22
|
461 Json::Value EventLogger::questionnaireToJson(){
|
rt300@22
|
462 // put all answers into Json formatted string
|
rt300@22
|
463 Json::Value root;
|
rt300@22
|
464
|
rt300@22
|
465 vector<int>::iterator aIter;
|
rt300@22
|
466
|
rt300@22
|
467 Json::Value questionnaire;
|
rt300@22
|
468
|
rt300@22
|
469 int i = 0;
|
rt300@22
|
470 for(aIter = questionnaireAnswers.begin(); aIter < questionnaireAnswers.end(); aIter++){
|
rt300@22
|
471 questionnaire[i] = (*aIter);
|
rt300@22
|
472 i++;
|
rt300@22
|
473 }
|
rt300@22
|
474
|
rt300@22
|
475 root["qAnswers"] = questionnaire;
|
rt300@28
|
476 root["comments"] = questionnaireComments;
|
rt300@22
|
477 root["userName"] = userName;
|
rt300@22
|
478 root["deviceID"] = deviceID;
|
rt300@22
|
479 root["iOSdeviceType"] = iOSdeviceType;
|
rt300@22
|
480 root["programVersion"] = PROGRAM_VERSION;
|
rt300@22
|
481
|
rt300@22
|
482 return root;
|
rt300@22
|
483 }
|
rt300@30
|
484
|
rt300@8
|
485 //---------------------------------------------------------------------------
|
rt300@30
|
486 void EventLogger::printAll(){
|
rt300@30
|
487 cout << "-----------------ALL LOGGED EVENTS----------------- \n";
|
rt300@30
|
488 vector<lEvent>::iterator evIter;
|
rt300@30
|
489 cout << logsToJson() << "\n";
|
rt300@30
|
490 cout << "---------------------QUESTIONNAIRE---------------- \n";
|
rt300@30
|
491 cout << questionnaireToJson() << "\n";
|
rt300@30
|
492 };
|
rt300@8
|
493 //---------------------------------------------------------------------------
|
rt300@32
|
494
|
rt300@32
|
495 void EventLogger::saveSessionToFile(){
|
rt300@32
|
496 string fname = ofxiPhoneGetDocumentsDirectory() + userName + '_' + EVENT_LOG_FILENAME;
|
rt300@32
|
497
|
rt300@32
|
498 // write to file
|
rt300@32
|
499 // json without the logs that were uploaded!
|
rt300@32
|
500 Json::Value jlogs = logsToJson();
|
rt300@32
|
501 ofFile logFile(fname,ofFile::WriteOnly);
|
rt300@32
|
502 logFile << jlogs;
|
rt300@32
|
503 logFile.close();
|
rt300@32
|
504
|
rt300@32
|
505 }
|