view eventLogger.mm @ 15:e45c3e631d20

View fiddling
author Robert Tubb <rt300@eecs.qmul.ac.uk>
date Thu, 17 Jan 2013 13:01:19 +0000
parents 6a9191f5b269
children fb2ef16dd013
line wrap: on
line source
//
//  eventLogger.mm
//  oscSenderExample
//
//  Created by Robert Tubb on 05/11/2012.
//
//

//---------------------------------------------------------------------------
#include "eventLogger.h"


EventLogger eventLogger;
extern IViewController *iViewController;

//---------------------------------------------------------------------------
EventLogger::EventLogger(){
    //QuestionnaireViewController * questionnaireViewController;
 
    questionnaireViewController	= [[QuestionnaireViewController alloc] initWithNibName:@"QuestionnaireViewController" bundle:nil];
    
	

    
    loggingEnabled = true;
    internetConnectionOK = false;
    nextUploadQty = 5000; // amount of data uploaded is always more than 5000 events
}
//---------------------------------------------------------------------------
void EventLogger::init(){
    
    readJsonToLog(ofxiPhoneGetDocumentsDirectory() + EVENT_LOG_FILENAME);
    sessionStartTime = ofGetSystemTime();
    
    testConnection();

    [ofxiPhoneGetGLParentView() addSubview:questionnaireViewController.view];
}
//---------------------------------------------------------------------------
bool EventLogger::testConnection(){
    string url = "http://127.0.0.1:8080/testservice/testConnection?testtext={%22test%22=%22sometext%22}";
    bool success = false;
    ofURLFileLoader fileLoader;
    ofHttpResponse resp;
    resp = fileLoader.get(url);
    
    cout << "HTTP STATUS  " << resp.status << "\n";
    cout << "HTTP ERROR  " << resp.error << "\n";
    cout << "HTTP DATA  " << resp.data << "\n";
    
    if (resp.status == 0){
        success = true;
        internetConnectionOK = true;
    }else{
        success = false;
        internetConnectionOK = false;
        // SHOW AN ALERT TO USER?
    }
    return success;
}
//---------------------------------------------------------------------------
void EventLogger::readJsonToLog(const string &jsonFile){
    Json::Value root;
    Json::Reader reader;
    
    
    ifstream theFile(jsonFile.c_str());
    stringstream fileText;
    string line;
    if(!theFile){
        cout<<"no event log file - first APP open\n";
        
        firstEverAppOpen();
        
        return;
    }else{
        
        while(theFile){
            theFile >> line;
            // cout << line;  // lots!!!!
            fileText << line;
            
        }
        
        theFile.close();
    }
    
    cout << "size of log JSON string:" << fileText.str().length() << "BYTES \n";
    
    bool parsingSuccessful = reader.parse( fileText.str(), root );
    
    if ( !parsingSuccessful )
    {
        // report to the user the failure and their locations in the document.
        std::cout  << "Failed to parse preset JSON\n"
        << reader.getFormattedErrorMessages();
        return;
    }
    
    // now put user deets into variables
    userName = root["userName"].asString();
    deviceID = root["deviceID"].asLargestInt();
    totalInteractionTime = root["totalInteractionTime"].asLargestInt();
    
    // check for unuploaded evts
    const Json::Value jlogs = root["events"];
    
    for ( int index = 0; index < jlogs.size(); ++index ) theEvents.push_back(lEvent(jlogs[index]));
    if(theEvents.size() > nextUploadQty){
        //try to upload
        attemptUpload();
    }
    // TODO if the total interaction time is greater than a certain amount && no questions answered - questionnaire time!
    cout << "Total interaction time: " << totalInteractionTime << '\n';
    
    if(totalInteractionTime > 0){
        // questionnaireViewController.show;
        [questionnaireViewController show:(id)this];
        
        //IF THE VIEW IS HIDDEN LETS BRING IT BACK!
        if( questionnaireViewController.view.hidden ){
            questionnaireViewController.view.hidden = NO;
        }
        
    }
    // is there logged stuff that hasn't been uploaded yet?
    
    // don't actually need to load old ones unless uploading? or saving...
    //while(eventLogFile >> nextLine){
    
    //}

    
}


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

