rt300@0: // rt300@0: // eventLogger.h rt300@0: // oscSenderExample rt300@0: // rt300@0: // Created by Robert Tubb on 05/11/2012. rt300@0: // rt300@0: // rt300@0: // This class handle everything to do with loggin user actions, rt300@0: // uploading logs to server, and storing locally if not uploaded rt300@0: rt300@0: #ifndef __oscSenderExample__eventLogger__ rt300@0: #define __oscSenderExample__eventLogger__ rt300@0: rt300@8: #define EVENT_LOG_FILENAME "log.json" rt300@22: #define SERVER_URL "http://127.0.0.1:8080/testservice/" rt300@1: rt300@4: #include "ofMain.h" rt300@4: #include "ofxiPhone.h" rt300@4: #include "2dvector.h" rt300@4: #include "ofxiPhoneExtras.h" rt300@4: #include rt300@4: #include rt300@4: #include rt300@22: #include rt300@4: #include rt300@4: #include "2dvector.h" rt300@8: #include "json.h" rt300@8: rt300@16: #import "usernameAlertViewController.h" rt300@16: rt300@8: rt300@9: // can add but don't change ordering - this will invalidate logs rt300@22: #define PROGRAM_VERSION 1.0 rt300@9: enum leventType {SAVE_PRESET, rt300@9: SAVE_DESET, rt300@9: SCROLL, rt300@22: ZOOM, rt300@9: SCROLL_STOPPED, rt300@22: ZOOM_STOPPED, rt300@22: SNAPPED_TO_PRESET, rt300@9: CHANGE_SLIDER, rt300@9: SWAP_VIEW, rt300@9: SET_MIN_ZOOM, rt300@9: SET_MAX_ZOOM}; rt300@1: rt300@8: //--------------------------------------------------------------------------- rt300@8: rt300@4: class lEvent{ rt300@5: public: rt300@1: // try and make this as compact as possible. rt300@4: leventType eventType; rt300@1: double val1; // x coord, scale if zoom rt300@1: double val2; // y coord, 0 if zoom rt300@4: int sliderID; rt300@9: long long eventTime; rt300@8: lEvent(leventType eType, double v1 = 0.0, double v2 = 0.0,int sID = 0){ rt300@5: eventType = eType; rt300@5: val1 = v1; rt300@5: val2 = v2; rt300@5: sliderID = sID; rt300@9: rt300@9: double timemsd = [NSDate timeIntervalSinceReferenceDate]; rt300@9: eventTime = (unsigned long long)(timemsd*1000); rt300@9: rt300@5: } rt300@8: lEvent(const Json::Value &jevt){ rt300@9: // constructor takes "jsonToEvent" readfile function role rt300@8: eventType = (leventType)jevt["eventType"].asInt(); rt300@8: val1 = jevt["val1"].asFloat(); rt300@8: val2 = jevt["val2"].asFloat(); rt300@8: sliderID = jevt["sliderID"].asInt(); rt300@9: eventTime = jevt["eventTime"].asLargestInt(); rt300@9: rt300@15: // TODO what happens if we try to read one that isn't there? rt300@15: rt300@8: } rt300@8: Json::Value eventToJson(){ rt300@8: Json::Value jevt; rt300@8: jevt["eventType"] = eventType; rt300@8: jevt["val1"] = val1; rt300@8: jevt["val2"] = val2; rt300@8: jevt["sliderID"] = sliderID; rt300@9: jevt["eventTime"] = eventTime; rt300@8: return jevt; rt300@8: } rt300@5: }; rt300@5: //--------------------------------------------------------------------------- rt300@8: // streams no longer used rt300@5: inline istream& operator>>(istream & is, lEvent& e){ rt300@5: is.setf(ios_base::fixed,ios_base::floatfield); rt300@5: is.precision(1); rt300@4: rt300@5: char delim; rt300@5: int eType; rt300@0: rt300@5: is >> eType >> delim >> e.val1 >> delim >> e.val2 >> delim >> e.sliderID; rt300@5: rt300@5: e.eventType = (leventType)eType; rt300@5: rt300@5: return is; rt300@5: } rt300@4: rt300@5: //--------------------------------------------------------------------------- rt300@5: inline ostream& operator<<(ostream & os, const lEvent& e){ rt300@5: os.setf(ios_base::fixed,ios_base::floatfield); rt300@5: os.precision(1); rt300@5: rt300@5: os << e.eventType << ',' << e.val1 << ',' << e.val2 << ',' << e.sliderID << '\n'; rt300@5: rt300@5: return os; rt300@7: } rt300@5: //--------------------------------------------------------------------------- rt300@4: rt300@0: class EventLogger{ rt300@0: public: rt300@14: bool loggingEnabled; rt300@22: bool serverConnectionOK; rt300@14: unsigned int deviceID; // unique get something from hardware?? rt300@14: unsigned int totalInteractionTime, sessionTime, sessionStartTime; rt300@14: string userName; // not unique rt300@14: rt300@14: EventLogger(); rt300@14: void init(); rt300@14: void exitAndSave(); rt300@14: void setUsername(const char *u); rt300@14: void logEvent(const leventType& evtType,const TwoVector& centre = TwoVector(), const double& scale = 1.0, const int& sliderID = -1, const double& sliderVal = 0.0); rt300@22: void questionnaireAnswersObtained(vector answers); rt300@14: rt300@14: private: rt300@0: // what we need... rt300@0: /* rt300@0: time, type, value rt300@0: */ rt300@14: rt300@14: rt300@4: vector theEvents; rt300@0: rt300@16: rt300@14: // values applicable to all events rt300@14: rt300@14: unsigned int nextUploadQty; rt300@14: rt300@8: rt300@22: ofxiPhoneDeviceType iOSdeviceType; rt300@14: rt300@9: bool testConnection(); rt300@22: vector questionnaireAnswers; rt300@22: bool questionnaireCompleted; rt300@22: bool questionnaireUploaded; rt300@9: rt300@7: void checkLogFile(); rt300@22: bool uploadEventLog(); rt300@7: void firstEverAppOpen(); rt300@8: void readJsonToLog(const string &jsonFile); rt300@22: bool uploadQuestionnaire(); rt300@22: bool sendToServer(string functionName, Json::Value jsonData); rt300@8: Json::Value logsToJson(); rt300@22: Json::Value questionnaireToJson(); rt300@5: void printAll(){ rt300@5: cout << "ALL LOGGED EVENTS!: \n"; rt300@5: vector::iterator evIter; rt300@5: for(evIter = theEvents.begin(); evIter < theEvents.end(); evIter++){ rt300@5: cout << *evIter; rt300@5: rt300@5: } rt300@5: }; rt300@0: }; rt300@0: rt300@0: rt300@8: //--------------------------------------------------------------------------- rt300@8: rt300@5: rt300@0: #endif /* defined(__oscSenderExample__eventLogger__) */