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