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@8
|
12
|
rt300@1
|
13 EventLogger eventLogger;
|
rt300@16
|
14 extern UsernameAlertViewController *usernameAlertViewController;
|
rt300@1
|
15
|
rt300@8
|
16 //---------------------------------------------------------------------------
|
rt300@1
|
17 EventLogger::EventLogger(){
|
rt300@14
|
18 //QuestionnaireViewController * questionnaireViewController;
|
rt300@8
|
19
|
rt300@14
|
20
|
rt300@8
|
21 loggingEnabled = true;
|
rt300@22
|
22 serverConnectionOK = false;
|
rt300@22
|
23 questionnaireCompleted = false;
|
rt300@22
|
24 questionnaireUploaded = false;
|
rt300@22
|
25
|
rt300@22
|
26
|
rt300@22
|
27 ofxiPhoneDeviceType iOSdeviceType = ofxiPhoneGetDeviceType();
|
rt300@22
|
28 cout << "Device: " << iOSdeviceType << '\n';
|
rt300@22
|
29
|
rt300@9
|
30 nextUploadQty = 5000; // amount of data uploaded is always more than 5000 events
|
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@16
|
43
|
rt300@8
|
44 }
|
rt300@8
|
45 //---------------------------------------------------------------------------
|
rt300@22
|
46 void EventLogger::questionnaireAnswersObtained(vector<int> answers){
|
rt300@22
|
47
|
rt300@22
|
48 questionnaireCompleted = true;
|
rt300@22
|
49 questionnaireAnswers = answers;
|
rt300@22
|
50
|
rt300@22
|
51 uploadQuestionnaire();
|
rt300@22
|
52
|
rt300@22
|
53 }
|
rt300@22
|
54 //---------------------------------------------------------------------------
|
rt300@22
|
55 bool EventLogger::uploadQuestionnaire(){
|
rt300@22
|
56 // show indicator
|
rt300@22
|
57 cout << "^^^^^^^^ UPLOADING QUESTIONNAIRE ^^^^^^^^ \n";
|
rt300@22
|
58
|
rt300@22
|
59 questionnaireUploaded = sendToServer("questionnaire", questionnaireToJson());
|
rt300@22
|
60 return questionnaireUploaded;
|
rt300@22
|
61 }
|
rt300@22
|
62 //---------------------------------------------------------------------------
|
rt300@22
|
63 bool EventLogger::sendToServer(string functionName, Json::Value jsonData){
|
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@22
|
77 if (!jsontext.empty() && jsontext[jsontext.length()-1] == '\n') {
|
rt300@22
|
78 jsontext.erase(jsontext.length()-1);
|
rt300@22
|
79 }
|
rt300@22
|
80
|
rt300@22
|
81 request.append(jsontext);
|
rt300@22
|
82
|
rt300@9
|
83 ofURLFileLoader fileLoader;
|
rt300@9
|
84 ofHttpResponse resp;
|
rt300@22
|
85 resp = fileLoader.get(request);
|
rt300@24
|
86 //fileLoader.getAsync(request);
|
rt300@9
|
87 cout << "HTTP STATUS " << resp.status << "\n";
|
rt300@9
|
88 cout << "HTTP ERROR " << resp.error << "\n";
|
rt300@22
|
89 cout << "HTTP DATA " << resp.data << "\n"; // ofBuffer
|
rt300@9
|
90
|
rt300@22
|
91 stringstream response;
|
rt300@22
|
92 response << resp.data;
|
rt300@22
|
93
|
rt300@22
|
94 if (resp.status == 200){
|
rt300@22
|
95 if(response.str() == "OK"){
|
rt300@22
|
96
|
rt300@22
|
97 sent = true;
|
rt300@22
|
98 }else{
|
rt300@22
|
99 // not ok
|
rt300@22
|
100 // problem serverside
|
rt300@22
|
101 sent = false;
|
rt300@22
|
102 }
|
rt300@9
|
103 }else{
|
rt300@22
|
104
|
rt300@22
|
105 sent = false;
|
rt300@9
|
106 // SHOW AN ALERT TO USER?
|
rt300@9
|
107 }
|
rt300@22
|
108 return sent;
|
rt300@22
|
109 }
|
rt300@22
|
110 //---------------------------------------------------------------------------
|
rt300@22
|
111 bool EventLogger::testConnection(){
|
rt300@22
|
112 Json::Value root;
|
rt300@22
|
113 root["test"] = "test";
|
rt300@22
|
114
|
rt300@22
|
115
|
rt300@22
|
116 serverConnectionOK = sendToServer("testConnection", root);
|
rt300@22
|
117 if (serverConnectionOK){
|
rt300@22
|
118 cout << "^^^^^^^^ server connection OK ^^^^^^^^ \n";
|
rt300@22
|
119 }else{
|
rt300@22
|
120 cout << "server connection ERROR \n";
|
rt300@22
|
121 }
|
rt300@9
|
122 }
|
rt300@9
|
123 //---------------------------------------------------------------------------
|
rt300@8
|
124 void EventLogger::readJsonToLog(const string &jsonFile){
|
rt300@8
|
125 Json::Value root;
|
rt300@8
|
126 Json::Reader reader;
|
rt300@5
|
127
|
rt300@5
|
128
|
rt300@8
|
129 ifstream theFile(jsonFile.c_str());
|
rt300@8
|
130 stringstream fileText;
|
rt300@8
|
131 string line;
|
rt300@8
|
132 if(!theFile){
|
rt300@8
|
133 cout<<"no event log file - first APP open\n";
|
rt300@8
|
134
|
rt300@8
|
135 firstEverAppOpen();
|
rt300@8
|
136
|
rt300@8
|
137 return;
|
rt300@8
|
138 }else{
|
rt300@8
|
139 while(theFile){
|
rt300@8
|
140 theFile >> line;
|
rt300@9
|
141 // cout << line; // lots!!!!
|
rt300@8
|
142 fileText << line;
|
rt300@8
|
143 }
|
rt300@8
|
144 theFile.close();
|
rt300@8
|
145 }
|
rt300@8
|
146
|
rt300@9
|
147 cout << "size of log JSON string:" << fileText.str().length() << "BYTES \n";
|
rt300@9
|
148
|
rt300@8
|
149 bool parsingSuccessful = reader.parse( fileText.str(), root );
|
rt300@8
|
150
|
rt300@8
|
151 if ( !parsingSuccessful )
|
rt300@8
|
152 {
|
rt300@8
|
153 // report to the user the failure and their locations in the document.
|
rt300@22
|
154 std::cout << "Failed to parse event log JSON: \n"
|
rt300@8
|
155 << reader.getFormattedErrorMessages();
|
rt300@8
|
156 return;
|
rt300@8
|
157 }
|
rt300@8
|
158
|
rt300@8
|
159 // now put user deets into variables
|
rt300@8
|
160 userName = root["userName"].asString();
|
rt300@8
|
161 deviceID = root["deviceID"].asLargestInt();
|
rt300@8
|
162 totalInteractionTime = root["totalInteractionTime"].asLargestInt();
|
rt300@22
|
163 questionnaireCompleted = root["questionnaireCompleted"].asBool();
|
rt300@22
|
164 questionnaireUploaded = root["questionnaireUploaded"].asBool();
|
rt300@22
|
165
|
rt300@22
|
166
|
rt300@22
|
167 if(questionnaireCompleted && !questionnaireUploaded){
|
rt300@22
|
168 // then read it in and upload it
|
rt300@22
|
169 Json::Value JArray = root["questionnaireAnswers"];
|
rt300@22
|
170 if(JArray.size() < 2){
|
rt300@22
|
171 cout << "Error - status of questionnaire is wierd\n";
|
rt300@22
|
172 }
|
rt300@22
|
173 for ( unsigned int i = 0; i < JArray.size(); i++ )
|
rt300@22
|
174 {
|
rt300@22
|
175 questionnaireAnswers.push_back(JArray[1].asInt());
|
rt300@22
|
176 }
|
rt300@22
|
177 uploadQuestionnaire();
|
rt300@22
|
178 }
|
rt300@8
|
179
|
rt300@8
|
180 // check for unuploaded evts
|
rt300@8
|
181 const Json::Value jlogs = root["events"];
|
rt300@8
|
182
|
rt300@8
|
183 for ( int index = 0; index < jlogs.size(); ++index ) theEvents.push_back(lEvent(jlogs[index]));
|
rt300@9
|
184 if(theEvents.size() > nextUploadQty){
|
rt300@8
|
185 //try to upload
|
rt300@22
|
186 uploadEventLog();
|
rt300@8
|
187 }
|
rt300@8
|
188 // TODO if the total interaction time is greater than a certain amount && no questions answered - questionnaire time!
|
rt300@14
|
189 cout << "Total interaction time: " << totalInteractionTime << '\n';
|
rt300@8
|
190
|
rt300@22
|
191 if(totalInteractionTime > 123){
|
rt300@22
|
192 //testApp->showQuestionnaire();
|
rt300@14
|
193
|
rt300@14
|
194 }
|
rt300@22
|
195 // is there logged stuff that hasn't been uploaded yet? - handled automatically
|
rt300@22
|
196
|
rt300@9
|
197
|
rt300@8
|
198
|
rt300@9
|
199 }
|
rt300@9
|
200
|
rt300@9
|
201
|
rt300@9
|
202 //---------------------------------------------------------------------------
|
rt300@9
|
203
|
rt300@22
|
204 bool EventLogger::uploadEventLog(){
|
rt300@22
|
205 // show indicator
|
rt300@22
|
206 cout << "^^^^^^^^ UPLOADING: " << theEvents.size() << " EVENTS ^^^^^^^^ .\n";
|
rt300@9
|
207
|
rt300@22
|
208 bool logUploaded = sendToServer("eventlog", logsToJson());
|
rt300@22
|
209 if(!logUploaded){
|
rt300@9
|
210 // try later
|
rt300@9
|
211 nextUploadQty += 5000;
|
rt300@9
|
212 }else{
|
rt300@9
|
213
|
rt300@9
|
214 // if success - clear memory
|
rt300@9
|
215 theEvents.clear();
|
rt300@9
|
216 }
|
rt300@22
|
217 return logUploaded;
|
rt300@8
|
218
|
rt300@1
|
219 }
|
rt300@8
|
220 //----------------------------------------------------------------------------
|
rt300@9
|
221 //void EventLogger::deleteLogFile(){
|
rt300@8
|
222
|
rt300@8
|
223 //---------------------------------------------------------------------------
|
rt300@8
|
224
|
rt300@8
|
225 void EventLogger::firstEverAppOpen(){
|
rt300@8
|
226 deviceID = ofGetSystemTimeMicros();
|
rt300@8
|
227 totalInteractionTime = 0;
|
rt300@22
|
228 questionnaireCompleted = false;
|
rt300@22
|
229 questionnaireUploaded = false;
|
rt300@8
|
230
|
rt300@24
|
231 ((testApp *)ofGetAppPtr())->showIntro();
|
rt300@24
|
232
|
rt300@24
|
233
|
rt300@24
|
234 //[usernameAlertViewController showUserNamePrompt];
|
rt300@9
|
235 // then we get userName via setUsername, called from button delegate
|
rt300@8
|
236
|
rt300@8
|
237 }
|
rt300@8
|
238 //---------------------------------------------------------------------------
|
rt300@8
|
239 // called from alertView OK in iViewController
|
rt300@8
|
240 void EventLogger::setUsername(const char *u){
|
rt300@8
|
241 userName = u;
|
rt300@7
|
242
|
rt300@7
|
243 }
|
rt300@8
|
244
|
rt300@8
|
245 //---------------------------------------------------------------------------
|
rt300@8
|
246 // log zoom event
|
rt300@5
|
247 void EventLogger::logEvent(const leventType& evtType,const TwoVector& centre, const double& scale, const int& sliderID, const double& sliderVal){
|
rt300@3
|
248 //cout << "log: " << evtType << "\n";
|
rt300@1
|
249
|
rt300@1
|
250 // scroll has 2 double coords
|
rt300@1
|
251 // zoom has 1 double scale
|
rt300@1
|
252 // save preset has 2 coords
|
rt300@1
|
253 // switch view has view type
|
rt300@9
|
254 // slider change has int slider index and 1 float value
|
rt300@1
|
255
|
rt300@4
|
256 // get time for key index
|
rt300@4
|
257
|
rt300@5
|
258 // thinFactor
|
rt300@5
|
259 if(!loggingEnabled) return;
|
rt300@4
|
260 switch ( evtType ) {
|
rt300@4
|
261 case SAVE_PRESET:
|
rt300@5
|
262 theEvents.push_back(lEvent(evtType,centre.x,centre.y));
|
rt300@4
|
263 // Code
|
rt300@4
|
264 break;
|
rt300@4
|
265 case SAVE_DESET:
|
rt300@5
|
266 theEvents.push_back(lEvent(evtType,centre.x,centre.y));
|
rt300@4
|
267 break;
|
rt300@4
|
268 case SCROLL:
|
rt300@5
|
269 theEvents.push_back(lEvent(evtType,centre.x,centre.y));
|
rt300@5
|
270 break;
|
rt300@5
|
271 case SCROLL_STOPPED:
|
rt300@5
|
272 theEvents.push_back(lEvent(evtType,centre.x,centre.y));
|
rt300@22
|
273 cout << "SCROLL STOPPED EVENT\n";
|
rt300@22
|
274 break;
|
rt300@22
|
275 case SNAPPED_TO_PRESET:
|
rt300@22
|
276 theEvents.push_back(lEvent(evtType,centre.x,centre.y,sliderID));
|
rt300@22
|
277 cout << "SCROLL STOPPED EVENT\n";
|
rt300@4
|
278 break;
|
rt300@4
|
279 case ZOOM:
|
rt300@5
|
280 theEvents.push_back(lEvent(evtType,scale));
|
rt300@4
|
281 break;
|
rt300@4
|
282 case CHANGE_SLIDER:
|
rt300@5
|
283 theEvents.push_back(lEvent(evtType,sliderVal , 0.0 , sliderID));
|
rt300@4
|
284 break;
|
rt300@4
|
285 default:
|
rt300@4
|
286 // Code
|
rt300@4
|
287 break;
|
rt300@1
|
288 }
|
rt300@8
|
289 if(theEvents.size() > nextUploadQty){
|
rt300@7
|
290 //try to upload
|
rt300@22
|
291 uploadEventLog();
|
rt300@7
|
292 }
|
rt300@9
|
293 //sessionTime = (ofGetSystemTime() - sessionStartTime);
|
rt300@7
|
294
|
rt300@1
|
295
|
rt300@1
|
296 }
|
rt300@8
|
297
|
rt300@8
|
298 //---------------------------------------------------------------------------
|
rt300@7
|
299
|
rt300@7
|
300 void EventLogger::exitAndSave(){
|
rt300@8
|
301 totalInteractionTime = totalInteractionTime + (ofGetSystemTime() - sessionStartTime);
|
rt300@7
|
302 // save user details
|
rt300@8
|
303 string fname = ofxiPhoneGetDocumentsDirectory() + EVENT_LOG_FILENAME;
|
rt300@8
|
304
|
rt300@8
|
305 Json::Value jlogs = logsToJson();
|
rt300@8
|
306 // try to upload
|
rt300@22
|
307 uploadEventLog();
|
rt300@7
|
308
|
rt300@8
|
309 // write to file
|
rt300@8
|
310
|
rt300@8
|
311 ofFile logFile(fname,ofFile::WriteOnly);
|
rt300@8
|
312 logFile << jlogs;
|
rt300@8
|
313
|
rt300@8
|
314 }
|
rt300@8
|
315 //---------------------------------------------------------------------------
|
rt300@8
|
316
|
rt300@8
|
317 Json::Value EventLogger::logsToJson(){
|
rt300@8
|
318 // put all logged events into Json formatted string
|
rt300@8
|
319 Json::Value root;
|
rt300@8
|
320
|
rt300@8
|
321 vector<lEvent>::iterator eventIter;
|
rt300@8
|
322
|
rt300@22
|
323 root["programVersion"] = PROGRAM_VERSION;
|
rt300@8
|
324 root["userName"] = userName;
|
rt300@8
|
325 root["deviceID"] = deviceID;
|
rt300@22
|
326 root["iOSdeviceType"] = iOSdeviceType;
|
rt300@8
|
327 root["totalInteractionTime"] = totalInteractionTime;
|
rt300@22
|
328 root["questionnaireCompleted"] = questionnaireCompleted;
|
rt300@22
|
329 root["questionnaireUploaded"] = questionnaireUploaded;
|
rt300@22
|
330 if(questionnaireCompleted && !questionnaireUploaded){
|
rt300@22
|
331 root["qAnswers"] = questionnaireToJson();
|
rt300@22
|
332 }
|
rt300@8
|
333
|
rt300@8
|
334 int i = 0;
|
rt300@8
|
335 for(eventIter = theEvents.begin(); eventIter < theEvents.end(); eventIter++){
|
rt300@8
|
336 root["events"][i] = (*eventIter).eventToJson();
|
rt300@8
|
337 i++;
|
rt300@7
|
338 }
|
rt300@8
|
339
|
rt300@8
|
340 return root;
|
rt300@8
|
341 }
|
rt300@22
|
342
|
rt300@8
|
343 //---------------------------------------------------------------------------
|
rt300@22
|
344
|
rt300@22
|
345 Json::Value EventLogger::questionnaireToJson(){
|
rt300@22
|
346 // put all answers into Json formatted string
|
rt300@22
|
347 Json::Value root;
|
rt300@22
|
348
|
rt300@22
|
349 vector<int>::iterator aIter;
|
rt300@22
|
350
|
rt300@22
|
351 Json::Value questionnaire;
|
rt300@22
|
352
|
rt300@22
|
353 int i = 0;
|
rt300@22
|
354 for(aIter = questionnaireAnswers.begin(); aIter < questionnaireAnswers.end(); aIter++){
|
rt300@22
|
355 questionnaire[i] = (*aIter);
|
rt300@22
|
356 i++;
|
rt300@22
|
357 }
|
rt300@22
|
358
|
rt300@22
|
359 root["qAnswers"] = questionnaire;
|
rt300@22
|
360 root["userName"] = userName;
|
rt300@22
|
361 root["deviceID"] = deviceID;
|
rt300@22
|
362 root["iOSdeviceType"] = iOSdeviceType;
|
rt300@22
|
363 root["programVersion"] = PROGRAM_VERSION;
|
rt300@22
|
364
|
rt300@22
|
365 return root;
|
rt300@22
|
366 }
|
rt300@8
|
367 //---------------------------------------------------------------------------
|
rt300@8
|
368 //---------------------------------------------------------------------------
|
rt300@22
|
369 //---------------------------------------------------------------------------
|