/*
* Copyright (C) 2011 Wolfgang Koller
*
* This file is part of GOFG Sports Computer - http://www.gofg.at/.
*
* GOFG Sports Computer is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GOFG Sports Computer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GOFG Sports Computer. If not, see <http://www.gnu.org/licenses/>.
*/
function TrackWaypoint() {
this.timestamp = null;
this.gps = {
lat : null,
lon : null,
alt : null
};
this.hr = null;
this.distance = null;
this.speed = null;
this.accuracy = null;
this.altitudeAccuracy = null;
}
TrackWaypoint.prototype.reset = function( p_resetValue ) {
if( p_resetValue == undefined ) p_resetValue = null;
this.timestamp = p_resetValue;
this.gps.lat = p_resetValue;
this.gps.lon = p_resetValue;
this.gps.alt = p_resetValue;
this.hr = p_resetValue;
this.distance = p_resetValue;
this.speed = p_resetValue;
this.accuracy = p_resetValue;
this.altitudeAccuracy = p_resetValue;
}
/**
* javascript object for handling a track (including writing to file and getting info)
*/
var TrackHandler = {
m_fileEntry : null, // Reference to the track file
m_trackDirectoryEntry : null, // Reference to the track directory
m_exportDirectoryEntry : null, // Reference to the export directory
m_totalDistance : 0, // Total distance for this track
m_lastDistance : 0, // Last distance (between last two waypoints)
m_elevationGain : 0, // Total elevation gain for this track
m_lastAltitude : -1000, // Last altitude
m_lastAltitudeDiff : 0, // Last altitude diff
m_startTimestamp : 0, // Start time for this track
m_maximumSpeed : 0, // Maximum speed
m_uuid : 0, // UUID of this track
m_bTrackOpen : false, // Indicates if the track is still open (and running) or not
m_bTrackLoading : false, // Indicates if a track is currently loaded
m_waypoint : null,
m_continuousFileWriter : null,
startTrack : function() {
if( TrackHandler.m_trackDirectoryEntry == null ) return;
// Only start a track if no track is currently loaded
if( TrackHandler.m_bTrackLoading ) return;
//console.log( "Starting-Track" );
// Reset (initialization)
TrackHandler._reset();
TrackHandler.m_bTrackOpen = true;
// Save start time
TrackHandler.m_startTimestamp = ((new Date()).getTime() / 1000).toFixed(0);
TrackHandler.m_waypoint.timestamp = TrackHandler.m_startTimestamp;
// Generate new uuid
TrackHandler.m_uuid = $.uidGen( { mode: 'random' } );
// Emit new track event
// Parameter is true if this is a load event
$.event.trigger( 'thnewtrack', [ false ] );
// Construct new file-name
var fileName = TrackHandler.m_startTimestamp + ".gsc";
// Request file reference
TrackHandler.m_trackDirectoryEntry.getFile( fileName, {create: true, exclusive: true}, TrackHandler._fileEntry, TrackHandler._fileSystemError );
},
/**
* Stop recording a new track
*/
stopTrack : function() {
TrackHandler.m_bTrackOpen = false;
// Emit end track event
// Parameter is true if this is a load event
$.event.trigger( 'thendtrack', [ false ] );
},
/**
* Load a track
* @param p_fileEntry FileEntry object for the file to load
* @param p_completeCallback Function reference which is called once the track is loaded
*/
loadTrack : function( p_fileEntry, p_completeCallback ) {
// Only load a track if no track is currently open
if( TrackHandler.m_bTrackOpen ) return;
// Reset our track status
TrackHandler._reset();
TrackHandler.m_bTrackLoading = true;
// Emit new track event
// Parameter is true if this is a load event
$.event.trigger( 'thnewtrack', [ true ] );
// Read the track
var trackReader = new TrackReader(
p_fileEntry,
TrackHandler._loadTrackWaypoint,
function( p_uuid ) {
TrackHandler.m_uuid = p_uuid;
TrackHandler.m_bTrackLoading = false;
// Emit end track event
// Parameter is true if this is a load event
$.event.trigger( 'thendtrack', [ true ] );
// Call complete callback
p_completeCallback( p_uuid );
}
);
},
/**
* Called whenever a new waypoint was loaded from a saved track
* @param p_waypoint Waypoint data
*/
_loadTrackWaypoint : function( p_waypoint ) {
if( TrackHandler.m_startTimestamp == 0 ) {
TrackHandler.m_startTimestamp = p_waypoint.timestamp;
}
TrackHandler.m_waypoint.timestamp = p_waypoint.timestamp;
TrackHandler.addAccuracy( p_waypoint.accuracy, p_waypoint.altitudeAccuracy );
TrackHandler.addDistance( p_waypoint.distance );
TrackHandler.addPosition( p_waypoint.gps.lat, p_waypoint.gps.lon, p_waypoint.gps.alt );
TrackHandler.addSpeed( p_waypoint.speed );
// Trigger new waypoint event
$.event.trigger( 'thwaypoint', [ TrackHandler.m_waypoint, true ] );
},
/**
* Set the directory for storing the tracks
* @param p_directoryEntry DirectoryEntry object for storing the track-files in
*/
setDirectory : function( p_directoryEntry ) {
TrackHandler.m_trackDirectoryEntry = p_directoryEntry;
},
/**
* Return the directory for storing the tracks
* @return DirectoryEntry Entry with tracks in it
*/
getDirectory : function() {
return TrackHandler.m_trackDirectoryEntry;
},
/**
* Set the directory for exporting the tracks
* @param p_directoryEntry DirectoryEntry object for storing the export-files in
*/
setExportDirectory : function( p_directoryEntry ) {
TrackHandler.m_exportDirectoryEntry = p_directoryEntry;
},
/**
* Return the directory for exporting the tracks
* @return DirectoryEntry Entry with export files in it
*/
getExportDirectory : function() {
return TrackHandler.m_exportDirectoryEntry;
},
// Add distance info to waypoint
addDistance : function( p_distance ) {
TrackHandler._checkWrite( TrackHandler.m_waypoint.distance != null );
TrackHandler.m_totalDistance += p_distance;
TrackHandler.m_lastDistance = p_distance;
TrackHandler.m_waypoint.distance = p_distance;
},
// Add speed info to waypoint
addSpeed : function( p_speed ) {
TrackHandler._checkWrite( TrackHandler.m_waypoint.speed != null );
TrackHandler.m_waypoint.speed = p_speed;
if( p_speed > TrackHandler.m_maximumSpeed ) TrackHandler.m_maximumSpeed = p_speed;
},
/**
* Add new position info to track
*/
addPosition : function( p_latitude, p_longitude, p_altitude ) {
TrackHandler._checkWrite( TrackHandler.m_waypoint.gps.lat != null );
if( TrackHandler.m_lastAltitude <= -1000 ) TrackHandler.m_lastAltitude = p_altitude;
// Check if altitude change was big enough
var altitudeDiff = p_altitude - TrackHandler.m_lastAltitude;
TrackHandler.m_lastAltitudeDiff = 0;
if( Math.abs(altitudeDiff) >= parseInt(SettingsHandler.get("minimumaltitudechange")) ) {
if( altitudeDiff > 0 ) {
// console.log( "Altitude-Change: " + altitudeDiff + " / " + TrackHandler.m_elevationGain );
TrackHandler.m_elevationGain += altitudeDiff;
TrackHandler.m_lastAltitudeDiff = altitudeDiff;
}
TrackHandler.m_lastAltitude = p_altitude;
}
TrackHandler.m_waypoint.gps = {
lat : p_latitude,
lon : p_longitude,
alt : p_altitude
};
},
/**
* Add accuracy information
* @param p_accuracy Accuracy of location (in m)
* @param p_altitudeAccuracy Accuracy of altitude (in m)
*/
addAccuracy : function( p_accuracy, p_altitudeAccuracy ) {
TrackHandler._checkWrite( TrackHandler.m_waypoint.accuracy != null );
TrackHandler.m_waypoint.accuracy = p_accuracy;
TrackHandler.m_waypoint.altitudeAccuracy = p_altitudeAccuracy;
},
/**
* Add a pause to the track
* @param p_start Start of pause (unixtimestamp)
* @param p_end Start of pause (unixtimestamp)
*/
addPause : function( p_start, p_end ) {
// TODO: Add pause handling
},
/**
* Returns the total distance for this track
* @return Number Total distance (in m)
*/
getTotalDistance : function() {
return TrackHandler.m_totalDistance;
},
/**
* Returns the total elevation gain for this track (in m)
*/
getElevationGain : function() {
return TrackHandler.m_elevationGain;
},
/**
* Returns the elevation rise in percent
*/
getElevationRise : function() {
return (TrackHandler.m_lastDistance > 0) ? (TrackHandler.m_lastAltitudeDiff / TrackHandler.m_lastDistance * 100) : 0;
},
/**
* Returns the average elevation rise in percent
*/
getAverageElevationRise : function() {
return (TrackHandler.m_totalDistance > 0) ? (TrackHandler.m_elevationGain / TrackHandler.m_totalDistance * 100) : 0;
},
/**
* Get duration for this track (in seconds)
*/
getDuration : function() {
if( TrackHandler.m_bTrackOpen ) {
return (((new Date()).getTime() / 1000).toFixed(0) - TrackHandler.m_startTimestamp);
}
else {
return (TrackHandler.m_waypoint.timestamp - TrackHandler.m_startTimestamp);
}
},
/**
* Get current speed
*/
getSpeed : function() {
return (TrackHandler.m_waypoint.speed + 0);
},
/**
* Returns the maximum speed for this track
*/
getMaximumSpeed : function() {
return (TrackHandler.m_maximumSpeed + 0);
},
/**
* Returns the average speed for this track
*/
getAverageSpeed : function() {
return (TrackHandler.m_totalDistance / TrackHandler.getDuration() + 0);
},
/**
* Get the current accuracy
*/
getAccuracy : function() {
return (TrackHandler.m_waypoint.accuracy + 0);
},
/**
* Get the current altitude accuracy
*/
getAltitudeAccuracy : function() {
return (TrackHandler.m_waypoint.altitudeAccuracy + 0);
},
// Generic function for writing a data-line in the correct format
_checkWrite : function( p_status ) {
// Check if we have a valid file-entry (which won't be the case during loading)
if( TrackHandler.m_fileEntry == null ) return;
// Check if status is true (which means the data-type already exists)
if( p_status ) {
// Trigger new waypoint event
$.event.trigger( 'thwaypoint', [ TrackHandler.m_waypoint, false ] );
// Write the waypoint to disk
TrackHandler._writeWayPoint();
// Reset waypoint and add new timestamp
TrackHandler.m_waypoint.reset();
TrackHandler.m_waypoint.timestamp = ((new Date()).getTime() / 1000).toFixed(0);
}
},
_writeWayPoint : function() {
TrackHandler.m_continuousFileWriter.writeLine( "01;" + TrackHandler.m_waypoint.timestamp );
if( TrackHandler.m_waypoint.gps.lat != null ) TrackHandler.m_continuousFileWriter.writeLine( "02;" + TrackHandler.m_waypoint.gps.lat + ":" + TrackHandler.m_waypoint.gps.lon + ":" + TrackHandler.m_waypoint.gps.alt );
if( TrackHandler.m_waypoint.hr != null ) TrackHandler.m_continuousFileWriter.writeLine( "03;" + TrackHandler.m_waypoint.hr );
if( TrackHandler.m_waypoint.distance != null ) TrackHandler.m_continuousFileWriter.writeLine( "04;" + TrackHandler.m_waypoint.distance );
if( TrackHandler.m_waypoint.speed != null ) TrackHandler.m_continuousFileWriter.writeLine( "05;" + TrackHandler.m_waypoint.speed );
if( TrackHandler.m_waypoint.accuracy != null ) TrackHandler.m_continuousFileWriter.writeLine( "06;" + TrackHandler.m_waypoint.accuracy + ":" + TrackHandler.m_waypoint.altitudeAccuracy );
},
_fileEntry : function( p_fileEntry ) {
TrackHandler.m_fileEntry = p_fileEntry;
TrackHandler.m_continuousFileWriter = new ContinuousFileWriter( TrackHandler.m_fileEntry );
TrackHandler.m_continuousFileWriter.writeLine( "00;" + TrackHandler.m_uuid ); // Write uuid to file
},
_fileSystemError : function( p_fileError ) {
console.log( "Error while operating on the file-system: " + p_fileError.code );
},
_reset : function() {
TrackHandler.m_fileEntry = null;
TrackHandler.m_totalDistance = 0;
TrackHandler.m_lastDistance = 0;
TrackHandler.m_elevationGain = 0;
TrackHandler.m_lastAltitude = -1000;
TrackHandler.m_lastAltitudeDiff = 0;
TrackHandler.m_startTimestamp = 0;
TrackHandler.m_maximumSpeed = 0;
TrackHandler.m_bTrackOpen = false;
TrackHandler.m_bTrackLoading = false;
TrackHandler.m_waypoint = new TrackWaypoint();
}
};