rt300@0
|
1 //
|
rt300@0
|
2 // eventLogger.h
|
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 // This class handle everything to do with loggin user actions,
|
rt300@0
|
9 // uploading logs to server, and storing locally if not uploaded
|
rt300@0
|
10
|
rt300@0
|
11 #ifndef __oscSenderExample__eventLogger__
|
rt300@0
|
12 #define __oscSenderExample__eventLogger__
|
rt300@0
|
13
|
rt300@1
|
14
|
rt300@4
|
15 #include "ofMain.h"
|
rt300@4
|
16 #include "ofxiPhone.h"
|
rt300@4
|
17 #include "2dvector.h"
|
rt300@4
|
18 #include "ofxiPhoneExtras.h"
|
rt300@4
|
19 #include <sys/time.h>
|
rt300@4
|
20 #include <iostream>
|
rt300@4
|
21 #include <string>
|
rt300@22
|
22 #include <cstring>
|
rt300@4
|
23 #include <map>
|
rt300@4
|
24 #include "2dvector.h"
|
rt300@8
|
25 #include "json.h"
|
rt300@24
|
26 #include "testApp.h"
|
rt300@32
|
27 #include "presetManager.h"
|
rt300@29
|
28 #import "ServerComms.h"
|
rt300@33
|
29 #include "grid.h"
|
rt300@33
|
30
|
rt300@38
|
31 #define EVENT_THIN_FACTOR 12
|
rt300@25
|
32 #define EVENT_LOG_FILENAME "log.json"
|
rt300@42
|
33 #define UPLOAD_CHUNK_SIZE 1000
|
rt300@33
|
34 #define APP_CREATION_TIME 381429000000 // milliseconds to the time i wrote this wee blighter. saves digits
|
rt300@33
|
35 #define SCROLL_TRAIL_LENGTH 200
|
rt300@47
|
36 #define PROGRAM_VERSION 1.0 // NOW USES NEW HILBERT CURVE. ALL OLD PRESETS WILL BE INVALID :(
|
rt300@29
|
37
|
rt300@33
|
38 #define SUPERVISED // this def will save files
|
rt300@25
|
39
|
rt300@25
|
40
|
rt300@9
|
41 // can add but don't change ordering - this will invalidate logs
|
rt300@25
|
42 enum leventType {SAVE_PRESET, // 0
|
rt300@25
|
43 SAVE_DESET, // 1
|
rt300@25
|
44 SCROLL, // 2
|
rt300@25
|
45 ZOOM, // 3
|
rt300@25
|
46 SCROLL_STOPPED, // 4
|
rt300@25
|
47 ZOOM_STOPPED, // 5
|
rt300@25
|
48 SNAPPED_TO_PRESET, // 6
|
rt300@25
|
49 CHANGE_SLIDER, // 7
|
rt300@25
|
50 SWAP_VIEW, // 8
|
rt300@25
|
51 SET_MIN_ZOOM, // 9
|
rt300@25
|
52 SET_MAX_ZOOM, // 10
|
rt300@25
|
53 RANDOMISE, // 11
|
rt300@25
|
54 APP_STARTED, // 12
|
rt300@25
|
55 APP_EXITED, // 13
|
rt300@25
|
56 CONSENT_DENIED, // 14
|
rt300@25
|
57 SEQ_LOCKED, // 15
|
rt300@25
|
58 SYNTH_LOCKED, // 16
|
rt300@25
|
59 PLAY_PRESSED, // 17
|
rt300@27
|
60 PAUSE_PRESSED, // 18
|
rt300@31
|
61 HELP_PRESSED, // 19
|
rt300@33
|
62 QUESTIONNAIRE_COMPLETED, // 20
|
rt300@33
|
63 EVALUATION_POINT, // 21
|
rt300@39
|
64 EMPTY_EVENT, // 22
|
rt300@39
|
65 SMOOTHING_ON, // 23
|
rt300@44
|
66 SMOOTHING_OFF, // 24
|
rt300@44
|
67 SNAPPED_TO_EVALPT, // 25
|
rt300@44
|
68 PRESET_DOUBLE_TAPPED};
|
rt300@1
|
69
|
rt300@8
|
70 //---------------------------------------------------------------------------
|
rt300@8
|
71
|
rt300@4
|
72 class lEvent{
|
rt300@5
|
73 public:
|
rt300@1
|
74 // try and make this as compact as possible.
|
rt300@4
|
75 leventType eventType;
|
rt300@1
|
76 double val1; // x coord, scale if zoom
|
rt300@1
|
77 double val2; // y coord, 0 if zoom
|
rt300@25
|
78 int sliderID; // xtra int
|
rt300@32
|
79 long long eventTime; // MILLISECONDS since app creation
|
rt300@8
|
80 lEvent(leventType eType, double v1 = 0.0, double v2 = 0.0,int sID = 0){
|
rt300@5
|
81 eventType = eType;
|
rt300@5
|
82 val1 = v1;
|
rt300@5
|
83 val2 = v2;
|
rt300@5
|
84 sliderID = sID;
|
rt300@9
|
85
|
rt300@28
|
86 double timemsd = [NSDate timeIntervalSinceReferenceDate]; // MILLISECONDS
|
rt300@25
|
87 eventTime = (unsigned long long)(timemsd*1000) - APP_CREATION_TIME;
|
rt300@9
|
88
|
rt300@5
|
89 }
|
rt300@25
|
90
|
rt300@8
|
91 lEvent(const Json::Value &jevt){
|
rt300@9
|
92 // constructor takes "jsonToEvent" readfile function role
|
rt300@25
|
93 eventType = (leventType)jevt["eType"].asInt();
|
rt300@25
|
94 val1 = jevt["v1"].asDouble();
|
rt300@25
|
95 val2 = jevt["v2"].asDouble();
|
rt300@25
|
96 sliderID = jevt["sID"].asInt();
|
rt300@25
|
97 eventTime = jevt["eTime"].asLargestInt();
|
rt300@9
|
98
|
rt300@15
|
99 // TODO what happens if we try to read one that isn't there?
|
rt300@15
|
100
|
rt300@8
|
101 }
|
rt300@8
|
102 Json::Value eventToJson(){
|
rt300@8
|
103 Json::Value jevt;
|
rt300@25
|
104 jevt["eType"] = eventType;
|
rt300@25
|
105 // here: should give a certain number of sig figs?
|
rt300@25
|
106 jevt["v1"] = val1;
|
rt300@25
|
107 jevt["v2"] = val2;
|
rt300@25
|
108 jevt["sID"] = sliderID;
|
rt300@25
|
109 jevt["eTime"] = eventTime;
|
rt300@8
|
110 return jevt;
|
rt300@8
|
111 }
|
rt300@33
|
112 void draw();
|
rt300@5
|
113 };
|
rt300@5
|
114 //---------------------------------------------------------------------------
|
rt300@8
|
115 // streams no longer used
|
rt300@5
|
116 inline istream& operator>>(istream & is, lEvent& e){
|
rt300@5
|
117 is.setf(ios_base::fixed,ios_base::floatfield);
|
rt300@5
|
118 is.precision(1);
|
rt300@4
|
119
|
rt300@5
|
120 char delim;
|
rt300@5
|
121 int eType;
|
rt300@0
|
122
|
rt300@5
|
123 is >> eType >> delim >> e.val1 >> delim >> e.val2 >> delim >> e.sliderID;
|
rt300@5
|
124
|
rt300@5
|
125 e.eventType = (leventType)eType;
|
rt300@5
|
126
|
rt300@5
|
127 return is;
|
rt300@5
|
128 }
|
rt300@4
|
129
|
rt300@5
|
130 //---------------------------------------------------------------------------
|
rt300@5
|
131 inline ostream& operator<<(ostream & os, const lEvent& e){
|
rt300@5
|
132 os.setf(ios_base::fixed,ios_base::floatfield);
|
rt300@5
|
133 os.precision(1);
|
rt300@5
|
134
|
rt300@5
|
135 os << e.eventType << ',' << e.val1 << ',' << e.val2 << ',' << e.sliderID << '\n';
|
rt300@5
|
136
|
rt300@5
|
137 return os;
|
rt300@7
|
138 }
|
rt300@5
|
139 //---------------------------------------------------------------------------
|
rt300@32
|
140
|
rt300@29
|
141
|
rt300@0
|
142 class EventLogger{
|
rt300@0
|
143 public:
|
rt300@25
|
144 int nextUploadNumber;
|
rt300@14
|
145 bool loggingEnabled;
|
rt300@31
|
146
|
rt300@27
|
147 bool logUploadInProgress;
|
rt300@22
|
148 bool serverConnectionOK;
|
rt300@25
|
149 bool consentGiven;
|
rt300@29
|
150 bool questionnaireCompleted;
|
rt300@29
|
151 bool questionnaireUploaded;
|
rt300@31
|
152
|
rt300@29
|
153 unsigned int deviceID;
|
rt300@25
|
154 unsigned int totalInteractionTime, savedInteractionTime, sessionTime, sessionStartTime;
|
rt300@14
|
155 string userName; // not unique
|
rt300@27
|
156
|
rt300@31
|
157 // constr
|
rt300@14
|
158 EventLogger();
|
rt300@31
|
159
|
rt300@31
|
160 // public methods:
|
rt300@42
|
161 void startLoadAll();
|
rt300@14
|
162 void exitAndSave();
|
rt300@14
|
163 void setUsername(const char *u);
|
rt300@27
|
164 void newUser();
|
rt300@14
|
165 void logEvent(const leventType& evtType,const TwoVector& centre = TwoVector(), const double& scale = 1.0, const int& sliderID = -1, const double& sliderVal = 0.0);
|
rt300@28
|
166 void questionnaireAnswersObtained(vector<int> answers, const char* userComments);
|
rt300@27
|
167 void urlResponse(ofHttpResponse & response);
|
rt300@30
|
168
|
rt300@30
|
169 void questionnaireOK();
|
rt300@30
|
170 void eventlogOK();
|
rt300@30
|
171 void testConnectionOK();
|
rt300@30
|
172 void questionnaireNotOK();
|
rt300@30
|
173 void eventlogNotOK();
|
rt300@30
|
174 void testConnectionNotOK();
|
rt300@30
|
175
|
rt300@30
|
176 void printAll();
|
rt300@32
|
177 void saveSessionToFile();
|
rt300@33
|
178 void drawTrail(const TwoVector min, const TwoVector max);
|
rt300@33
|
179 vector<lEvent> getDrawableEventsInRange(const TwoVector min, const TwoVector max);
|
rt300@44
|
180 vector<lEvent *> getEvaluationPointsInRange(const TwoVector min, const TwoVector max);
|
rt300@33
|
181 vector<TwoVector> getRecentPath(int numEvents);
|
rt300@38
|
182
|
rt300@38
|
183 void clearTrail();
|
rt300@14
|
184 private:
|
rt300@31
|
185
|
rt300@38
|
186 vector<lEvent> theEvents; // all logged but not uploaded events
|
rt300@38
|
187 deque<lEvent> eventsToDraw; // 200 or so drawable events, maybe uploaded maybe not
|
rt300@29
|
188
|
rt300@39
|
189 void thinnedSliderEvent(lEvent nextEvent);
|
rt300@39
|
190 void thinnedZoomEvent(lEvent nextEvent);
|
rt300@39
|
191 void thinnedSnapEvent(lEvent nextEvent);
|
rt300@33
|
192 void thinnedScrollEvent(lEvent nextEvent);
|
rt300@14
|
193 unsigned int nextUploadQty;
|
rt300@14
|
194
|
rt300@28
|
195 string questionnaireComments;
|
rt300@8
|
196
|
rt300@22
|
197 ofxiPhoneDeviceType iOSdeviceType;
|
rt300@14
|
198
|
rt300@42
|
199
|
rt300@22
|
200 vector<int> questionnaireAnswers;
|
rt300@28
|
201 int interfaceOrder;
|
rt300@9
|
202
|
rt300@31
|
203 // private methods
|
rt300@42
|
204 void testConnection();
|
rt300@7
|
205 void checkLogFile();
|
rt300@29
|
206 void deleteLogs(); // new user
|
rt300@27
|
207 bool uploadEventLog(bool async);
|
rt300@7
|
208 void firstEverAppOpen();
|
rt300@42
|
209 void loadExistingLogFile(const string &jsonFile);
|
rt300@27
|
210 void uploadQuestionnaire();
|
rt300@27
|
211 bool sendToServer(string functionName, Json::Value jsonData, bool async);
|
rt300@30
|
212
|
rt300@43
|
213
|
rt300@8
|
214 Json::Value logsToJson();
|
rt300@22
|
215 Json::Value questionnaireToJson();
|
rt300@30
|
216
|
rt300@29
|
217
|
rt300@29
|
218 //
|
rt300@29
|
219 ServerComms *serverComms;
|
rt300@29
|
220
|
rt300@0
|
221 };
|
rt300@0
|
222
|
rt300@44
|
223 lEvent * e;
|
rt300@44
|
224
|
rt300@8
|
225 //---------------------------------------------------------------------------
|
rt300@8
|
226
|
rt300@5
|
227
|
rt300@0
|
228 #endif /* defined(__oscSenderExample__eventLogger__) */
|