merged
This commit is contained in:
14
code/chat.js
14
code/chat.js
@ -540,7 +540,6 @@ window.chat.show = function(name) {
|
||||
? $('#updatestatus').hide()
|
||||
: $('#updatestatus').show();
|
||||
$('#chat, #chatinput').show();
|
||||
$('#map').css('visibility', 'hidden');
|
||||
|
||||
var t = $('<a>'+name+'</a>');
|
||||
window.chat.chooseAnchor(t);
|
||||
@ -681,7 +680,18 @@ window.chat.postMsg = function() {
|
||||
var msg = $.trim($('#chatinput input').val());
|
||||
if(!msg || msg === '') return;
|
||||
|
||||
if(c === 'debug') return new Function (msg)();
|
||||
if(c === 'debug') {
|
||||
var result;
|
||||
try {
|
||||
result = eval(msg);
|
||||
} catch(e) {
|
||||
if(e.stack) console.error(e.stack);
|
||||
throw e; // to trigger native error message
|
||||
}
|
||||
if(result !== undefined)
|
||||
console.log(result.toString());
|
||||
return result;
|
||||
}
|
||||
|
||||
var publik = c === 'public';
|
||||
var latlng = map.getCenter();
|
||||
|
@ -23,10 +23,6 @@ window.debug.console = function() {
|
||||
}
|
||||
|
||||
window.debug.console.show = function() {
|
||||
if (window.isSmartphone()) {
|
||||
$('#scrollwrapper, #updatestatus').hide();
|
||||
$('#map').css('visibility', 'hidden');
|
||||
}
|
||||
$('#chat, #chatinput').show();
|
||||
window.debug.console.create();
|
||||
$('#chatinput mark').css('cssText', 'color: #bbb !important').text('debug:');
|
||||
@ -88,10 +84,20 @@ window.debug.console.error = function(text) {
|
||||
|
||||
window.debug.console.overwriteNative = function() {
|
||||
window.debug.console.create();
|
||||
window.console = function() {}
|
||||
window.console.log = window.debug.console.log;
|
||||
window.console.warn = window.debug.console.warn;
|
||||
window.console.error = window.debug.console.error;
|
||||
|
||||
var nativeConsole = window.console;
|
||||
window.console = {};
|
||||
|
||||
function overwrite(which) {
|
||||
window.console[which] = function() {
|
||||
nativeConsole[which].apply(nativeConsole, arguments);
|
||||
window.debug.console[which].apply(window.debug.console, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
overwrite("log");
|
||||
overwrite("warn");
|
||||
overwrite("error");
|
||||
}
|
||||
|
||||
window.debug.console.overwriteNativeIfRequired = function() {
|
||||
|
@ -14,6 +14,7 @@ window.setupGeosearch = function() {
|
||||
$('#geosearchwrapper img').click(function(){
|
||||
map.locate({setView : true, maxZoom: 13});
|
||||
});
|
||||
$('#geosearch').keyup(function(){$(this).removeClass('search_not_found')});
|
||||
}
|
||||
|
||||
window.search = function(search) {
|
||||
@ -22,13 +23,16 @@ window.search = function(search) {
|
||||
}
|
||||
|
||||
$.getJSON(NOMINATIM + encodeURIComponent(search), function(data) {
|
||||
if(!data || !data[0]) return true;
|
||||
if(!data || !data[0]) {
|
||||
$('#geosearch').addClass('search_not_found');
|
||||
return true;
|
||||
}
|
||||
var b = data[0].boundingbox;
|
||||
if(!b) return true;
|
||||
var southWest = new L.LatLng(b[0], b[2]),
|
||||
northEast = new L.LatLng(b[1], b[3]),
|
||||
bounds = new L.LatLngBounds(southWest, northEast);
|
||||
window.map.fitBounds(bounds);
|
||||
if(window.isSmartphone()) window.smartphone.mapButton.click();
|
||||
if(window.isSmartphone()) window.show('map');
|
||||
});
|
||||
}
|
||||
|
@ -15,6 +15,9 @@
|
||||
// required to successfully boot the plugin.
|
||||
//
|
||||
// Here’s more specific information about each event:
|
||||
// playerNameResolved: called when unresolved player name get resolved.
|
||||
// Argument is {names: object} which names[guid] is the
|
||||
// resolved player name.
|
||||
// portalSelected: called when portal on map is selected/unselected.
|
||||
// Provide guid of selected and unselected portal.
|
||||
// mapDataRefreshStart: called when we start refreshing map data
|
||||
@ -49,7 +52,7 @@
|
||||
|
||||
window._hooks = {}
|
||||
window.VALID_HOOKS = [
|
||||
'portalSelected',
|
||||
'playerNameResolved', 'portalSelected',
|
||||
'mapDataRefreshStart', 'mapDataRefreshEnd',
|
||||
'portalAdded', 'linkAdded', 'fieldAdded',
|
||||
'portalDetailsUpdated',
|
||||
|
@ -2,8 +2,16 @@
|
||||
// cache for map data tiles.
|
||||
|
||||
window.DataCache = function() {
|
||||
this.REQUEST_CACHE_FRESH_AGE = 60; // if younger than this, use data in the cache rather than fetching from the server
|
||||
this.REQUEST_CACHE_MAX_AGE = 180; // maximum cache age. entries are deleted from the cache after this time
|
||||
// stock site nemesis.dashboard.DataManager.CACHE_EXPIRY_MS_ = 18E4 - so should be 2 mins cache time
|
||||
this.REQUEST_CACHE_FRESH_AGE = 120; // if younger than this, use data in the cache rather than fetching from the server
|
||||
|
||||
// stale cache entries can be updated (that's what the optional 'timestampMs' field in getThinnedEntnties is
|
||||
// for, retrieving deltas) so use a long max age to take advantage of this
|
||||
// however, ther must be an overall limit on the maximum age of data from the servers, otherwise the deletedEntity
|
||||
// entries would grow indefinitely. an hour seems reasonable from experience with the data, so 55 mins max cache time
|
||||
// this.REQUEST_CACHE_MAX_AGE = 55*60; // maximum cache age. entries are deleted from the cache after this time
|
||||
//UPDATE: this timestampMs parameter doesn't work, so reduced max age to limit RAM usage
|
||||
this.REQUEST_CACHE_MAX_AGE = 15*60; // maximum cache age. entries are deleted from the cache after this time
|
||||
|
||||
if (L.Browser.mobile) {
|
||||
// on mobile devices, smaller cache size
|
||||
@ -18,15 +26,19 @@ window.DataCache = function() {
|
||||
|
||||
}
|
||||
|
||||
window.DataCache.prototype.store = function(qk,data,date) {
|
||||
window.DataCache.prototype.store = function(qk,data,freshTime) {
|
||||
// fixme? common behaviour for objects is that properties are kept in the order they're added
|
||||
// this is handy, as it allows easy retrieval of the oldest entries for expiring
|
||||
// however, this is not guaranteed by the standards, but all our supported browsers work this way
|
||||
|
||||
delete this._cache[qk];
|
||||
|
||||
if (date === undefined) date = new Date();
|
||||
this._cache[qk] = { time: date.getTime(), data: data };
|
||||
var time = new Date().getTime();
|
||||
|
||||
if (freshTime===undefined) freshTime = this.REQUEST_CACHE_FRESH_AGE*1000;
|
||||
var expire = time + freshTime;
|
||||
|
||||
this._cache[qk] = { time: time, expire: expire, data: data };
|
||||
}
|
||||
|
||||
window.DataCache.prototype.get = function(qk) {
|
||||
@ -42,8 +54,8 @@ window.DataCache.prototype.getTime = function(qk) {
|
||||
window.DataCache.prototype.isFresh = function(qk) {
|
||||
if (qk in this._cache) {
|
||||
var d = new Date();
|
||||
var t = d.getTime() - this.REQUEST_CACHE_FRESH_AGE*1000;
|
||||
if (this._cache[qk].time >= t) return true;
|
||||
var t = d.getTime();
|
||||
if (this._cache[qk].expire >= t) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
|
@ -9,26 +9,33 @@
|
||||
// Convertion functions courtesy of
|
||||
// http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
|
||||
|
||||
window.lngToTile = function(lng, zoom) {
|
||||
return Math.floor((lng + 180) / 360 * Math.pow(2, (zoom>12)?zoom:(zoom+2)));
|
||||
|
||||
window.levelToTilesPerEdge = function(level) {
|
||||
var LEVEL_TO_TILES_PER_EDGE = [65536, 65536, 16384, 16384, 4096, 1536, 1024, 256, 32];
|
||||
return LEVEL_TO_TILES_PER_EDGE[level];
|
||||
}
|
||||
|
||||
window.latToTile = function(lat, zoom) {
|
||||
|
||||
window.lngToTile = function(lng, level) {
|
||||
return Math.floor((lng + 180) / 360 * levelToTilesPerEdge(level));
|
||||
}
|
||||
|
||||
window.latToTile = function(lat, level) {
|
||||
return Math.floor((1 - Math.log(Math.tan(lat * Math.PI / 180) +
|
||||
1 / Math.cos(lat * Math.PI / 180)) / Math.PI) / 2 * Math.pow(2, (zoom>12)?zoom:(zoom+2)));
|
||||
1 / Math.cos(lat * Math.PI / 180)) / Math.PI) / 2 * levelToTilesPerEdge(level));
|
||||
}
|
||||
|
||||
window.tileToLng = function(x, zoom) {
|
||||
return x / Math.pow(2, (zoom>12)?zoom:(zoom+2)) * 360 - 180;
|
||||
window.tileToLng = function(x, level) {
|
||||
return x / levelToTilesPerEdge(level) * 360 - 180;
|
||||
}
|
||||
|
||||
window.tileToLat = function(y, zoom) {
|
||||
var n = Math.PI - 2 * Math.PI * y / Math.pow(2, (zoom>12)?zoom:(zoom+2));
|
||||
window.tileToLat = function(y, level) {
|
||||
var n = Math.PI - 2 * Math.PI * y / levelToTilesPerEdge(level);
|
||||
return 180 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n)));
|
||||
}
|
||||
|
||||
window.pointToTileId = function(zoom, x, y) {
|
||||
return zoom + "_" + x + "_" + y;
|
||||
window.pointToTileId = function(level, x, y) {
|
||||
return level + "_" + x + "_" + y;
|
||||
}
|
||||
|
||||
// given tile id and bounds, returns the format as required by the
|
||||
|
@ -192,7 +192,9 @@ window.Render.prototype.deletePortalEntity = function(guid) {
|
||||
window.Render.prototype.deleteLinkEntity = function(guid) {
|
||||
if (guid in window.links) {
|
||||
var l = window.links[guid];
|
||||
linksFactionLayers[l.options.team].removeLayer(l);
|
||||
if (linksFactionLayers[l.options.team].hasLayer(l)) {
|
||||
linksFactionLayers[l.options.team].removeLayer(l);
|
||||
}
|
||||
delete window.links[guid];
|
||||
}
|
||||
}
|
||||
|
@ -28,24 +28,27 @@ window.MapDataRequest = function() {
|
||||
this.MAX_TILE_RETRIES = 3;
|
||||
|
||||
// refresh timers
|
||||
this.MOVE_REFRESH = 0.5; //refresh time to use after a move
|
||||
this.STARTUP_REFRESH = 5; //refresh time used on first load of IITC
|
||||
this.MOVE_REFRESH = 1; //time, after a map move (pan/zoom) before starting the refresh processing
|
||||
this.STARTUP_REFRESH = 3; //refresh time used on first load of IITC
|
||||
this.IDLE_RESUME_REFRESH = 5; //refresh time used after resuming from idle
|
||||
|
||||
// after one of the above, there's an additional delay between preparing the refresh (clearing out of bounds,
|
||||
// processing cache, etc) and actually sending the first network requests
|
||||
this.DOWNLOAD_DELAY = 3; //delay after preparing the data download before tile requests are sent
|
||||
|
||||
// a short delay between one request finishing and the queue being run for the next request
|
||||
|
||||
// a short delay between one request finishing and the queue being run for the next request.
|
||||
// this gives a chance of other requests finishing, allowing better grouping of retries in new requests
|
||||
this.RUN_QUEUE_DELAY = 0.5;
|
||||
|
||||
// delay before re-queueing tiles
|
||||
this.TILE_TIMEOUT_REQUEUE_DELAY = 0.5; // short delay before retrying a 'error==TIMEOUT' tile - as this is very common
|
||||
this.BAD_REQUEST_REQUEUE_DELAY = 4; // longer delay before retrying a completely failed request - as in this case the servers are struggling
|
||||
// delay before re-queueing tiles in failed requests
|
||||
this.BAD_REQUEST_REQUEUE_DELAY = 5; // longer delay before retrying a completely failed request - as in this case the servers are struggling
|
||||
|
||||
// a delay before processing the queue after requeueing tiles. this gives a chance for other requests to finish
|
||||
// or other requeue actions to happen before the queue is processed, allowing better grouping of requests
|
||||
// however, the queue may be processed sooner if a previous timeout was set
|
||||
this.REQUEUE_DELAY = 1;
|
||||
|
||||
// additionally, a delay before processing the queue after requeueing tiles
|
||||
// (this way, if multiple requeue delays finish within a short time of each other, they're all processed in one queue run)
|
||||
this.RERUN_QUEUE_DELAY = 2;
|
||||
|
||||
this.REFRESH_CLOSE = 120; // refresh time to use for close views z>12 when not idle and not moving
|
||||
this.REFRESH_FAR = 600; // refresh time for far views z <= 12
|
||||
@ -89,8 +92,8 @@ window.MapDataRequest.prototype.mapMoveEnd = function() {
|
||||
|
||||
if (this.fetchedDataParams) {
|
||||
// we have fetched (or are fetching) data...
|
||||
if (this.fetchedDataParams.zoom == zoom && this.fetchedDataParams.bounds.contains(bounds)) {
|
||||
// ... and the data zoom levels are the same, and the current bounds is inside the fetched bounds
|
||||
if (this.fetchedDataParams.mapZoom == map.getZoom() && this.fetchedDataParams.bounds.contains(bounds)) {
|
||||
// ... and the zoom level is the same and the current bounds is inside the fetched bounds
|
||||
// so, no need to fetch data. if there's time left, restore the original timeout
|
||||
|
||||
var remainingTime = (this.timerExpectedTimeoutTime - new Date().getTime())/1000;
|
||||
@ -169,8 +172,8 @@ window.MapDataRequest.prototype.refresh = function() {
|
||||
// a 'set' to keep track of hard failures for tiles
|
||||
this.tileErrorCount = {};
|
||||
|
||||
// fill tileBounds with the data needed to request each tile
|
||||
this.tileBounds = {};
|
||||
// the 'set' of requested tile QKs
|
||||
this.queuedTiles = {};
|
||||
|
||||
|
||||
var bounds = clampLatLngBounds(map.getBounds());
|
||||
@ -183,24 +186,24 @@ window.MapDataRequest.prototype.refresh = function() {
|
||||
//var debugrect = L.rectangle(bounds,{color: 'red', fill: false, weight: 4, opacity: 0.8}).addTo(map);
|
||||
//setTimeout (function(){ map.removeLayer(debugrect); }, 10*1000);
|
||||
|
||||
var x1 = lngToTile(bounds.getWest(), zoom);
|
||||
var x2 = lngToTile(bounds.getEast(), zoom);
|
||||
var y1 = latToTile(bounds.getNorth(), zoom);
|
||||
var y2 = latToTile(bounds.getSouth(), zoom);
|
||||
var x1 = lngToTile(bounds.getWest(), minPortalLevel);
|
||||
var x2 = lngToTile(bounds.getEast(), minPortalLevel);
|
||||
var y1 = latToTile(bounds.getNorth(), minPortalLevel);
|
||||
var y2 = latToTile(bounds.getSouth(), minPortalLevel);
|
||||
|
||||
// calculate the full bounds for the data - including the part of the tiles off the screen edge
|
||||
var dataBounds = L.latLngBounds([
|
||||
[tileToLat(y2+1,zoom), tileToLng(x1,zoom)],
|
||||
[tileToLat(y1,zoom), tileToLng(x2+1,zoom)]
|
||||
[tileToLat(y2+1,minPortalLevel), tileToLng(x1,minPortalLevel)],
|
||||
[tileToLat(y1,minPortalLevel), tileToLng(x2+1,minPortalLevel)]
|
||||
]);
|
||||
//var debugrect2 = L.rectangle(dataBounds,{color: 'magenta', fill: false, weight: 4, opacity: 0.8}).addTo(map);
|
||||
//setTimeout (function(){ map.removeLayer(debugrect2); }, 10*1000);
|
||||
|
||||
// store the parameters used for fetching the data. used to prevent unneeded refreshes after move/zoom
|
||||
this.fetchedDataParams = { bounds: dataBounds, zoom: zoom };
|
||||
this.fetchedDataParams = { bounds: dataBounds, mapZoom: map.getZoom(), minPortalLevel: minPortalLevel };
|
||||
|
||||
|
||||
window.runHooks ('mapDataRefreshStart', {bounds: bounds, zoom: zoom, tileBounds: dataBounds});
|
||||
window.runHooks ('mapDataRefreshStart', {bounds: bounds, zoom: zoom, minPortalLevel: minPortalLevel, tileBounds: dataBounds});
|
||||
|
||||
this.render.startRenderPass();
|
||||
this.render.clearPortalsBelowLevel(minPortalLevel);
|
||||
@ -224,11 +227,11 @@ window.MapDataRequest.prototype.refresh = function() {
|
||||
for (var y = y1; y <= y2; y++) {
|
||||
// x goes from bottom to top(?)
|
||||
for (var x = x1; x <= x2; x++) {
|
||||
var tile_id = pointToTileId(zoom, x, y);
|
||||
var latNorth = tileToLat(y,zoom);
|
||||
var latSouth = tileToLat(y+1,zoom);
|
||||
var lngWest = tileToLng(x,zoom);
|
||||
var lngEast = tileToLng(x+1,zoom);
|
||||
var tile_id = pointToTileId(minPortalLevel, x, y);
|
||||
var latNorth = tileToLat(y,minPortalLevel);
|
||||
var latSouth = tileToLat(y+1,minPortalLevel);
|
||||
var lngWest = tileToLng(x,minPortalLevel);
|
||||
var lngEast = tileToLng(x+1,minPortalLevel);
|
||||
|
||||
this.debugTiles.create(tile_id,[[latSouth,lngWest],[latNorth,lngEast]]);
|
||||
|
||||
@ -238,16 +241,17 @@ window.MapDataRequest.prototype.refresh = function() {
|
||||
this.render.processTileData (this.cache.get(tile_id));
|
||||
this.cachedTileCount += 1;
|
||||
} else {
|
||||
// no fresh data - queue a request
|
||||
var boundsParams = generateBoundsParams(
|
||||
tile_id,
|
||||
latSouth,
|
||||
lngWest,
|
||||
latNorth,
|
||||
lngEast
|
||||
);
|
||||
|
||||
this.tileBounds[tile_id] = boundsParams;
|
||||
// no fresh data
|
||||
|
||||
// render the cached stale data, if we have it. this ensures *something* appears quickly when possible
|
||||
var old_data = this.cache && this.cache.get(tile_id);
|
||||
if (old_data) {
|
||||
this.render.processTileData (old_data);
|
||||
}
|
||||
|
||||
// queue a request
|
||||
this.queuedTiles[tile_id] = tile_id;
|
||||
this.requestedTileCount += 1;
|
||||
}
|
||||
}
|
||||
@ -255,10 +259,19 @@ window.MapDataRequest.prototype.refresh = function() {
|
||||
|
||||
this.setStatus ('loading');
|
||||
|
||||
// technically a request hasn't actually finished - however, displayed portal data has been refreshed
|
||||
// so as far as plugins are concerned, it should be treated as a finished request
|
||||
window.runHooks('requestFinished', {success: true});
|
||||
|
||||
console.log ('done request preperation (cleared out-of-bounds and invalid for zoom, and rendered cached data)');
|
||||
|
||||
// don't start processing the download queue immediately - start it after a short delay
|
||||
this.delayProcessRequestQueue (this.DOWNLOAD_DELAY,true);
|
||||
if (Object.keys(this.queuedTiles).length > 0) {
|
||||
// queued requests - don't start processing the download queue immediately - start it after a short delay
|
||||
this.delayProcessRequestQueue (this.DOWNLOAD_DELAY,true);
|
||||
} else {
|
||||
// all data was from the cache, nothing queued - run the queue 'immediately' so it handles the end request processing
|
||||
this.delayProcessRequestQueue (0,true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -273,7 +286,7 @@ window.MapDataRequest.prototype.delayProcessRequestQueue = function(seconds,isFi
|
||||
window.MapDataRequest.prototype.processRequestQueue = function(isFirstPass) {
|
||||
|
||||
// if nothing left in the queue, end the render. otherwise, send network requests
|
||||
if (Object.keys(this.tileBounds).length == 0) {
|
||||
if (Object.keys(this.queuedTiles).length == 0) {
|
||||
|
||||
this.render.endRenderPass();
|
||||
|
||||
@ -301,7 +314,7 @@ window.MapDataRequest.prototype.processRequestQueue = function(isFirstPass) {
|
||||
|
||||
// create a list of tiles that aren't requested over the network
|
||||
var pendingTiles = [];
|
||||
for (var id in this.tileBounds) {
|
||||
for (var id in this.queuedTiles) {
|
||||
if (!(id in this.requestedTiles) ) {
|
||||
pendingTiles.push(id);
|
||||
}
|
||||
@ -351,7 +364,7 @@ window.MapDataRequest.prototype.processRequestQueue = function(isFirstPass) {
|
||||
|
||||
window.MapDataRequest.prototype.sendTileRequest = function(tiles) {
|
||||
|
||||
var boundsParamsList = [];
|
||||
var tilesList = [];
|
||||
|
||||
for (var i in tiles) {
|
||||
var id = tiles[i];
|
||||
@ -360,15 +373,14 @@ window.MapDataRequest.prototype.sendTileRequest = function(tiles) {
|
||||
|
||||
this.requestedTiles[id] = true;
|
||||
|
||||
var boundsParams = this.tileBounds[id];
|
||||
if (boundsParams) {
|
||||
boundsParamsList.push (boundsParams);
|
||||
if (id in this.queuedTiles) {
|
||||
tilesList.push (id);
|
||||
} else {
|
||||
console.warn('failed to find bounds for tile id '+id);
|
||||
console.warn('no queue entry for tile id '+id);
|
||||
}
|
||||
}
|
||||
|
||||
var data = { boundsParamsList: boundsParamsList };
|
||||
var data = { quadKeys: tilesList };
|
||||
|
||||
this.activeRequestCount += 1;
|
||||
|
||||
@ -382,7 +394,7 @@ window.MapDataRequest.prototype.sendTileRequest = function(tiles) {
|
||||
}
|
||||
|
||||
window.MapDataRequest.prototype.requeueTile = function(id, error) {
|
||||
if (id in this.tileBounds) {
|
||||
if (id in this.queuedTiles) {
|
||||
// tile is currently wanted...
|
||||
|
||||
// first, see if the error can be ignored due to retry counts
|
||||
@ -408,7 +420,7 @@ window.MapDataRequest.prototype.requeueTile = function(id, error) {
|
||||
this.failedTileCount += 1;
|
||||
}
|
||||
// and delete from the pending requests...
|
||||
delete this.tileBounds[id];
|
||||
delete this.queuedTiles[id];
|
||||
|
||||
} else {
|
||||
// if false, was a 'timeout' or we're retrying, so unlimited retries (as the stock site does)
|
||||
@ -418,9 +430,8 @@ window.MapDataRequest.prototype.requeueTile = function(id, error) {
|
||||
// proper queue, just an object with guid as properties. Javascript standards don't guarantee the order of properties
|
||||
// within an object. however, all current browsers do keep property order, and new properties are added at the end.
|
||||
// therefore, delete and re-add the requeued tile and it will be added to the end of the queue
|
||||
var boundsData = this.tileBounds[id];
|
||||
delete this.tileBounds[id];
|
||||
this.tileBounds[id] = boundsData;
|
||||
delete this.queuedTiles[id];
|
||||
this.queuedTiles[id] = id;
|
||||
|
||||
}
|
||||
} // else the tile wasn't currently wanted (an old non-cancelled request) - ignore
|
||||
@ -463,7 +474,6 @@ window.MapDataRequest.prototype.handleResponse = function (data, tiles, success)
|
||||
if (val.error == "TIMEOUT") {
|
||||
// TIMEOUT errors for individual tiles are 'expected'(!) - and result in a silent unlimited retries
|
||||
timeoutTiles.push (id);
|
||||
this.debugTiles.setState (id, 'tile-timeout');
|
||||
} else {
|
||||
console.warn('map data tile '+id+' failed: error=='+val.error);
|
||||
errorTiles.push (id);
|
||||
@ -478,12 +488,12 @@ window.MapDataRequest.prototype.handleResponse = function (data, tiles, success)
|
||||
|
||||
// if this tile was in the render list, render it
|
||||
// (requests aren't aborted when new requests are started, so it's entirely possible we don't want to render it!)
|
||||
if (id in this.tileBounds) {
|
||||
if (id in this.queuedTiles) {
|
||||
this.debugTiles.setState (id, 'ok');
|
||||
|
||||
this.render.processTileData (val);
|
||||
|
||||
delete this.tileBounds[id];
|
||||
delete this.queuedTiles[id];
|
||||
this.successTileCount += 1;
|
||||
|
||||
} // else we don't want this tile (from an old non-cancelled request) - ignore
|
||||
@ -491,6 +501,9 @@ window.MapDataRequest.prototype.handleResponse = function (data, tiles, success)
|
||||
|
||||
}
|
||||
|
||||
// TODO? check for any requested tiles in 'tiles' not being mentioned in the response - and handle as if it's a 'timeout'?
|
||||
|
||||
|
||||
window.runHooks('requestFinished', {success: true});
|
||||
}
|
||||
|
||||
@ -498,28 +511,27 @@ window.MapDataRequest.prototype.handleResponse = function (data, tiles, success)
|
||||
console.log ('getThinnedEntities status: '+tiles.length+' tiles: '+successTiles.length+' successful, '+timeoutTiles.length+' timed out, '+errorTiles.length+' failed');
|
||||
|
||||
|
||||
//setTimeout has no way of passing the 'context' (aka 'this') to it's function
|
||||
var savedContext = this;
|
||||
|
||||
// requeue any 'timeout' tiles immediately
|
||||
if (timeoutTiles.length > 0) {
|
||||
setTimeout (function() {
|
||||
for (var i in timeoutTiles) {
|
||||
var id = timeoutTiles[i];
|
||||
delete savedContext.requestedTiles[id];
|
||||
savedContext.requeueTile(id, false);
|
||||
}
|
||||
savedContext.delayProcessRequestQueue(this.RERUN_QUEUE_DELAY);
|
||||
}, this.TILE_TIMEOUT_REQUEUE_DELAY*1000);
|
||||
for (var i in timeoutTiles) {
|
||||
var id = timeoutTiles[i];
|
||||
delete this.requestedTiles[id];
|
||||
this.requeueTile(id, false);
|
||||
}
|
||||
}
|
||||
|
||||
// but for other errors, delay before retrying (as the server is having issues)
|
||||
if (errorTiles.length > 0) {
|
||||
//setTimeout has no way of passing the 'context' (aka 'this') to it's function
|
||||
var savedContext = this;
|
||||
|
||||
setTimeout (function() {
|
||||
for (var i in errorTiles) {
|
||||
var id = errorTiles[i];
|
||||
delete savedContext.requestedTiles[id];
|
||||
savedContext.requeueTile(id, true);
|
||||
}
|
||||
savedContext.delayProcessRequestQueue(this.RERUN_QUEUE_DELAY);
|
||||
savedContext.delayProcessRequestQueue(this.REQUEUE_DELAY);
|
||||
}, this.BAD_REQUEST_REQUEUE_DELAY*1000);
|
||||
}
|
||||
|
||||
|
@ -1,42 +1,45 @@
|
||||
// created to start cleaning up "window" interaction
|
||||
//
|
||||
window.show = function(id) {
|
||||
window.hideall();
|
||||
if (typeof android !== 'undefined' && android && android.switchToPane) {
|
||||
android.switchToPane(id);
|
||||
}
|
||||
switch(id) {
|
||||
case 'full':
|
||||
window.chat.show('full');
|
||||
break;
|
||||
case 'compact':
|
||||
window.chat.show('compact');
|
||||
break;
|
||||
case 'public':
|
||||
window.chat.show('public');
|
||||
break;
|
||||
case 'faction':
|
||||
window.chat.show('faction');
|
||||
break;
|
||||
case 'debug':
|
||||
window.debug.console.show();
|
||||
break;
|
||||
case 'map':
|
||||
window.smartphone.mapButton.click();
|
||||
$('#portal_highlight_select').show();
|
||||
$('#farm_level_select').show();
|
||||
break;
|
||||
case 'info':
|
||||
window.smartphone.sideButton.click();
|
||||
break;
|
||||
default:
|
||||
window.smartphone.mapButton.click();
|
||||
break;
|
||||
}
|
||||
window.hideall();
|
||||
|
||||
switch(id) {
|
||||
case 'full':
|
||||
window.chat.show('full');
|
||||
break;
|
||||
case 'compact':
|
||||
window.chat.show('compact');
|
||||
break;
|
||||
case 'public':
|
||||
window.chat.show('public');
|
||||
break;
|
||||
case 'faction':
|
||||
window.chat.show('faction');
|
||||
break;
|
||||
case 'debug':
|
||||
window.debug.console.show();
|
||||
break;
|
||||
case 'map':
|
||||
window.smartphone.mapButton.click();
|
||||
$('#portal_highlight_select').show();
|
||||
$('#farm_level_select').show();
|
||||
break;
|
||||
case 'info':
|
||||
window.smartphone.sideButton.click();
|
||||
break;
|
||||
default:
|
||||
window.smartphone.mapButton.click();
|
||||
break;
|
||||
}
|
||||
|
||||
if (typeof android !== 'undefined' && android && android.switchToPane) {
|
||||
android.switchToPane(id);
|
||||
}
|
||||
}
|
||||
|
||||
window.hideall = function() {
|
||||
$('#chatcontrols, #chat, #chatinput, #sidebartoggle, #scrollwrapper, #updatestatus, #portal_highlight_select').hide();
|
||||
$('#farm_level_select').hide();
|
||||
$('#map').css('visibility', 'hidden');
|
||||
$('#chatcontrols, #chat, #chatinput, #sidebartoggle, #scrollwrapper, #updatestatus, #portal_highlight_select').hide();
|
||||
$('#farm_level_select').hide();
|
||||
$('#map').css('visibility', 'hidden');
|
||||
$('.ui-tooltip').remove();
|
||||
}
|
||||
|
@ -39,6 +39,12 @@ window.playerNameToGuid = function(playerName) {
|
||||
var cachedGuid = window._playerNameToGuidCache[playerName];
|
||||
if (cachedGuid !== undefined) return cachedGuid;
|
||||
|
||||
// IITC needs our own player GUID, from a lookup by name. so we retrieve this from localstorage (if available)
|
||||
if (playerName == PLAYER.nickname) {
|
||||
cachedGuid = localStorage['PLAYER-'+PLAYER.nickname];
|
||||
if (cachedGuid !== undefined) return cachedGuid;
|
||||
}
|
||||
|
||||
var guid = null;
|
||||
$.each(Object.keys(sessionStorage), function(ind,key) {
|
||||
if(playerName === sessionStorage[key]) {
|
||||
@ -68,9 +74,11 @@ window.resolvePlayerNames = function() {
|
||||
window.playersInResolving = window.playersInResolving.concat(p);
|
||||
|
||||
postAjax('getPlayersByGuids', d, function(dat) {
|
||||
var resolvedName = {};
|
||||
if(dat.result) {
|
||||
$.each(dat.result, function(ind, player) {
|
||||
window.setPlayerName(player.guid, player.nickname);
|
||||
resolvedName[player.guid] = player.nickname;
|
||||
// remove from array
|
||||
window.playersInResolving.splice(window.playersInResolving.indexOf(player.guid), 1);
|
||||
});
|
||||
@ -82,6 +90,9 @@ window.resolvePlayerNames = function() {
|
||||
//therefore, not a good idea to automatically retry by adding back to the playersToResolve list
|
||||
}
|
||||
|
||||
// Run hook 'playerNameResolved' with the resolved player names
|
||||
window.runHooks('playerNameResolved', {names: resolvedName});
|
||||
|
||||
//TODO: have an event triggered for this instead of hard-coded single function call
|
||||
if(window.selectedPortal)
|
||||
window.renderPortalDetails(window.selectedPortal);
|
||||
@ -107,22 +118,17 @@ window.setPlayerName = function(guid, nick, uncertain) {
|
||||
alert('You have run into bug #37. Please help me solve it!\nCopy and paste this text and post it here:\nhttps://github.com/breunigs/ingress-intel-total-conversion/issues/37\nIf copy & pasting doesn’t work, make a screenshot instead.\n\n\n' + window.debug.printStackTrace() + '\n\n\n' + JSON.stringify(nick));
|
||||
}
|
||||
sessionStorage[guid] = nick;
|
||||
|
||||
// IITC needs our own player ID early on in startup. the only way we can find this is by something else
|
||||
// doing a guid->name lookup for our own name. as this doesn't always happen - and likely won't happen when needed
|
||||
// we'll store our own name->guid lookup in localStorage
|
||||
if (nick == PLAYER.nickname) {
|
||||
localStorage['PLAYER-'+PLAYER.nickname] = guid;
|
||||
PLAYER.guid = guid; // set it in PLAYER in case it wasn't already done
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
window.loadPlayerNamesForPortal = function(portal_details) {
|
||||
if(map.getZoom() < PRECACHE_PLAYER_NAMES_ZOOM) return;
|
||||
var e = portal_details;
|
||||
|
||||
if(e.captured && e.captured.capturingPlayerId)
|
||||
getPlayerName(e.captured.capturingPlayerId);
|
||||
|
||||
if(!e.resonatorArray || !e.resonatorArray.resonators) return;
|
||||
|
||||
$.each(e.resonatorArray.resonators, function(ind, reso) {
|
||||
if(reso) getPlayerName(reso.ownerGuid);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// test to see if a specific player GUID is a special system account (e.g. __JARVIS__, __ADA__) that shouldn't
|
||||
|
@ -90,6 +90,17 @@ window.renderPortalDetails = function(guid) {
|
||||
portalDetailedDescription += '</table>';
|
||||
}
|
||||
|
||||
var levelDetails = getPortalLevel(d);
|
||||
if(levelDetails != 8) {
|
||||
if(levelDetails==Math.ceil(levelDetails))
|
||||
levelDetails += "\n8";
|
||||
else
|
||||
levelDetails += "\n" + (Math.ceil(levelDetails) - levelDetails)*8;
|
||||
levelDetails += " resonator level(s) needed for next portal level";
|
||||
} else {
|
||||
levelDetails += "\nfully upgraded";
|
||||
}
|
||||
levelDetails = "Level " + levelDetails;
|
||||
|
||||
$('#portaldetails')
|
||||
.attr('class', TEAM_TO_CSS[getTeam(d)])
|
||||
@ -98,7 +109,7 @@ window.renderPortalDetails = function(guid) {
|
||||
+ '<span class="close" onclick="renderPortalDetails(null); if(isSmartphone()) show(\'map\');" title="Close">X</span>'
|
||||
// help cursor via ".imgpreview img"
|
||||
+ '<div class="imgpreview" '+imgTitle+' style="background-image: url('+img+')">'
|
||||
+ '<span id="level">'+Math.floor(getPortalLevel(d))+'</span>'
|
||||
+ '<span id="level" title="'+levelDetails+'">'+Math.floor(getPortalLevel(d))+'</span>'
|
||||
+ '<div class="portalDetails">'+ portalDetailedDescription + '</div>'
|
||||
+ '<img class="hide" src="'+img+'"/></div>'
|
||||
+ '</div>'
|
||||
@ -134,9 +145,14 @@ window.setPortalIndicators = function(d) {
|
||||
|
||||
var range = getPortalRange(d);
|
||||
var coord = [d.locationE6.latE6/1E6, d.locationE6.lngE6/1E6];
|
||||
portalRangeIndicator = (range > 0
|
||||
? L.geodesicCircle(coord, range, { fill: false, color: RANGE_INDICATOR_COLOR, weight: 3, clickable: false })
|
||||
: L.circle(coord, range, { fill: false, stroke: false, clickable: false })
|
||||
portalRangeIndicator = (range.range > 0
|
||||
? L.geodesicCircle(coord, range.range, {
|
||||
fill: false,
|
||||
color: RANGE_INDICATOR_COLOR,
|
||||
weight: 3,
|
||||
dashArray: range.isLinkable ? undefined : "10,10",
|
||||
clickable: false })
|
||||
: L.circle(coord, range.range, { fill: false, stroke: false, clickable: false })
|
||||
).addTo(map);
|
||||
|
||||
portalAccessIndicator = L.circle(coord, HACK_RANGE,
|
||||
|
@ -5,11 +5,20 @@
|
||||
// returns displayable text+link about portal range
|
||||
window.getRangeText = function(d) {
|
||||
var range = getPortalRange(d);
|
||||
|
||||
var title = 'Base range:\t' + digits(Math.floor(range.base))+'m'
|
||||
+ '\nLink amp boost:\t×'+range.boost
|
||||
+ '\nRange:\t'+digits(Math.floor(range.range))+'m';
|
||||
|
||||
if(!range.isLinkable) title += '\nPortal is missing resonators,\nno new links can be made';
|
||||
|
||||
return ['range',
|
||||
'<a onclick="window.rangeLinkClick()">'
|
||||
+ (range > 1000
|
||||
? Math.floor(range/1000) + ' km'
|
||||
: Math.floor(range) + ' m')
|
||||
'<a onclick="window.rangeLinkClick()"'
|
||||
+ (range.isLinkable ? '' : ' style="text-decoration:line-through;"')
|
||||
+ ' title="'+title+'">'
|
||||
+ (range.range > 1000
|
||||
? Math.floor(range.range/1000) + ' km'
|
||||
: Math.floor(range.range) + ' m')
|
||||
+ '</a>'];
|
||||
}
|
||||
|
||||
|
@ -47,18 +47,20 @@ window.getPortalRange = function(d) {
|
||||
$.each(d.resonatorArray.resonators, function(ind, reso) {
|
||||
if(!reso) {
|
||||
resoMissing = true;
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
lvl += parseInt(reso.level);
|
||||
});
|
||||
if(resoMissing) return 0;
|
||||
|
||||
var range = 160*Math.pow(getPortalLevel(d), 4);
|
||||
var range = {
|
||||
base: 160*Math.pow(getPortalLevel(d), 4),
|
||||
boost: getLinkAmpRangeBoost(d)
|
||||
};
|
||||
|
||||
var boost = getLinkAmpRangeBoost(d);
|
||||
|
||||
return range*boost;
|
||||
range.range = range.boost * range.base;
|
||||
range.isLinkable = !resoMissing;
|
||||
|
||||
return range;
|
||||
}
|
||||
|
||||
window.getLinkAmpRangeBoost = function(d) {
|
||||
|
@ -35,7 +35,6 @@ window.runOnSmartphonesBeforeBoot = function() {
|
||||
}
|
||||
|
||||
window.smartphone.mapButton = $('<a>map</a>').click(function() {
|
||||
$('#chat, #chatinput, #scrollwrapper').hide();
|
||||
$('#map').css('visibility', 'visible');
|
||||
$('#updatestatus').show();
|
||||
$('#chatcontrols a .active').removeClass('active');
|
||||
@ -43,8 +42,6 @@ window.runOnSmartphonesBeforeBoot = function() {
|
||||
});
|
||||
|
||||
window.smartphone.sideButton = $('<a>info</a>').click(function() {
|
||||
$('#chat, #chatinput, #updatestatus').hide();
|
||||
$('#map').css('visibility', 'hidden');
|
||||
$('#scrollwrapper').show();
|
||||
$('.active').removeClass('active');
|
||||
$("#chatcontrols a:contains('info')").addClass('active');
|
||||
@ -112,11 +109,13 @@ window.runOnSmartphonesAfterBoot = function() {
|
||||
if(!isSmartphone()) return;
|
||||
console.warn('running smartphone post boot stuff');
|
||||
|
||||
smartphone.mapButton.click();
|
||||
window.show('map');
|
||||
|
||||
// add a div/hook for updating mobile info
|
||||
$('#updatestatus').prepend('<div id="mobileinfo" onclick="show(\'info\')"></div>');
|
||||
window.addHook('portalDetailsUpdated', window.smartphoneInfo);
|
||||
// init msg of status bar. hint for the user that a tap leads to the info screen
|
||||
$('#mobileinfo').html('<div style="text-align: center"><b>tap here for info screen</b></div>');
|
||||
|
||||
// disable img full view
|
||||
$('#portaldetails').off('click', '**');
|
||||
|
@ -1,597 +0,0 @@
|
||||
// UTILS + MISC ///////////////////////////////////////////////////////
|
||||
|
||||
window.aboutIITC = function(){
|
||||
var v = '@@BUILDNAME@@-@@BUILDDATE@@';
|
||||
var attrib = '@@INCLUDEMD:ATTRIBUTION.md@@';
|
||||
var contrib = '@@INCLUDEMD:CONTRIBS.md@@'
|
||||
var a = ''
|
||||
+ ' <div><b>About IITC</b></div> '
|
||||
+ ' <div>Ingress Intel Total Conversion</div> '
|
||||
+ ' <hr>'
|
||||
+ ' <div>'
|
||||
+ ' <a href="http://iitc.jonatkins.com/" target="_blank">IITC Homepage</a><br />'
|
||||
+ ' On the script’s homepage you can:'
|
||||
+ ' <ul>'
|
||||
+ ' <li>Find Updates</li>'
|
||||
+ ' <li>Get Plugins</li>'
|
||||
+ ' <li>Report Bugs</li>'
|
||||
+ ' <li>Contribute!</li>'
|
||||
+ ' </ul>'
|
||||
+ ' </div>'
|
||||
+ ' <div>'
|
||||
+ ' MapQuest OSM tiles Courtesy of <a href="http://www.mapquest.com/" target="_blank">MapQuest</a> <img src="https://developer.mapquest.com/content/osm/mq_logo.png">'
|
||||
+ ' </div>'
|
||||
+ ' <hr>'
|
||||
+ ' <div>Version: ' + v + '</div>'
|
||||
+ ' <hr>'
|
||||
+ ' <div>' + attrib + '</div>'
|
||||
+ ' <hr>'
|
||||
+ ' <div>' + contrib + '</div>';
|
||||
dialog({
|
||||
title: 'IITC ' + v,
|
||||
html: a,
|
||||
dialogClass: 'ui-dialog-aboutIITC'
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
window.layerGroupLength = function(layerGroup) {
|
||||
var layersCount = 0;
|
||||
var layers = layerGroup._layers;
|
||||
if (layers)
|
||||
layersCount = Object.keys(layers).length;
|
||||
return layersCount;
|
||||
}
|
||||
|
||||
// retrieves parameter from the URL?query=string.
|
||||
window.getURLParam = function(param) {
|
||||
var v = document.URL;
|
||||
var i = v.indexOf(param);
|
||||
if(i <= -1) return '';
|
||||
v = v.substr(i);
|
||||
i = v.indexOf("&");
|
||||
if(i >= 0) v = v.substr(0, i);
|
||||
return v.replace(param+"=","");
|
||||
}
|
||||
|
||||
// read cookie by name.
|
||||
// http://stackoverflow.com/a/5639455/1684530 by cwolves
|
||||
var cookies;
|
||||
window.readCookie = function(name,c,C,i){
|
||||
if(cookies) return cookies[name];
|
||||
c = document.cookie.split('; ');
|
||||
cookies = {};
|
||||
for(i=c.length-1; i>=0; i--){
|
||||
C = c[i].split('=');
|
||||
cookies[C[0]] = unescape(C[1]);
|
||||
}
|
||||
return cookies[name];
|
||||
}
|
||||
|
||||
window.writeCookie = function(name, val) {
|
||||
document.cookie = name + "=" + val + '; expires=Thu, 31 Dec 2020 23:59:59 GMT; path=/';
|
||||
}
|
||||
|
||||
window.eraseCookie = function(name) {
|
||||
document.cookie = name + '=; expires=Thu, 1 Jan 1970 00:00:00 GMT; path=/';
|
||||
}
|
||||
|
||||
//certain values were stored in cookies, but we're better off using localStorage instead - make it easy to convert
|
||||
window.convertCookieToLocalStorage = function(name) {
|
||||
var cookie=readCookie(name);
|
||||
if(cookie !== undefined) {
|
||||
console.log('converting cookie '+name+' to localStorage');
|
||||
if(localStorage[name] === undefined) {
|
||||
localStorage[name] = cookie;
|
||||
}
|
||||
eraseCookie(name);
|
||||
}
|
||||
}
|
||||
|
||||
// add thousand separators to given number.
|
||||
// http://stackoverflow.com/a/1990590/1684530 by Doug Neiner.
|
||||
window.digits = function(d) {
|
||||
return (d+"").replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1 ");
|
||||
}
|
||||
|
||||
|
||||
window.requestParameterMunges = [
|
||||
// now obsolete (they don't have some of the new parameters) munge sets deleted
|
||||
|
||||
|
||||
// set 3 - in the update of 2013-09-30 (addition of 'alerts' chat tab)
|
||||
{
|
||||
'dashboard.getGameScore': 'fhlzntzkl5v7hcfh', // GET_GAME_SCORE
|
||||
'dashboard.getPaginatedPlextsV2': 'wzuitnswoda7w028', // GET_PAGINATED_PLEXTS
|
||||
'dashboard.getThinnedEntitiesV4': 'scgrm4lf2371esgw', // GET_THINNED_ENTITIES
|
||||
'dashboard.getPlayersByGuids': '81l6usczczoi3lfi', // LOOKUP_PLAYERS
|
||||
'dashboard.redeemReward': '8kop2koeld9b4c26', // REDEEM_REWARD
|
||||
'dashboard.sendInviteEmail': 't0ccodsm1nuo5uso', // SEND_INVITE_EMAIL
|
||||
'dashboard.sendPlext': 'k04cfjwwsg3h3827', // SEND_PLEXT
|
||||
|
||||
method: '22ux2z96jwq5zn78',
|
||||
version: 'kf6hgl9yau03ws0o', //guessed parameter name - only seen munged
|
||||
version_parameter: '4608f4356a6f55690f127fb542f557f98de66169', // passed as the value to the above parameter
|
||||
boundsParamsList: '29t16cmsn6l3r2xg',
|
||||
id: '7rogqhp5pzcqobcw',
|
||||
minLatE6: 'yzbnp7z9bd28p0yr',
|
||||
minLngE6: '2pdhntvo85cd90bw',
|
||||
maxLatE6: 'c4ivr013h4dr68pd',
|
||||
maxLngE6: '4p8oorcrwalc1mzf',
|
||||
timestampMs: 'vd2rsa9v6f8q606s',
|
||||
qk: 'cblh9xe0bgwjy5ij',
|
||||
desiredNumItems: '3ymaq7slb165porj',
|
||||
minTimestampMs: 's9jf2seni33y3gyu',
|
||||
maxTimestampMs: '2kh3vti98rhp3g29',
|
||||
chatTab: '7n7ocqfq1p18352b', //guessed parameter name - only seen munged
|
||||
ascendingTimestampOrder: 'p88a2ztchtjhiazl',
|
||||
message: 'e8qm0kptw2trrcrw',
|
||||
latE6: 'fja1phtsqxm71dqm',
|
||||
lngE6: 'iut1tb7c0x726hwn',
|
||||
guids: '5hyiwhwc0jyljvro',
|
||||
inviteeEmailAddress: 's9z6zt03eymzxhkj',
|
||||
},
|
||||
|
||||
// set 4 - second update of 2013-09-30
|
||||
{
|
||||
'dashboard.getGameScore': 'ija9jgrf5hj7wm9r', // GET_GAME_SCORE
|
||||
'dashboard.getPaginatedPlextsV2': '0elftx739mkbzi1b', // GET_PAGINATED_PLEXTS
|
||||
'dashboard.getThinnedEntitiesV4': 'prv0ez8cbsykh63g', // GET_THINNED_ENTITIES
|
||||
'dashboard.getPlayersByGuids': 'i0lxy6nc695z9ka3', // LOOKUP_PLAYERS
|
||||
'dashboard.redeemReward': '376oivna8rf8qbfj', // REDEEM_REWARD
|
||||
'dashboard.sendInviteEmail': '96y930v5q96nrcrw', // SEND_INVITE_EMAIL
|
||||
'dashboard.sendPlext': 'c04kceytofuqvyqg', // SEND_PLEXT
|
||||
|
||||
method: '9we4b31i48ui4sdm',
|
||||
version: 'q402kn5zqisuo1ym', //guessed parameter name - only seen munged
|
||||
version_parameter: 'dbad4485024d446ae946e3d287b5d640029ef3e3', // passed as the value to the above parameter
|
||||
boundsParamsList: '3r5ctyvc2f653zjd',
|
||||
id: 'izey8ciqg2dz2oqc',
|
||||
minLatE6: 'cein0n4jrifa7ui2',
|
||||
minLngE6: 'lbd1juids3johtdo',
|
||||
maxLatE6: 'h4kyot9kmvd3g284',
|
||||
maxLngE6: 'sbci6jjc2d5g9uy4',
|
||||
timestampMs: '2wurn9giagbvv6bt',
|
||||
qk: 'hq73mwpjqyvcp6ul',
|
||||
desiredNumItems: 'kyo6vh5n58hmrnua',
|
||||
minTimestampMs: 'hu4swdftcp7mvkdi',
|
||||
maxTimestampMs: 'ly6ylae5lv1z9072',
|
||||
chatTab: 'q5kxut5rmbtlqbf9', //guessed parameter name - only seen munged
|
||||
ascendingTimestampOrder: 'hvfd0io35rahwjgr',
|
||||
message: 'z4hf7tzl27o14455',
|
||||
latE6: 'zyzh3bdxyd47vk1x',
|
||||
lngE6: 'n5d1f8pql51t641x',
|
||||
guids: 'gl16ehqoc3i3oi07',
|
||||
inviteeEmailAddress: 'orc9ufg7rp7g1y9j',
|
||||
},
|
||||
|
||||
];
|
||||
window.activeRequestMungeSet = undefined;
|
||||
|
||||
// attempt to guess the munge set in use, by looking therough the functions of the stock intel page for one of the munged params
|
||||
window.detectActiveMungeSet = function() {
|
||||
if (window.requestParameterMunges.length == 1) {
|
||||
// no point in searching through the code when there's only one set in use
|
||||
window.activeRequestMungeSet = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// try and find the stock page functions
|
||||
// FIXME? revert to searching through all the code? is that practical?
|
||||
var stockFunc = nemesis.dashboard.network.DataFetcher.prototype.sendRequest_.toString()
|
||||
for (var i in window.requestParameterMunges) {
|
||||
if (stockFunc.indexOf (window.requestParameterMunges[i]['method']) >= 0) {
|
||||
console.log('IITC: found request munge set index '+i+' in stock intel function nemesis.dashboard.network.DataFetcher.prototype.sendRequest_');
|
||||
window.activeRequestMungeSet = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (window.activeRequestMungeSet===undefined) {
|
||||
console.error('IITC: failed to find request munge set - IITC will likely fail');
|
||||
window.activeRequestMungeSet = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// niantic now add some munging to the request parameters. so far, only two sets of this munging have been seen
|
||||
window.requestDataMunge = function(data) {
|
||||
var activeMunge = window.requestParameterMunges[window.activeRequestMungeSet];
|
||||
|
||||
function munge(obj) {
|
||||
if (Object.prototype.toString.call(obj) === '[object Array]') {
|
||||
// an array - munge each element of it
|
||||
var newobj = [];
|
||||
for (var i in obj) {
|
||||
newobj[i] = munge(obj[i]);
|
||||
}
|
||||
return newobj;
|
||||
} else if (typeof obj === 'object') {
|
||||
// an object: munge each property name, and pass the value through the munge process
|
||||
var newobj = Object();
|
||||
for (var p in obj) {
|
||||
var m = activeMunge[p];
|
||||
if (m === undefined) {
|
||||
console.error('Error: failed to find munge for object property '+p);
|
||||
newobj[p] = obj[p];
|
||||
} else {
|
||||
// rename the property
|
||||
newobj[m] = munge(obj[p]);
|
||||
}
|
||||
}
|
||||
return newobj;
|
||||
} else {
|
||||
// neither an array or an object - so must be a simple value. return it unmodified
|
||||
return obj;
|
||||
}
|
||||
};
|
||||
|
||||
var newdata = munge(data);
|
||||
return newdata;
|
||||
}
|
||||
|
||||
// posts AJAX request to Ingress API.
|
||||
// action: last part of the actual URL, the rpc/dashboard. is
|
||||
// added automatically
|
||||
// data: JSON data to post. method will be derived automatically from
|
||||
// action, but may be overridden. Expects to be given Hash.
|
||||
// Strings are not supported.
|
||||
// success: method to call on success. See jQuery API docs for avail-
|
||||
// able arguments: http://api.jquery.com/jQuery.ajax/
|
||||
// error: see above. Additionally it is logged if the request failed.
|
||||
window.postAjax = function(action, data, success, error) {
|
||||
if (window.activeRequestMungeSet===undefined) {
|
||||
window.detectActiveMungeSet();
|
||||
}
|
||||
var activeMunge = window.requestParameterMunges[window.activeRequestMungeSet];
|
||||
|
||||
var methodName = 'dashboard.'+action;
|
||||
var versionStr = 'version_parameter';
|
||||
|
||||
// munging of the method name - seen in Set 2 (onwards?)
|
||||
methodName = activeMunge[methodName];
|
||||
// and of the 'version' parameter
|
||||
versionStr = activeMunge[versionStr];
|
||||
|
||||
var post_data = JSON.stringify(window.requestDataMunge($.extend({method: methodName, version: versionStr}, data)));
|
||||
var remove = function(data, textStatus, jqXHR) { window.requests.remove(jqXHR); };
|
||||
var errCnt = function(jqXHR) { window.failedRequestCount++; window.requests.remove(jqXHR); };
|
||||
var result = $.ajax({
|
||||
url: '/r/'+methodName,
|
||||
type: 'POST',
|
||||
data: post_data,
|
||||
context: data,
|
||||
dataType: 'json',
|
||||
success: [remove, success],
|
||||
error: error ? [errCnt, error] : errCnt,
|
||||
contentType: 'application/json; charset=utf-8',
|
||||
beforeSend: function(req) {
|
||||
req.setRequestHeader('X-CSRFToken', readCookie('csrftoken'));
|
||||
}
|
||||
});
|
||||
result.action = action;
|
||||
return result;
|
||||
}
|
||||
|
||||
window.zeroPad = function(number,pad) {
|
||||
number = number.toString();
|
||||
var zeros = pad - number.length;
|
||||
return Array(zeros>0?zeros+1:0).join("0") + number;
|
||||
}
|
||||
|
||||
|
||||
// converts javascript timestamps to HH:mm:ss format if it was today;
|
||||
// otherwise it returns YYYY-MM-DD
|
||||
window.unixTimeToString = function(time, full) {
|
||||
if(!time) return null;
|
||||
var d = new Date(typeof time === 'string' ? parseInt(time) : time);
|
||||
var time = d.toLocaleTimeString();
|
||||
var date = d.getFullYear()+'-'+zeroPad(d.getMonth()+1,2)+'-'+zeroPad(d.getDate(),2);
|
||||
if(typeof full !== 'undefined' && full) return date + ' ' + time;
|
||||
if(d.toDateString() == new Date().toDateString())
|
||||
return time;
|
||||
else
|
||||
return date;
|
||||
}
|
||||
|
||||
// converts a javascript time to a precise date and time (optionally with millisecond precision)
|
||||
// formatted in ISO-style YYYY-MM-DD hh:mm:ss.mmm - but using local timezone
|
||||
window.unixTimeToDateTimeString = function(time, millisecond) {
|
||||
if(!time) return null;
|
||||
var d = new Date(typeof time === 'string' ? parseInt(time) : time);
|
||||
return d.getFullYear()+'-'+zeroPad(d.getMonth()+1,2)+'-'+zeroPad(d.getDate(),2)
|
||||
+' '+d.toLocaleTimeString()+(millisecond?'.'+zeroPad(d.getMilliseconds(),3):'');
|
||||
}
|
||||
|
||||
window.unixTimeToHHmm = function(time) {
|
||||
if(!time) return null;
|
||||
var d = new Date(typeof time === 'string' ? parseInt(time) : time);
|
||||
var h = '' + d.getHours(); h = h.length === 1 ? '0' + h : h;
|
||||
var s = '' + d.getMinutes(); s = s.length === 1 ? '0' + s : s;
|
||||
return h + ':' + s;
|
||||
}
|
||||
|
||||
window.formatInterval = function(seconds) {
|
||||
|
||||
var h = Math.floor(seconds / 3600);
|
||||
var m = Math.floor((seconds % 3600) / 60);
|
||||
var s = seconds % 60;
|
||||
|
||||
var text = '';
|
||||
if (h > 0) text += h+'h';
|
||||
if (m > 0) text += m+'m';
|
||||
if (s > 0 || text == '') text += s+'s';
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
window.rangeLinkClick = function() {
|
||||
if(window.portalRangeIndicator)
|
||||
window.map.fitBounds(window.portalRangeIndicator.getBounds());
|
||||
if(window.isSmartphone())
|
||||
window.smartphone.mapButton.click();
|
||||
}
|
||||
|
||||
window.showPortalPosLinks = function(lat, lng, name) {
|
||||
var encoded_name = 'undefined';
|
||||
if(name !== undefined) {
|
||||
encoded_name = encodeURIComponent(name);
|
||||
}
|
||||
|
||||
if (typeof android !== 'undefined' && android && android.intentPosLink) {
|
||||
android.intentPosLink(lat, lng, map.getZoom(), name, true);
|
||||
} else {
|
||||
var qrcode = '<div id="qrcode"></div>';
|
||||
var script = '<script>$(\'#qrcode\').qrcode({text:\'GEO:'+lat+','+lng+'\'});</script>';
|
||||
var gmaps = '<a href="https://maps.google.com/?q='+lat+','+lng+'%20('+encoded_name+')">Google Maps</a>';
|
||||
var bingmaps = '<a href="http://www.bing.com/maps/?v=2&cp='+lat+'~'+lng+'&lvl=16&sp=Point.'+lat+'_'+lng+'_'+encoded_name+'___">Bing Maps</a>';
|
||||
var osm = '<a href="http://www.openstreetmap.org/?mlat='+lat+'&mlon='+lng+'&zoom=16">OpenStreetMap</a>';
|
||||
var latLng = '<span><' + lat + ',' + lng +'></span>';
|
||||
dialog({
|
||||
html: '<div style="text-align: center;">' + qrcode + script + gmaps + '; ' + bingmaps + '; ' + osm + '<br />' + latLng + '</div>',
|
||||
title: name,
|
||||
id: 'poslinks'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
window.androidCopy = function(text) {
|
||||
if(typeof android === 'undefined' || !android || !android.copy)
|
||||
return true; // i.e. execute other actions
|
||||
else
|
||||
android.copy(text);
|
||||
return false;
|
||||
}
|
||||
|
||||
window.androidPermalink = function() {
|
||||
if(typeof android === 'undefined' || !android || !android.copy)
|
||||
return true; // i.e. execute other actions
|
||||
|
||||
var center = map.getCenter();
|
||||
android.intentPosLink(center.lat, center.lng, map.getZoom(), "Intel Map", false);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
window.getPortalDataZoom = function() {
|
||||
var mapZoom = map.getZoom();
|
||||
|
||||
// make sure we're dealing with an integer here
|
||||
// (mobile: a float somehow gets through in some cases!)
|
||||
var z = parseInt(mapZoom);
|
||||
|
||||
// limiting the mazimum zoom level for data retrieval reduces the number of requests at high zoom levels
|
||||
// (as all portal data is retrieved at z=17, why retrieve multiple z=18 tiles when fewer z=17 would do?)
|
||||
// very effective along with the new cache code
|
||||
if (z > 17) z=17;
|
||||
|
||||
//sanity check - should never happen
|
||||
if (z < 0) z=0;
|
||||
|
||||
return z;
|
||||
}
|
||||
|
||||
|
||||
window.getMinPortalLevelForZoom = function(z) {
|
||||
//based on code from stock gen_dashboard.js
|
||||
switch(z) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
return 8;
|
||||
case 4:
|
||||
case 5:
|
||||
return 7;
|
||||
case 6:
|
||||
case 7:
|
||||
return 6;
|
||||
case 8:
|
||||
return 5;
|
||||
case 9:
|
||||
case 10:
|
||||
return 4;
|
||||
case 11:
|
||||
case 12:
|
||||
return 3;
|
||||
case 13:
|
||||
case 14:
|
||||
return 2;
|
||||
case 15:
|
||||
case 16:
|
||||
return 1;
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
window.getMinPortalLevel = function() {
|
||||
var z = getPortalDataZoom();
|
||||
return getMinPortalLevelForZoom(z);
|
||||
}
|
||||
|
||||
// returns number of pixels left to scroll down before reaching the
|
||||
// bottom. Works similar to the native scrollTop function.
|
||||
window.scrollBottom = function(elm) {
|
||||
if(typeof elm === 'string') elm = $(elm);
|
||||
return elm.get(0).scrollHeight - elm.innerHeight() - elm.scrollTop();
|
||||
}
|
||||
|
||||
window.zoomToAndShowPortal = function(guid, latlng) {
|
||||
map.setView(latlng, 17);
|
||||
// if the data is available, render it immediately. Otherwise defer
|
||||
// until it becomes available.
|
||||
if(window.portals[guid])
|
||||
renderPortalDetails(guid);
|
||||
else
|
||||
urlPortal = guid;
|
||||
}
|
||||
|
||||
|
||||
String.prototype.capitalize = function() {
|
||||
return this.charAt(0).toUpperCase() + this.slice(1).toLowerCase();
|
||||
}
|
||||
|
||||
// http://stackoverflow.com/a/646643/1684530 by Bergi and CMS
|
||||
if (typeof String.prototype.startsWith !== 'function') {
|
||||
String.prototype.startsWith = function (str){
|
||||
return this.slice(0, str.length) === str;
|
||||
};
|
||||
}
|
||||
|
||||
// escape a javascript string, so quotes and backslashes are escaped with a backslash
|
||||
// (for strings passed as parameters to html onclick="..." for example)
|
||||
window.escapeJavascriptString = function(str) {
|
||||
return (str+'').replace(/[\\"']/g,'\\$&');
|
||||
}
|
||||
|
||||
//escape special characters, such as tags
|
||||
window.escapeHtmlSpecialChars = function(str) {
|
||||
var div = document.createElement(div);
|
||||
var text = document.createTextNode(str);
|
||||
div.appendChild(text);
|
||||
return div.innerHTML;
|
||||
}
|
||||
|
||||
window.prettyEnergy = function(nrg) {
|
||||
return nrg> 1000 ? Math.round(nrg/1000) + ' k': nrg;
|
||||
}
|
||||
|
||||
window.setPermaLink = function(elm) {
|
||||
var c = map.getCenter();
|
||||
var lat = Math.round(c.lat*1E6)/1E6;
|
||||
var lng = Math.round(c.lng*1E6)/1E6;
|
||||
var qry = 'll='+lat+','+lng+'&z=' + map.getZoom();
|
||||
$(elm).attr('href', '/intel?' + qry);
|
||||
}
|
||||
|
||||
window.uniqueArray = function(arr) {
|
||||
return $.grep(arr, function(v, i) {
|
||||
return $.inArray(v, arr) === i;
|
||||
});
|
||||
}
|
||||
|
||||
window.genFourColumnTable = function(blocks) {
|
||||
var t = $.map(blocks, function(detail, index) {
|
||||
if(!detail) return '';
|
||||
if(index % 2 === 0)
|
||||
return '<tr><td>'+detail[1]+'</td><th>'+detail[0]+'</th>';
|
||||
else
|
||||
return ' <th>'+detail[0]+'</th><td>'+detail[1]+'</td></tr>';
|
||||
}).join('');
|
||||
if(t.length % 2 === 1) t + '<td></td><td></td></tr>';
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
// converts given text with newlines (\n) and tabs (\t) to a HTML
|
||||
// table automatically.
|
||||
window.convertTextToTableMagic = function(text) {
|
||||
// check if it should be converted to a table
|
||||
if(!text.match(/\t/)) return text.replace(/\n/g, '<br>');
|
||||
|
||||
var data = [];
|
||||
var columnCount = 0;
|
||||
|
||||
// parse data
|
||||
var rows = text.split('\n');
|
||||
$.each(rows, function(i, row) {
|
||||
data[i] = row.split('\t');
|
||||
if(data[i].length > columnCount) columnCount = data[i].length;
|
||||
});
|
||||
|
||||
// build the table
|
||||
var table = '<table>';
|
||||
$.each(data, function(i, row) {
|
||||
table += '<tr>';
|
||||
$.each(data[i], function(k, cell) {
|
||||
var attributes = '';
|
||||
if(k === 0 && data[i].length < columnCount) {
|
||||
attributes = ' colspan="'+(columnCount - data[i].length + 1)+'"';
|
||||
}
|
||||
table += '<td'+attributes+'>'+cell+'</td>';
|
||||
});
|
||||
table += '</tr>';
|
||||
});
|
||||
table += '</table>';
|
||||
return table;
|
||||
}
|
||||
|
||||
// Given 3 sets of points in an array[3]{lat, lng} returns the area of the triangle
|
||||
window.calcTriArea = function(p) {
|
||||
return Math.abs((p[0].lat*(p[1].lng-p[2].lng)+p[1].lat*(p[2].lng-p[0].lng)+p[2].lat*(p[0].lng-p[1].lng))/2);
|
||||
}
|
||||
|
||||
// Update layerGroups display status to window.overlayStatus and localStorage 'ingress.intelmap.layergroupdisplayed'
|
||||
window.updateDisplayedLayerGroup = function(name, display) {
|
||||
overlayStatus[name] = display;
|
||||
localStorage['ingress.intelmap.layergroupdisplayed'] = JSON.stringify(overlayStatus);
|
||||
}
|
||||
|
||||
// Read layerGroup status from window.overlayStatus if it was added to map,
|
||||
// read from cookie if it has not added to map yet.
|
||||
// return 'defaultDisplay' if both overlayStatus and cookie didn't have the record
|
||||
window.isLayerGroupDisplayed = function(name, defaultDisplay) {
|
||||
if(typeof(overlayStatus[name]) !== 'undefined') return overlayStatus[name];
|
||||
|
||||
convertCookieToLocalStorage('ingress.intelmap.layergroupdisplayed');
|
||||
var layersJSON = localStorage['ingress.intelmap.layergroupdisplayed'];
|
||||
if(!layersJSON) return defaultDisplay;
|
||||
|
||||
var layers = JSON.parse(layersJSON);
|
||||
// keep latest overlayStatus
|
||||
overlayStatus = $.extend(layers, overlayStatus);
|
||||
if(typeof(overlayStatus[name]) === 'undefined') return defaultDisplay;
|
||||
return overlayStatus[name];
|
||||
}
|
||||
|
||||
window.addLayerGroup = function(name, layerGroup, defaultDisplay) {
|
||||
if(isLayerGroupDisplayed(name, defaultDisplay)) map.addLayer(layerGroup);
|
||||
layerChooser.addOverlay(layerGroup, name);
|
||||
}
|
||||
|
||||
window.clampLat = function(lat) {
|
||||
// the map projection used does not handle above approx +- 85 degrees north/south of the equator
|
||||
if (lat > 85.051128)
|
||||
lat = 85.051128;
|
||||
else if (lat < -85.051128)
|
||||
lat = -85.051128;
|
||||
return lat;
|
||||
}
|
||||
|
||||
window.clampLng = function(lng) {
|
||||
if (lng > 179.999999)
|
||||
lng = 179.999999;
|
||||
else if (lng < -180.0)
|
||||
lng = -180.0;
|
||||
return lng;
|
||||
}
|
||||
|
||||
|
||||
window.clampLatLng = function(latlng) {
|
||||
return new L.LatLng ( clampLat(latlng.lat), clampLng(latlng.lng) );
|
||||
}
|
||||
|
||||
window.clampLatLngBounds = function(bounds) {
|
||||
return new L.LatLngBounds ( clampLatLng(bounds.getSouthWest()), clampLatLng(bounds.getNorthEast()) );
|
||||
}
|
Reference in New Issue
Block a user