You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
260 lines
9.4 KiB
JavaScript
260 lines
9.4 KiB
JavaScript
/*
|
|
* TerranQuest - Augmented Reality fantasy game
|
|
*
|
|
* Copyright 2016 Netsyms Technologies
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
|
|
//////////////////////////////////////////////
|
|
// GPS and map stuff
|
|
//////////////////////////////////////////////
|
|
|
|
/**
|
|
* Handles GPS and map data.
|
|
*/
|
|
|
|
// Globals
|
|
var lockGot = false;
|
|
var latitude = 0.0000;
|
|
var longitude = 0.0000;
|
|
var gpsaccuracy = 9999;
|
|
var requiredaccuracy = 40;
|
|
// End Globals
|
|
|
|
var fetchplacecounter = 0;
|
|
var lastgpstime = 0;
|
|
var map = L.map('map');
|
|
var tileurl = "http://tile.stamen.com/terrain/{z}/{x}/{y}.jpg";
|
|
map.setZoom(17);
|
|
map.dragging.disable();
|
|
//map.touchZoom.disable();
|
|
//map.doubleClickZoom.disable();
|
|
//map.scrollWheelZoom.disable();
|
|
map.keyboard.disable();
|
|
$(".leaflet-control-zoom").css("visibility", "hidden");
|
|
// Disable tap handler, if present.
|
|
//if (map.tap) {
|
|
// map.tap.disable();
|
|
//}
|
|
|
|
// Tile layer
|
|
map.addLayer(new L.tileLayer(tileurl, {minZoom: 16, maxZoom: 18}));
|
|
// Places layer
|
|
var placeLayer = L.geoJson(
|
|
{"name": "Places", "type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "Point", "coordinates": [0, 0]}, "properties": {"osm_id": -1, "name": null, 'gameinfo': {'teamid': "0"}}}]},
|
|
{
|
|
onEachFeature: onPlaceTap,
|
|
pointToLayer: function (feature, latlng) {
|
|
var teamcolor = "#" + getTeamColorFromId(feature.properties.gameinfo.teamid);
|
|
return L.circleMarker(latlng, {
|
|
radius: 14,
|
|
fillColor: teamcolor,
|
|
color: "#000",
|
|
weight: 1,
|
|
opacity: 1,
|
|
fillOpacity: 0.6
|
|
});
|
|
}
|
|
});//.addTo(map);
|
|
|
|
var placemarkers = L.markerClusterGroup({
|
|
spiderfyDistanceMultiplier: 2,
|
|
spiderfyOnMaxZoom: false,
|
|
showCoverageOnHover: false,
|
|
zoomToBoundsOnClick: false,
|
|
maxClusterRadius: 30
|
|
});
|
|
placemarkers.on('clusterclick', function (a) {
|
|
a.layer.spiderfy();
|
|
});
|
|
placemarkers.addLayer(placeLayer);
|
|
map.addLayer(placemarkers);
|
|
|
|
var lc = L.control.locate({
|
|
position: 'topleft', // set the location of the control
|
|
layer: undefined, // use your own layer for the location marker, creates a new layer by default
|
|
drawCircle: false, // controls whether a circle is drawn that shows the uncertainty about the location
|
|
setView: 'always',
|
|
keepCurrentZoomLevel: true, // keep the current map zoom level when displaying the user's location. (if `false`, use maxZoom)
|
|
remainActive: {inView: 'setView', outOfView: 'setView'},
|
|
markerClass: L.circleMarker, // L.circleMarker or L.marker
|
|
circleStyle: {}, // change the style of the circle around the user's location
|
|
markerStyle: {color: '#008000', fillColor: '#32CD32'},
|
|
followCircleStyle: {}, // set difference for the style of the circle around the user's location while following
|
|
followMarkerStyle: {},
|
|
icon: 'fa fa-map-marker', // class for icon, fa-location-arrow or fa-map-marker
|
|
iconLoading: 'fa fa-spinner fa-pulse', // class for loading icon
|
|
iconElementTag: 'span', // tag for the icon element, span or i
|
|
circlePadding: [0, 0], // padding around accuracy circle, value is passed to setBounds
|
|
metric: true, // use metric or imperial units
|
|
onLocationError: function (err) {
|
|
}, // define an error callback function
|
|
onLocationOutsideMapBounds: function (context) { // called when outside map boundaries
|
|
},
|
|
showPopup: false, // display a popup when the user click on the inner marker
|
|
strings: {
|
|
title: ".", // title of the locate control
|
|
metersUnit: "meters", // string for metric units
|
|
feetUnit: "feet", // string for imperial units
|
|
popup: "You are within {distance} {unit} from this point", // text to appear if user clicks on circle
|
|
outsideMapBoundsMsg: "You seem located outside the boundaries of the map" // default message for onLocationOutsideMapBounds
|
|
},
|
|
locateOptions: {} // define location options e.g enableHighAccuracy: true or maxZoom: 10
|
|
}).addTo(map);
|
|
lc.start();
|
|
|
|
|
|
function mapPos(lat, lon) {
|
|
lockGot = true;
|
|
hideLoading();
|
|
// Don't update places every time
|
|
if (fetchplacecounter === 0) {
|
|
loadPlaces(latitude, longitude);
|
|
}
|
|
fetchplacecounter++;
|
|
if (fetchplacecounter > 10) {
|
|
fetchplacecounter = 0;
|
|
}
|
|
}
|
|
|
|
function onPlaceTap(feature, layer) {
|
|
layer.on('click', function (e) {
|
|
openPlace(feature);
|
|
});
|
|
}
|
|
|
|
function loadPlaces(lat, long) {
|
|
if (!lockGot) {
|
|
return;
|
|
}
|
|
var url = mkApiUrl('places', 'gs') + "?lat=" + lat + "&long=" + long + "&radius=.5&names=1&lang=" + USER_LANGUAGE;
|
|
try {
|
|
$.getJSON(
|
|
url,
|
|
function (data) {
|
|
if (data.type === 'FeatureCollection') {
|
|
placeLayer.clearLayers();
|
|
placemarkers.clearLayers();
|
|
data.features.forEach(function (item) {
|
|
item.properties.popupContent = "<span class='marker-popup-text' onclick='openPlace(" + item.properties.osm_id + ")'>" + item.properties.name + "</span>";
|
|
placeLayer.addData(item);
|
|
});
|
|
placemarkers.addLayer(placeLayer);
|
|
}
|
|
}
|
|
);
|
|
} catch (ex) {
|
|
serverProblemsDialog();
|
|
}
|
|
}
|
|
|
|
function openPlace(feature) {
|
|
$('#main-content').load("screens/place.html", null, function () {
|
|
loadPlace(feature);
|
|
$('#overlay-main').css('display', 'block');
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Hide the loading overlay if everything is loaded, otherwise do nothing
|
|
*/
|
|
function hideLoading() {
|
|
if (lockGot && gpsaccuracy < requiredaccuracy && $('#loading').css('display') !== 'none') {
|
|
getWeather();
|
|
getTerrain();
|
|
$('#loading').fadeOut('slow', function () {
|
|
$('#loading').css('display', 'none');
|
|
updateStatusBarColor();
|
|
});
|
|
}
|
|
}
|
|
|
|
var updatePosition = function (position) {
|
|
latitude = position.coords.latitude;
|
|
longitude = position.coords.longitude;
|
|
lastgpstime = position.timestamp;
|
|
gpsaccuracy = position.coords.accuracy;
|
|
if (gpsaccuracy > requiredaccuracy) {
|
|
$('#no-lock').css('display', 'block');
|
|
} else {
|
|
$('#no-lock').css('display', 'none');
|
|
}
|
|
mapPos(latitude, longitude);
|
|
};
|
|
|
|
function pingServer() {
|
|
if (lockGot && gpsaccuracy < requiredaccuracy) {
|
|
$.getJSON(mkApiUrl('ping') + "?user=" + username + "&lat=" + latitude + "&long=" + longitude + "&lang=" + USER_LANGUAGE, function (data) {
|
|
if (data.status == "ERROR") {
|
|
localStorage.setItem("no_autologin", "true");
|
|
username = null;
|
|
password = null;
|
|
document.location.href = "index.html";
|
|
navigator.notification.alert("Your session status has changed, and you have been logged out. \n\nReason: " + data.message, null, "Sign-in Status Changed", "OK");
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
var errorMsgShown = false;
|
|
var fifteen_seconds = false;
|
|
function onError(error) {
|
|
if (!errorMsgShown) {
|
|
var msg = error.message;
|
|
if (msg.toLowerCase().includes("timeout") && fifteen_seconds == false) {
|
|
return;
|
|
} else if (msg.toLowerCase().includes("timeout")) {
|
|
msg = "no lock within 15 seconds";
|
|
$('#loading-error').text("Check your device's network and location settings, and ensure a clear view of the sky (" + msg + ").");
|
|
} else {
|
|
$('#loading-error').text("Check your device's network and location settings, and ensure a clear view of the sky (" + msg + ").");
|
|
}
|
|
errorMsgShown = true;
|
|
}
|
|
}
|
|
|
|
function popDiagData() {
|
|
navigator.notification.alert("Latitude: " + latitude +
|
|
"\nLongitude: " + longitude +
|
|
"\nAccuracy: " + gpsaccuracy +
|
|
"\nWeather: " + rawWeatherData.temperature + " F, " + rawWeatherData.summary + ", " + rawWeatherData.windSpeed + " mph" +
|
|
"\nTerrain: " + terrainName + " (" + terrainType + ")",
|
|
null,
|
|
"World Info",
|
|
"Close");
|
|
}
|
|
// Initial GPS position and stuff
|
|
navigator.geolocation.getCurrentPosition(updatePosition, onError, {timeout: 15000, enableHighAccuracy: true});
|
|
// Update position
|
|
setInterval(function () {
|
|
navigator.geolocation.getCurrentPosition(updatePosition, onError, {timeout: 1000, enableHighAccuracy: true});
|
|
}, 1000);
|
|
setTimeout(function () {
|
|
fifteen_seconds = true;
|
|
}, 15 * 1000);
|
|
// Update places
|
|
setInterval(function () {
|
|
loadPlaces(latitude, longitude);
|
|
}, 1000 * 15);
|
|
// Ping the server with coordinates
|
|
setInterval(pingServer, 5000);
|
|
// Show error if it's taking too long
|
|
setTimeout(function () {
|
|
onError();
|
|
}, 15 * 1000);
|
|
|
|
setTimeout(function () {
|
|
$('#loading-error').text("If you're outside and the settings are OK, something has gone wrong. Try restarting or reinstalling the app.");
|
|
}, 45 * 1000); |