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__) */