Mercurial > hg > tweakathon2ios
diff eventLogger.h @ 0:a223551fdc1f
First commit - copy from tweakathlon.
author | Robert Tubb <rt300@eecs.qmul.ac.uk> |
---|---|
date | Fri, 10 Oct 2014 11:46:42 +0100 |
parents | |
children | 7e0a19a538d4 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/eventLogger.h Fri Oct 10 11:46:42 2014 +0100 @@ -0,0 +1,219 @@ +// +// 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 APP_CREATION_TIME 0 // ignore this, pointless +#define PROGRAM_NAME "TWEAKATHLON" +#define PROGRAM_VERSION 0.2 + +#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_TESTS, // 19 probably superfluous + CRAP_TEST, // eliminate these coords somehow ??? + EMPTY_EVENT, + SPEED_CHANGED, // 22 ms between sounds + +}; + +//--------------------------------------------------------------------------- + +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 int deviceID; + unsigned int totalInteractionTime, savedInteractionTime, sessionTime, sessionStartTime; + string userName; // not unique + string questionnaireComments; +// constr + EventLogger(); + +// public methods: + 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; + +// 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; + +}; + + + //--------------------------------------------------------------------------- + + +#endif /* defined(__oscSenderExample__eventLogger__) */