view eventLogger.h @ 49:178642d134a7 tip

xtra files
author Robert Tubb <rt300@eecs.qmul.ac.uk>
date Wed, 01 May 2013 17:34:33 +0100
parents 0d3a993405e4
children
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"
#include "testApp.h"
#include "presetManager.h"
#import "ServerComms.h"
#include "grid.h"

#define EVENT_THIN_FACTOR 12
#define EVENT_LOG_FILENAME "log.json"
#define UPLOAD_CHUNK_SIZE 1000
#define APP_CREATION_TIME 381429000000   // milliseconds to the time i wrote this wee blighter. saves digits
#define SCROLL_TRAIL_LENGTH 200
#define PROGRAM_VERSION 1.0 // NOW USES NEW HILBERT CURVE. ALL OLD PRESETS WILL BE INVALID :(

#define SUPERVISED // this def will save files


// can add but don't change ordering - this will invalidate logs
enum leventType {SAVE_PRESET,  // 0
    SAVE_DESET,           // 1
    SCROLL,               // 2
    ZOOM,                 // 3
    SCROLL_STOPPED,        // 4
    ZOOM_STOPPED,           // 5
    SNAPPED_TO_PRESET,      // 6
    CHANGE_SLIDER,          // 7
    SWAP_VIEW,              // 8
    SET_MIN_ZOOM,           // 9
    SET_MAX_ZOOM,           // 10
    RANDOMISE,             // 11
    APP_STARTED,            // 12
    APP_EXITED,             // 13
    CONSENT_DENIED,         // 14
    SEQ_LOCKED,             // 15
    SYNTH_LOCKED,           // 16
    PLAY_PRESSED,           // 17
    PAUSE_PRESSED,         // 18
    HELP_PRESSED,            // 19
    QUESTIONNAIRE_COMPLETED,  // 20
    EVALUATION_POINT,       // 21
    EMPTY_EVENT,            // 22
    SMOOTHING_ON,           // 23
    SMOOTHING_OFF,          // 24
    SNAPPED_TO_EVALPT,       // 25
    PRESET_DOUBLE_TAPPED};

//---------------------------------------------------------------------------

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 app creation
    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
        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?
        
    }
    Json::Value eventToJson(){
        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;
    }
    void draw();
};
//---------------------------------------------------------------------------
// streams no longer used
inline istream& operator>>(istream & is, lEvent& e){
    is.setf(ios_base::fixed,ios_base::floatfield);
    is.precision(1);
    
    char delim;
    int eType;

    is >> eType >> delim >> e.val1 >> delim >> e.val2 >> delim >> e.sliderID;
    
    e.eventType = (leventType)eType;
    
    return is;
}

//---------------------------------------------------------------------------
inline ostream& operator<<(ostream & os, const lEvent& e){
    os.setf(ios_base::fixed,ios_base::floatfield);
    os.precision(1);
    
    os << e.eventType << ',' << e.val1 << ',' << e.val2 << ',' << e.sliderID << '\n';
    
    return os;
}
 //---------------------------------------------------------------------------   
 
    
class EventLogger{
public:
    int nextUploadNumber;
    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

// constr
    EventLogger();
    
// public methods:
    void startLoadAll();
    void exitAndSave();
    void setUsername(const char *u);
    void newUser();
    void logEvent(const leventType& evtType,const TwoVector& centre = TwoVector(), const double& scale = 1.0, const int& sliderID = -1, const double& sliderVal = 0.0);
    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();
    void drawTrail(const TwoVector min, const TwoVector max);
    vector<lEvent> getDrawableEventsInRange(const TwoVector min, const TwoVector max);
    vector<lEvent *> getEvaluationPointsInRange(const TwoVector min, const TwoVector max);
    vector<TwoVector> getRecentPath(int numEvents);
    
    void clearTrail();
private:
  
    vector<lEvent> theEvents; // all logged but not uploaded events
    deque<lEvent> eventsToDraw; // 200 or so drawable events, maybe uploaded maybe not

    void thinnedSliderEvent(lEvent nextEvent);
    void thinnedZoomEvent(lEvent nextEvent);
    void thinnedSnapEvent(lEvent nextEvent);
    void thinnedScrollEvent(lEvent nextEvent);
    unsigned int nextUploadQty;

    string questionnaireComments;
    
    ofxiPhoneDeviceType iOSdeviceType;
    

    vector<int> questionnaireAnswers;
    int interfaceOrder;

// 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();

    
    //
    ServerComms *serverComms;
    
};

    lEvent * e;
    
    //---------------------------------------------------------------------------
   

#endif /* defined(__oscSenderExample__eventLogger__) */