bool EventLogger::attemptUpload(){
    
    // do simple check of internet connection ?
    // if not connected return
    if(!internetConnectionOK){
        return false;
    }
    // show indicator
    cout << "UPLOADING: " << theEvents.size() << " logs.\n";
    
    // if numlogs > 500000 show alert...?
    
    string url = "http://127.0.0.1:8080/testservice/eventlog?jsontext=";
    url.append(logsToJson().toStyledString());
    
    
    ofURLFileLoader fileLoader;
    ofHttpResponse resp;
    resp = fileLoader.get(url); // Does this sit and wait and arse up interaction?
    
    cout << "HTTP STATUS  " << resp.status << "\n";
    cout << "HTTP ERROR  " << resp.error << "\n";
    cout << "HTTP DATA  " << resp.data << "\n";
    
    bool uploaded = false;
    if (resp.status == 0) uploaded = true; // should do a check on server, and report in data ?
    if(!uploaded){
        // try later
        nextUploadQty += 5000;
    }else{
        
        // if success - clear memory
        theEvents.clear();
    }
    return uploaded;
    
}

//----------------------------------------------------------------------------
//void EventLogger::deleteLogFile(){

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

void EventLogger::firstEverAppOpen(){
    deviceID = ofGetSystemTimeMicros();
    totalInteractionTime = 0;
    
    [iViewController showUserNamePrompt];
    // then we get userName via setUsername, called from button delegate
    
}
//---------------------------------------------------------------------------
// called from alertView OK in iViewController
void EventLogger::setUsername(const char *u){
    userName = u;

}

//---------------------------------------------------------------------------
// log zoom event
void EventLogger::logEvent(const leventType& evtType,const TwoVector& centre, const double& scale, const int& sliderID, const double& sliderVal){
    //cout << "log: " << evtType << "\n";
    
    // scroll has 2 double coords
    // zoom has 1 double scale
    // save preset has 2 coords
    // switch view has view type
    // slider change has int slider index and 1 float value
    
    // get time for key index
    
    // thinFactor
    if(!loggingEnabled) return;
    switch ( evtType ) {
        case SAVE_PRESET:
            theEvents.push_back(lEvent(evtType,centre.x,centre.y));
            // Code
            break;
        case SAVE_DESET:
            theEvents.push_back(lEvent(evtType,centre.x,centre.y));
            break;
        case SCROLL:
            theEvents.push_back(lEvent(evtType,centre.x,centre.y));
            break;
        case SCROLL_STOPPED:
            theEvents.push_back(lEvent(evtType,centre.x,centre.y));
            break;
        case ZOOM:
            theEvents.push_back(lEvent(evtType,scale));
            break;
        case CHANGE_SLIDER:
            theEvents.push_back(lEvent(evtType,sliderVal , 0.0 , sliderID));
            break;
        default:
            // Code
            break;
    }
    if(theEvents.size() > nextUploadQty){
        //try to upload
        attemptUpload();
    }
    //sessionTime = (ofGetSystemTime() - sessionStartTime);
    
    
}

//---------------------------------------------------------------------------
void EventLogger::sendHttp(){
    
    string url = "http://www.rootnot.co.uk/cgi-bin/zoomlogs.cgi";
    ofURLFileLoader fileLoader;
    ofHttpResponse resp;
    resp = fileLoader.get(url);
    cout << "HTTP STATUS  " << resp.status << "\n";
    cout << "HTTP ERROR  " << resp.error << "\n";
    cout << "HTTP DATA  " << resp.data << "\n";
}



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

void EventLogger::exitAndSave(){
    totalInteractionTime = totalInteractionTime + (ofGetSystemTime() - sessionStartTime);
    // save user details
    string fname = ofxiPhoneGetDocumentsDirectory() + EVENT_LOG_FILENAME;

    Json::Value jlogs = logsToJson();
    // try to upload
    bool uploaded = attemptUpload();
    
    // write to file
    
    ofFile logFile(fname,ofFile::WriteOnly);
    logFile << jlogs;
    
}
//---------------------------------------------------------------------------

Json::Value EventLogger::logsToJson(){
    // put all logged events into Json formatted string
    Json::Value root;

    vector<lEvent>::iterator eventIter;
    
    root["userName"] = userName;
    root["deviceID"] = deviceID;
    root["totalInteractionTime"] = totalInteractionTime;
    
    int i = 0;
    for(eventIter = theEvents.begin(); eventIter < theEvents.end(); eventIter++){
        root["events"][i] = (*eventIter).eventToJson();
        i++;
    }
    
    return root;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------