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