Last active
August 29, 2015 14:04
-
-
Save tkh44/4bd07918f48514c94a36 to your computer and use it in GitHub Desktop.
location caching and distance checking
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
((angular, window) => { | |
/** | |
* GeoLocation Utility Service | |
* @param $localStorage | |
* @param $cordovaGeolocation | |
* @param $q | |
* @returns {{getCachedGeoLocation: getCachedGeoLocation, getDistance: getDistance}} | |
* @constructor | |
*/ | |
var GeoService = function($localStorage, $cordovaGeolocation, $q) { | |
var $storage = $localStorage, | |
cachedLocation = $storage.currentLocation, | |
isUS = navigator.language.match(/us/ig); | |
// Was the last lookup more than 5 min ago and did it contain an error. | |
var isLocationExpired = () => | |
angular.isUndefined(cachedLocation) // Is there a cachedLocation object | |
|| !cachedLocation.error // Error from device | |
|| cachedLocation.timestamp - Date.now() > 3E5; // Older than 300000ms(5 min) | |
/** | |
* Return the distance in miles if `navigator.language` is 'en-US' otherwise | |
* returns distance in kilometers | |
* | |
* @param {number} distance | |
* @returns {string} distance in either miles or km | |
*/ | |
var getLocaleDistance = (distance) => | |
isUS ? (distance / 1.609344).toFixed(1) + ' mi' : distance.toFixed(1) + ' km'; | |
/** | |
* Calculates the distance between two latitude-longitude points | |
* | |
* Taken from {@link http://stackoverflow.com/a/7179026} | |
* @param {number} lat1 | |
* @param {number} lon1 | |
* @param {number} lat2 | |
* @param {number} lon2 | |
* @returns {number} | |
*/ | |
var computeDistanceBetween = (lat1, lon1, lat2, lon2) => { | |
var toRad = (val) => val * Math.PI / 180; | |
var R = 6371 | 0, // Radius of the earth 6371 km | |
dLat = toRad(lat2 - lat1), | |
dLon = toRad(lon2 - lon1); | |
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2); | |
var c = 2 * Math.atan(Math.sqrt(a), Math.sqrt(1 - a)); | |
return R * c; | |
}; | |
/** | |
* Storage for deferred variable. | |
* | |
* @type {null} | |
*/ | |
var deferred = null; | |
/** | |
* Get the user's last known location. | |
* Checks cache(localStorage) before making call to device. | |
* | |
* @returns {external:Promise} | |
*/ | |
this.getCachedGeoLocation = function() { | |
if (_.isNull(deferred)) { | |
deferred = $q.defer(); | |
// Pull from cache | |
if (!isLocationExpired()) { | |
return $q.when(cachedLocation); | |
// Pull from device | |
} else { | |
$cordovaGeolocation.getCurrentPosition().then((position) => { | |
var currentPosition = { | |
latitude: position.coords.latitude, | |
longitude: position.coords.longitude, | |
accuracy: position.coords.accuracy , | |
timestamp: +position.timestamp | |
}; | |
$storage.currentLocation = currentPosition; | |
deferred.resolve(currentPosition); | |
}, (err) => { | |
cachedLocation['error'] = err; | |
deferred.reject(err) | |
}).finally(() => { | |
deferred = null; | |
}); | |
} | |
} | |
return deferred.promise; | |
}; | |
/** | |
* Get the distance of the building from the cached geolocation of user | |
* | |
* @param {number} latitude | |
* @param {number} longitude | |
* @returns {string} prettyDistance | |
*/ | |
this.getDistance = function(latitude, longitude) { | |
return getLocaleDistance(computeDistanceBetween(cachedLocation.latitude, cachedLocation.longitude, latitude, longitude)); | |
} | |
}; | |
angular.module('iOffice.geo', ['ngCordova']).service('GeoService', GeoService); | |
})(angular, window); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment