Mercurial > hg > tweakathon2ios
view eventLogger.h @ 44:d810aa9ca03a
times. cosmetic stuff
author | Robert Tubb <rt300@eecs.qmul.ac.uk> |
---|---|
date | Mon, 15 Dec 2014 17:33:41 +0000 |
parents | 4ad0d218f890 |
children | 80112c9349c4 |
line wrap: on
line source
// // eventLogger.h // oscSenderExample // // Created by Robert Tubb on 05/11/2012. // // // This class handle everything to do with loggin user actions, // uploading logs to server, and storing locally if not uploaded #ifndef __oscSenderExample__eventLogger__ #define __oscSenderExample__eventLogger__ #include "ofMain.h" #include "ofxiPhone.h" #include "2dvector.h" #include "ofxiPhoneExtras.h" #include <sys/time.h> #include <iostream> #include <string> #include <cstring> #include <map> #include "2dvector.h" #include "json.h" #import "ServerComms.h" #include "boost/bind.hpp" #include "boost/function.hpp" #include "Poco/Mutex.h" #define EVENT_THIN_FACTOR 30 #define EVENT_LOG_FILENAME "log.json" #define UPLOAD_CHUNK_SIZE 1000 #define SAVE_CHUNK_SIZE 30000 // this is "too big" and must be saved, usually run end will save #define APP_CREATION_TIME 0 // ignore this, pointless #define PROGRAM_NAME "RIFTATHON" #define PROGRAM_VERSION 0.1 #define SUPERVISED // this def will save files // can add but don't change ordering - this will invalidate logs enum leventType {APP_LOADED, // 0 INTRO_CONSENTED, // 1 APP_EXITED, // 2 HELP_PRESSED, // 3 QUESTIONNAIRE_COMPLETED, // 4 NEW_TEST, // 5 // al the set up of the new test TARGET_PARAM_SET, // 6 setting up the target sound, param id and value CANDIDATE_PARAM_SET, // 7 setting up the cand sound starting pos, subset of param id and value CANDIDATE_CHANGEABLE_IDX, // 8 list of changeable indexes CANDIDATE_MAPPING_IDS, // 9 which kind of control was mapped to which param CONTROL_LIST, // 10 list of control types TEST_TIMER_STARTED, // 11 we're off!! CANDIDATE_PARAM_ADJUSTED, // 12 interactions changing params SUBMIT_PRESSED, // 13 this is the suer saying they've found it, along with the actual answer DISTANCE_TIME_SCORE, // 14 list of the results, now we should go back to NEW_TEST COUNTDOWN_INITIATED, // 15 just in case ALL_TESTS_COMPLETED, // 16 ? TARGET_PLAYED, // 17 however this happens it might be good to know when this happens CANDIDATE_PLAYED, // 18 START_THE_SEARCH_TESTS, // 19 probably superfluous CRAP_TEST, // eliminate these coords somehow ??? EMPTY_EVENT, SPEED_CHANGED, // 22 ms between sounds SAVE_PRESET, // 23 save a preset START_THE_TRAINING_TESTS, // 24 start traning START_THE_EXP_TESTS, // 25 start explore/express START_THE_PERFORMANCE_TESTS, // 26 starting perf // new stuff for TRaining stage START_NEW_RUN, // 27 TRAINING_RESULT, // 28 NEW_STEP, // 29 NEW_TARGET, // 30 NEW_START_POS, //31 FINISH_POS, //32 FINISHED_RUN, //33 CANDIDATE_PARAM_ADJUSTED_ALL, //34 TARGET_AND_MATCH, //35 FORGOT_SEQ, //36 RUN_SKIPPED //37 }; //--------------------------------------------------------------------------- class lEvent{ public: // try and make this as compact as possible. leventType eventType; double val1; // x coord, scale if zoom double val2; // y coord, 0 if zoom int sliderID; // xtra int long long eventTime; // MILLISECONDS since ref date vector<int> eventData; // variable length data int // old sonic zoom style event lEvent(leventType eType, double v1 = 0.0, double v2 = 0.0,int sID = 0){ eventType = eType; val1 = v1; val2 = v2; sliderID = sID; double timemsd = [NSDate timeIntervalSinceReferenceDate]; // MILLISECONDS, but with fractional part ( eventTime = (unsigned long long)(timemsd*1000) - APP_CREATION_TIME; } // new tweakathlon event lEvent(leventType eType, vector<int> theData){ eventType = eType; eventData = theData; double timemsd = [NSDate timeIntervalSinceReferenceDate]; // MILLISECONDS, but with fractional part ( eventTime = (unsigned long long)(timemsd*1000) - APP_CREATION_TIME; } lEvent(const Json::Value &jevt){ // constructor takes "jsonToEvent" readfile function role eventType = (leventType)jevt["eType"].asInt(); val1 = jevt["v1"].asDouble(); val2 = jevt["v2"].asDouble(); sliderID = jevt["sID"].asInt(); eventTime = jevt["eTime"].asLargestInt(); // TODO what happens if we try to read one that isn't there? } // new tweak event to json Json::Value eventToJson(){ Json::Value jevt; jevt["eType"] = eventType; // convert vector to json array for(auto it = eventData.begin(); it < eventData.end(); it++){ jevt["eData"].append(*it); } jevt["eTime"] = eventTime; return jevt; } Json::Value eventToJsonOld(){ Json::Value jevt; jevt["eType"] = eventType; // here: should give a certain number of sig figs? jevt["v1"] = val1; jevt["v2"] = val2; jevt["sID"] = sliderID; jevt["eTime"] = eventTime; return jevt; } }; //------------------------------------------ class EventLogger{ public: Poco::Mutex _mutex; int nextUploadNumber; int nextUploadQty; bool loggingEnabled; bool logUploadInProgress; bool serverConnectionOK; bool consentGiven; bool questionnaireCompleted; bool questionnaireUploaded; unsigned long long deviceID; unsigned long long totalInteractionTime, savedInteractionTime, sessionTime, sessionStartTime; string userName; // not unique string questionnaireComments; // constr EventLogger(); // public methods: void onUsernameEntered(); void startLoadAll(); void exitAndSave(); void setUsername(const char *u); string getUsername(){ return userName; } void newUser(); void logEvent(const leventType& evtType); void logEvent(const leventType& evtType, const vector<int> eventData); void questionnaireAnswersObtained(vector<int> answers, const char* userComments); void urlResponse(ofHttpResponse & response); void questionnaireOK(); void eventlogOK(); void testConnectionOK(); void questionnaireNotOK(); void eventlogNotOK(); void testConnectionNotOK(); void printAll(); void saveSessionToFile(); private: void thinnedSliderEvent(lEvent newEvent); vector<lEvent> theEvents; // all logged but not uploaded events vector<int> questionnaireAnswers; string nextLogFileIndexString(); void loadUserDetailsFromLastLogFile(int numExistingLogs); // private methods void testConnection(); void checkLogFile(); void deleteLogs(); // new user bool uploadEventLog(bool async); void firstEverAppOpen(); void loadExistingLogFile(const string &jsonFile); void uploadQuestionnaire(); bool sendToServer(string functionName, Json::Value jsonData, bool async); Json::Value logsToJson(); Json::Value questionnaireToJson(); template<class T> bool matchID(T thing); bool matchID2(); // ServerComms *serverComms; int nextLogFileIndex; }; //--------------------------------------------------------------------------- #endif /* defined(__oscSenderExample__eventLogger__) */