diff --git a/assets/IITC.png b/assets/IITC.png new file mode 100755 index 00000000..d4c6ac5d Binary files /dev/null and b/assets/IITC.png differ diff --git a/assets/IITC.svg b/assets/IITC.svg new file mode 100755 index 00000000..ca2653f8 --- /dev/null +++ b/assets/IITC.svg @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/boot.js b/code/boot.js index caaad95f..2982bd34 100644 --- a/code/boot.js +++ b/code/boot.js @@ -119,7 +119,7 @@ window.setupMap = function() { //their usage policy has no limits (except required notification above 4000 tiles/sec - we're perhaps at 50 tiles/sec based on CloudMade stats) var mqSubdomains = [ 'otile1','otile2', 'otile3', 'otile4' ]; var mqTileUrlPrefix = window.location.protocol !== 'https:' ? 'http://{s}.mqcdn.com' : 'https://{s}-s.mqcdn.com'; - var mqMapOpt = {attribution: osmAttribution+', Tiles Courtesy of MapQuest', mazZoom: 18, detectRetena: true, subdomains: mqSubdomains}; + var mqMapOpt = {attribution: osmAttribution+', Tiles Courtesy of MapQuest', maxZoom: 18, detectRetena: true, subdomains: mqSubdomains}; var mqMap = new L.TileLayer(mqTileUrlPrefix+'/tiles/1.0.0/map/{z}/{x}/{y}.jpg',mqMapOpt); //MapQuest satellite coverage outside of the US is rather limited - so not really worth having as we have google as an option //var mqSatOpt = {attribution: 'Portions Courtesy NASA/JPL-Caltech and U.S. Depart. of Agriculture, Farm Service Agency', mazZoom: 18, detectRetena: true, subdomains: mqSubdomains}; @@ -127,10 +127,11 @@ window.setupMap = function() { var views = [ /*0*/ mqMap, - /*1*/ new L.Google('INGRESS'), - /*2*/ new L.Google('ROADMAP'), + /*1*/ new L.Google('INGRESS',{maxZoom:20}), + /*2*/ new L.Google('ROADMAP',{maxZoom:20}), /*3*/ new L.Google('SATELLITE',{maxZoom:20}), - /*4*/ new L.Google('HYBRID',{maxZoom:20}) + /*4*/ new L.Google('HYBRID',{maxZoom:20}), + /*5*/ new L.Google('TERRAIN',{maxZoom:15}) ]; @@ -161,7 +162,8 @@ window.setupMap = function() { 'Default Ingress Map': views[1], 'Google Roads': views[2], 'Google Satellite': views[3], - 'Google Hybrid': views[4] + 'Google Hybrid': views[4], + 'Google Terrain': views[5] }, addLayers); map.addControl(window.layerChooser); diff --git a/code/map_data.js b/code/map_data.js index 91c6b4f0..89e8eeb2 100644 --- a/code/map_data.js +++ b/code/map_data.js @@ -12,34 +12,30 @@ window.requestData = function() { requests.abort(); cleanUp(); - var magic = convertCenterLat(map.getCenter().lat); - var R = calculateR(magic); - var bounds = map.getBounds(); - // convert to point values - topRight = convertLatLngToPoint(bounds.getNorthEast(), magic, R); - bottomLeft = convertLatLngToPoint(bounds.getSouthWest() , magic, R); - // how many quadrants intersect the current view? - quadsX = Math.abs(bottomLeft.x - topRight.x); - quadsY = Math.abs(bottomLeft.y - topRight.y); + + var x1 = lngToTile(bounds.getNorthWest().lng, map.getZoom()); + var x2 = lngToTile(bounds.getNorthEast().lng, map.getZoom()); + var y1 = latToTile(bounds.getNorthWest().lat, map.getZoom()); + var y2 = latToTile(bounds.getSouthWest().lat, map.getZoom()); // will group requests by second-last quad-key quadrant tiles = {}; // walk in x-direction, starts right goes left - for(var i = 0; i <= quadsX; i++) { - var x = Math.abs(topRight.x - i); - var qk = pointToQuadKey(x, topRight.y); - var bnds = convertPointToLatLng(x, topRight.y, magic, R); - if(!tiles[qk.slice(0, -1)]) tiles[qk.slice(0, -1)] = []; - tiles[qk.slice(0, -1)].push(generateBoundsParams(qk, bnds)); - - // walk in y-direction, starts top, goes down - for(var j = 1; j <= quadsY; j++) { - var qk = pointToQuadKey(x, topRight.y + j); - var bnds = convertPointToLatLng(x, topRight.y + j, magic, R); - if(!tiles[qk.slice(0, -1)]) tiles[qk.slice(0, -1)] = []; - tiles[qk.slice(0, -1)].push(generateBoundsParams(qk, bnds)); + for (var x = x1; x <= x2; x++) { + for (var y = y1; y <= y2; y++) { + var tile_id = pointToTileId(map.getZoom(), x, y); + var bucket = Math.floor(x / 2) + "" + Math.floor(y / 2); + if (!tiles[bucket]) + tiles[bucket] = []; + tiles[bucket].push(generateBoundsParams( + tile_id, + tileToLat(y + 1, map.getZoom()), + tileToLng(x, map.getZoom()), + tileToLat(y, map.getZoom()), + tileToLng(x + 1, map.getZoom()) + )); } } @@ -78,7 +74,7 @@ window.handleDataResponse = function(data, textStatus, jqXHR) { // portals can be brought to front, this costs extra time. They need // to be in the foreground, or they cannot be clicked. See // https://github.com/Leaflet/Leaflet/issues/185 - var ppp = []; + var ppp = {}; var p2f = {}; $.each(m, function(qk, val) { $.each(val.deletedGameEntityGuids || [], function(ind, guid) { @@ -115,7 +111,7 @@ window.handleDataResponse = function(data, textStatus, jqXHR) { ent[2].imageByUrl = {'imageUrl': DEFAULT_PORTAL_IMG}; } - ppp.push(ent); // delay portal render + ppp[ent[0]] = ent; // delay portal render } else if(ent[2].edge !== undefined) { renderLink(ent); } else if(ent[2].capturedRegion !== undefined) { @@ -132,6 +128,25 @@ window.handleDataResponse = function(data, textStatus, jqXHR) { }); $.each(ppp, function(ind, portal) { + if ('portalV2' in portal[2] && 'linkedEdges' in portal[2].portalV2) { + $.each(portal[2].portalV2.linkedEdges, function (ind, edge) { + if (!ppp[edge.otherPortalGuid]) + return; + renderLink([ + edge.edgeGuid, + portal[1], + { + "controllingTeam": portal[2].controllingTeam, + "edge": { + "destinationPortalGuid": edge.isOrigin ? ppp[edge.otherPortalGuid][0] : portal[0], + "destinationPortalLocation": edge.isOrigin ? ppp[edge.otherPortalGuid][2].locationE6 : portal[2].locationE6, + "originPortalGuid": !edge.isOrigin ? ppp[edge.otherPortalGuid][0] : portal[0], + "originPortalLocation": !edge.isOrigin ? ppp[edge.otherPortalGuid][2].locationE6 : portal[2].locationE6 + } + } + ]); + }); + } if(portal[2].portalV2['linkedFields'] === undefined) { portal[2].portalV2['linkedFields'] = []; } diff --git a/code/map_data_calc_tools.js b/code/map_data_calc_tools.js index eca1b7e9..98535759 100644 --- a/code/map_data_calc_tools.js +++ b/code/map_data_calc_tools.js @@ -1,65 +1,45 @@ - // MAP DATA REQUEST CALCULATORS ////////////////////////////////////// // Ingress Intel splits up requests for map data (portals, links, // fields) into tiles. To get data for the current viewport (i.e. what // is currently visible) it first calculates which tiles intersect. // For all those tiles, it then calculates the lat/lng bounds of that // tile and a quadkey. Both the bounds and the quadkey are “somewhat” -// required to get complete data. No idea how the projection between -// lat/lng and tiles works. -// What follows now are functions that allow conversion between tiles -// and lat/lng as well as calculating the quad key. The variable names -// may be misleading. -// The minified source for this code was in gen_dashboard.js after the -// “// input 89” line (alternatively: the class was called “Xe”). +// required to get complete data. +// +// Convertion functions courtesy of +// http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames -window.convertCenterLat = function(centerLat) { - return Math.round(256 * 0.9999 * Math.abs(1 / Math.cos(centerLat * DEG2RAD))); +window.lngToTile = function(lng, zoom) { + return Math.floor((lng + 180) / 360 * Math.pow(2, zoom)); } -window.calculateR = function(convCenterLat) { - return 1 << window.map.getZoom() - (convCenterLat / 256 - 1); +window.latToTile = function(lat, zoom) { + 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)); } -window.convertLatLngToPoint = function(latlng, magic, R) { - var x = (magic + latlng.lng * magic / 180)*R; - var l = Math.sin(latlng.lat * DEG2RAD); - var y = (magic + Math.log((1+l)/(1-l)) * -(magic / (2*Math.PI)))*R; - return {x: Math.floor(x/magic), y: Math.floor(y/magic)}; +window.tileToLng = function(x, zoom) { + return x / Math.pow(2, zoom) * 360 - 180; } -window.convertPointToLatLng = function(x, y, magic, R) { - var e = {}; - e.sw = { - // orig function put together from all over the place - // lat: (2 * Math.atan(Math.exp((((y + 1) * magic / R) - (magic/ 2)) / (-1*(magic / (2 * Math.PI))))) - Math.PI / 2) / (Math.PI / 180), - // shortened version by your favorite algebra program. - lat: (360*Math.atan(Math.exp(Math.PI - Math.PI*(y+1)/R)))/Math.PI - 90, - lng: 180*x/R-180 - }; - e.ne = { - //lat: (2 * Math.atan(Math.exp(((y * magic / R) - (magic/ 2)) / (-1*(magic / (2 * Math.PI))))) - Math.PI / 2) / (Math.PI / 180), - lat: (360*Math.atan(Math.exp(Math.PI - Math.PI*y/R)))/Math.PI - 90, - lng: 180*(x+1)/R-180 - }; - return e; +window.tileToLat = function(y, zoom) { + var n = Math.PI - 2 * Math.PI * y / Math.pow(2, zoom); + return 180 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))); } -// calculates the quad key for a given point. The point is not(!) in -// lat/lng format. -window.pointToQuadKey = function(x, y) { - return window.map.getZoom() + "_" + x + "_" + y; +window.pointToTileId = function(zoom, x, y) { + return zoom + "_" + x + "_" + y; } -// given quadkey and bounds, returns the format as required by the +// given tile id and bounds, returns the format as required by the // Ingress API to request map data. -window.generateBoundsParams = function(quadkey, bounds) { +window.generateBoundsParams = function(tile_id, minLat, minLng, maxLat, maxLng) { return { - id: quadkey, - qk: quadkey, - minLatE6: Math.round(bounds.sw.lat * 1E6), - minLngE6: Math.round(bounds.sw.lng * 1E6), - maxLatE6: Math.round(bounds.ne.lat * 1E6), - maxLngE6: Math.round(bounds.ne.lng * 1E6) + id: tile_id, + qk: tile_id, + minLatE6: Math.round(minLat * 1E6), + minLngE6: Math.round(minLng * 1E6), + maxLatE6: Math.round(maxLat * 1E6), + maxLngE6: Math.round(maxLng * 1E6) }; } diff --git a/code/utils_misc.js b/code/utils_misc.js index 3b8be358..6a5b1e76 100644 --- a/code/utils_misc.js +++ b/code/utils_misc.js @@ -137,7 +137,7 @@ window.showPortalPosLinks = function(lat, lng, name) { portal_name = encodeURIComponent(' (' + name + ')'); } if (typeof android !== 'undefined' && android && android.intentPosLink) { - android.intentPosLink(window.location.protocol + '//maps.google.com/?q='+lat+','+lng); + android.intentPosLink(lat, lng, portal_name); } else { var qrcode = '
'; var script = ''; @@ -202,8 +202,8 @@ window.renderLimitReached = function(ratio) { window.getMinPortalLevel = function() { var z = map.getZoom(); - if(z >= 16) return 0; - var conv = ['impossible', 8,7,7,6,6,5,5,4,4,3,3,2,2,1,1]; + if(z >= 17) return 0; + var conv = ['impossible', 8,8,8,7,7,6,6,5,4,4,3,3,2,2,1,1]; var minLevelByRenderLimit = portalRenderLimit.getMinLevel(); var result = minLevelByRenderLimit > conv[z] ? minLevelByRenderLimit @@ -233,6 +233,7 @@ window.getTypeByGuid = function(guid) { // portals end in “.11” or “.12“, links in “.9", fields in “.b” // .11 == portals // .12 == portals + // .16 == portals // .9 == links // .b == fields // .c == player/creator @@ -246,6 +247,7 @@ window.getTypeByGuid = function(guid) { switch(guid.slice(33)) { case '11': case '12': + case '16': return TYPE_PORTAL; case '9': diff --git a/main.js b/main.js index f87807ad..3bebd816 100644 --- a/main.js +++ b/main.js @@ -1,7 +1,7 @@ // ==UserScript== // @id ingress-intel-total-conversion@jonatkins // @name IITC: Ingress intel map total conversion -// @version 0.11.0.@@DATETIMEVERSION@@ +// @version 0.11.2.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ // @downloadURL @@DOWNLOADURL@@ diff --git a/mobile/AndroidManifest.xml b/mobile/AndroidManifest.xml index 844d7462..472be5e6 100644 --- a/mobile/AndroidManifest.xml +++ b/mobile/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="12" + android:versionName="0.3.1" > '; + } else { + title += 'Level unknown' } } @@ -370,7 +371,8 @@ window.plugin.playerTracker.centerMapOnUser = function(nick) { return false; } - map.setView(position, map.getZoom()); + if(window.isSmartphone()) window.smartphone.mapButton.click(); + window.map.setView(position, map.getZoom()); } window.plugin.playerTracker.onNicknameClicked = function(info) { diff --git a/plugins/portals-list.user.js b/plugins/portals-list.user.js index 37997cc2..4b4bfbd5 100644 --- a/plugins/portals-list.user.js +++ b/plugins/portals-list.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @id iitc-plugin-portals-list@teo96 // @name IITC plugin: show list of portals -// @version 0.0.10.@@DATETIMEVERSION@@ +// @version 0.0.11.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ // @downloadURL @@DOWNLOADURL@@ @@ -13,6 +13,8 @@ // ==/UserScript== /* whatsnew +* 0.0.11: Add nominal energy column and # links, fix sort bug when opened even amounts of times, nits +* 0.0.10: Fixed persistent css problem with alert * 0.0.9 : bugs hunt * 0.0.8 : Aborted to avoid problems with Niantic (export portals informations as csv or kml file) * 0.0.7 : more informations avalaible via tooltips (who deployed, energy, ...), new E/AP column @@ -45,328 +47,239 @@ window.plugin.portalslist.resP = 0; window.plugin.portalslist.filter=0; //fill the listPortals array with portals avalaible on the map (level filtered portals will not appear in the table) -window.plugin.portalslist.getPortals = function(){ - //filter : 0 = All, 1 = Res, 2 = Enl - //console.log('** getPortals'); - var retval=false; - - window.plugin.portalslist.listPortals = []; - //get portals informations from IITC - $.each(window.portals, function(i, portal) { - - retval=true; - var d = portal.options.details; - var name = d.portalV2.descriptiveText.TITLE; - var address = d.portalV2.descriptiveText.ADDRESS; - var img = d.imageByUrl && d.imageByUrl.imageUrl ? d.imageByUrl.imageUrl : DEFAULT_PORTAL_IMG; - var team = portal.options.team; - switch (team){ - case 1 : - window.plugin.portalslist.resP++; - break; - case 2 : - window.plugin.portalslist.enlP++; - break; - } - var level = getPortalLevel(d).toFixed(2); - var guid = portal.options.guid; - - - //get resonators informations - var resonators = []; // my local resonator array : reso level, reso deployed by, distance to portal, energy total, max - var energy = 0; - var maxenergy=0; - $.each(portal.options.details.resonatorArray.resonators, function(ind, reso) { - if(reso) { - resonators[ind] = [reso.level, window.getPlayerName(reso.ownerGuid), reso.distanceToPortal, reso.energyTotal, RESO_NRG[reso.level]]; - energy += reso.energyTotal; - maxenergy += RESO_NRG[reso.level]; - } else { resonators[ind] = [0,'',0,0,0]; } - }); - // Sort resonators array by resonator level - resonators.sort(function (a, b) {return b[0] - a[0]}); - - //get shield informations - var shields = []; - $.each(d.portalV2.linkedModArray, function(ind, mod) { - if (mod) - //shields[ind] = mod.rarity.capitalize().replace('_', ' '); - shields[ind] = [mod.rarity.substr(0,1).capitalize(), getPlayerName(mod.installingUser)] ; - else - shields[ind] = ['', '']; - }); - - var APgain= getAttackApGain(d).enemyAp; - var thisPortal = {'portal':d,'name':name,'team':team,'level':level,'guid':guid, 'resonators':resonators,'energyratio' : Math.floor(energy/maxenergy*100), 'shields':shields, 'APgain':APgain, 'EAP' : (energy/APgain).toFixed(2), 'energy': energy, 'maxenergy':maxenergy, 'lat':portal._latlng.lat, 'lng':portal._latlng.lng, 'address': address, 'img' : img}; - window.plugin.portalslist.listPortals.push(thisPortal); +window.plugin.portalslist.getPortals = function() { + //filter : 0 = All, 1 = Res, 2 = Enl + //console.log('** getPortals'); + var retval=false; + + window.plugin.portalslist.listPortals = []; + //get portals informations from IITC + $.each(window.portals, function(i, portal) { + + retval=true; + var d = portal.options.details; + var name = d.portalV2.descriptiveText.TITLE; + var address = d.portalV2.descriptiveText.ADDRESS; + var img = d.imageByUrl && d.imageByUrl.imageUrl ? d.imageByUrl.imageUrl : DEFAULT_PORTAL_IMG; + var team = portal.options.team; + switch (team){ + case 1 : + window.plugin.portalslist.resP++; + break; + case 2 : + window.plugin.portalslist.enlP++; + break; + } + var level = getPortalLevel(d).toFixed(2); + var guid = portal.options.guid; + + + //get resonators informations + var resonators = []; // my local resonator array : reso level, reso deployed by, distance to portal, energy total, max + var energy = 0; + var maxenergy=0; + $.each(portal.options.details.resonatorArray.resonators, function(ind, reso) { + if(reso) { + resonators[ind] = [reso.level, window.getPlayerName(reso.ownerGuid), reso.distanceToPortal, reso.energyTotal, RESO_NRG[reso.level]]; + energy += reso.energyTotal; + maxenergy += RESO_NRG[reso.level]; + } else { resonators[ind] = [0,'',0,0,0]; } }); - - return retval; + // Sort resonators array by resonator level + resonators.sort(function (a, b) {return b[0] - a[0]}); + + //get shield informations + var shields = []; + $.each(d.portalV2.linkedModArray, function(ind, mod) { + if (mod) { + //shields[ind] = mod.rarity.capitalize().replace('_', ' '); + shields[ind] = [mod.rarity.substr(0,1).capitalize(), getPlayerName(mod.installingUser)] ; + } else { + shields[ind] = ['', '']; + } + }); + + var APgain= getAttackApGain(d).enemyAp; + var thisPortal = {'portal': d, 'name': name, 'team': team, 'level': level, 'guid': guid, 'resonators': resonators, 'energyratio': maxenergy ? Math.floor(energy/maxenergy*100) : 0, 'shields': shields, 'APgain': APgain, 'EAP': (energy/APgain).toFixed(2), 'energy': energy, 'maxenergy': maxenergy, 'links': d.portalV2.linkedEdges.length, 'lat': portal._latlng.lat, 'lng': portal._latlng.lng, 'address': address, 'img': img}; + window.plugin.portalslist.listPortals.push(thisPortal); + }); + + return retval; } -window.plugin.portalslist.displayPL = function() { - // debug tools - //var start = new Date().getTime(); - //console.log('***** Start ' + start); - - var html = ''; - window.plugin.portalslist.sortOrder=-1; - window.plugin.portalslist.enlP = 0; - window.plugin.portalslist.resP = 0; +window.plugin.portalslist.displayPL = function() { + // debug tools + //var start = new Date().getTime(); + //console.log('***** Start ' + start); - if (window.plugin.portalslist.getPortals()) { - html += window.plugin.portalslist.portalTable('level', window.plugin.portalslist.sortOrder,window.plugin.portalslist.filter); - } else { - html = '
Nothing to Show !
'; - }; - alert('
' + html + '
', true, function() {$(".ui-dialog").removeClass('ui-dialog-portalslist');}); - $(".ui-dialog").addClass('ui-dialog-portalslist'); + var html = ''; + window.plugin.portalslist.sortOrder=-1; + window.plugin.portalslist.enlP = 0; + window.plugin.portalslist.resP = 0; + + if (window.plugin.portalslist.getPortals()) { + html += window.plugin.portalslist.portalTable('level', window.plugin.portalslist.sortOrder,window.plugin.portalslist.filter); + } else { + html = '
Nothing to Show !
'; + }; + alert('
' + html + '
', true, function() { + $(".ui-dialog").removeClass('ui-dialog-portalslist'); + $(document).off('.portalslist'); + }); + $(".ui-dialog").addClass('ui-dialog-portalslist'); + + // Setup sorting + $(document).on('click.portalslist', '#portalslist table th', function() { + $('#portalslist').html(window.plugin.portalslist.portalTable($(this).data('sort'),window.plugin.portalslist.sortOrder,window.plugin.portalslist.filter)); + }); + $(document).on('click.portalslist', '#portalslist .filterAll', function() { + $('#portalslist').html(window.plugin.portalslist.portalTable($(this).data('sort'),window.plugin.portalslist.sortOrder,0)); + }); + $(document).on('click.portalslist', '#portalslist .filterRes', function() { + $('#portalslist').html(window.plugin.portalslist.portalTable($(this).data('sort'),window.plugin.portalslist.sortOrder,1)); + }); + $(document).on('click.portalslist', '#portalslist .filterEnl', function() { + $('#portalslist').html(window.plugin.portalslist.portalTable($(this).data('sort'),window.plugin.portalslist.sortOrder,2)); + }); - // Setup sorting - $(document).on('click', '#portalslist table th', function() { - $('#portalslist').html(window.plugin.portalslist.portalTable($(this).data('sort'),window.plugin.portalslist.sortOrder,window.plugin.portalslist.filter)); - }); - $(document).on('click', '#portalslist .filterAll', function() { - $('#portalslist').html(window.plugin.portalslist.portalTable($(this).data('sort'),window.plugin.portalslist.sortOrder,0)); - }); - $(document).on('click', '#portalslist .filterRes', function() { - $('#portalslist').html(window.plugin.portalslist.portalTable($(this).data('sort'),window.plugin.portalslist.sortOrder,1)); - }); - $(document).on('click', '#portalslist .filterEnl', function() { - $('#portalslist').html(window.plugin.portalslist.portalTable($(this).data('sort'),window.plugin.portalslist.sortOrder,2)); - }); - - //debug tools - //end = new Date().getTime(); - //console.log('***** end : ' + end + ' and Elapse : ' + (end - start)); + //debug tools + //end = new Date().getTime(); + //console.log('***** end : ' + end + ' and Elapse : ' + (end - start)); } window.plugin.portalslist.portalTable = function(sortBy, sortOrder, filter) { - // sortOrder <0 ==> desc, >0 ==> asc, i use sortOrder * -1 to change the state - window.plugin.portalslist.filter=filter; - var portals=window.plugin.portalslist.listPortals; - - //Array sort - window.plugin.portalslist.listPortals.sort(function(a, b) { - var retVal = 0; - switch (sortBy) { - case 'names': - retVal = a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1; - break; - case 'r1': - retVal = b.resonators[0][0] - a.resonators[0][0]; - break; - case 'r2': - retVal = b.resonators[1][0] - a.resonators[1][0]; - break; - case 'r3': - retVal = b.resonators[2][0] - a.resonators[2][0]; - break; - case 'r4': - retVal = b.resonators[3][0] - a.resonators[3][0]; - break; - case 'r5': - retVal = b.resonators[4][0] - a.resonators[4][0]; - break; - case 'r6': - retVal = b.resonators[5][0] - a.resonators[5][0]; - break; - case 'r7': - retVal = b.resonators[6][0] - a.resonators[6][0]; - break; - case 'r8': - retVal = b.resonators[7][0] - a.resonators[7][0]; - break; - case 's1': - retVal = a.shields[0].toLowerCase() > b.shields[0].toLowerCase() ? -1 : 1; - break; - case 's2': - retVal = a.shields[1].toLowerCase() > b.shields[1].toLowerCase() ? -1 : 1; - break; - case 's3': - retVal = a.shields[2].toLowerCase() > b.shields[2].toLowerCase() ? -1 : 1; - break; - case 's4': - retVal = a.shields[3].toLowerCase() > b.shields[3].toLowerCase() ? -1 : 1; - break; - default: - retVal = b[sortBy] - a[sortBy]; - break; - } - if (sortOrder > 0) { retVal = -retVal} //thx @jonatkins - return retVal; - }); - - var sort = window.plugin.portalslist.portalTableSort; - var html = window.plugin.portalslist.stats(); - html += '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + ''; - - - $.each(portals, function(ind, portal) { - - if (filter === 0 || filter === portal.team){ - html += '' - + '' - + '' - + ''; - - $.each([0, 1, 2, 3 ,4 ,5 ,6 ,7], function(ind, slot) { - - var title = 'title="owner: ' + portal.resonators[slot][1] + '
' - + 'energy: ' + portal.resonators[slot][3] + ' / ' + portal.resonators[slot][4] + ' (' + Math.floor(portal.resonators[slot][3]/portal.resonators[slot][4]*100) + '%)
' - + 'distance: ' + portal.resonators[slot][2] + 'm'; - - html += ''; - - }); - - html += '' - + '' - + '' - + '' - + '' - + '' - + ''; - - html+= ''; - } - }); - html += '
PortalLevelTR1R2R3R4R5R6R7R8EnergyS1S2S3S4AP GainE/AP
' + window.plugin.portalslist.getPortalLink(portal.portal, portal.guid) + '' + portal.level + '' + portal.team + '' + portal.resonators[slot][0] + '' + portal.energyratio + '%' + portal.shields[0][0] + '' + portal.shields[1][0] + '' + portal.shields[2][0] + '' + portal.shields[3][0] + '' + portal.APgain + '' + portal.EAP + '
'; - - //html += window.plugin.portalslist.exportLinks(); - - html += '
Click on portals table headers to sort by that column. ' - + 'Click on All Portals, Resistant Portals, Enlightened Portals to filter
' - + 'Thanks to @vita10gy & @xelio for their IITC plugins who inspired me. A @teo96 production. Vive la Résistance !
'; + // sortOrder <0 ==> desc, >0 ==> asc, i use sortOrder * -1 to change the state + window.plugin.portalslist.filter=filter; + var portals=window.plugin.portalslist.listPortals; - window.plugin.portalslist.sortOrder = window.plugin.portalslist.sortOrder*-1; - return html; + //Array sort + window.plugin.portalslist.listPortals.sort(function(a, b) { + var retVal = 0; + switch (sortBy) { + case 'names': + retVal = a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1; + break; + case 'r1': + retVal = b.resonators[0][0] - a.resonators[0][0]; + break; + case 'r2': + retVal = b.resonators[1][0] - a.resonators[1][0]; + break; + case 'r3': + retVal = b.resonators[2][0] - a.resonators[2][0]; + break; + case 'r4': + retVal = b.resonators[3][0] - a.resonators[3][0]; + break; + case 'r5': + retVal = b.resonators[4][0] - a.resonators[4][0]; + break; + case 'r6': + retVal = b.resonators[5][0] - a.resonators[5][0]; + break; + case 'r7': + retVal = b.resonators[6][0] - a.resonators[6][0]; + break; + case 'r8': + retVal = b.resonators[7][0] - a.resonators[7][0]; + break; + case 's1': + retVal = a.shields[0].toLowerCase() > b.shields[0].toLowerCase() ? -1 : 1; + break; + case 's2': + retVal = a.shields[1].toLowerCase() > b.shields[1].toLowerCase() ? -1 : 1; + break; + case 's3': + retVal = a.shields[2].toLowerCase() > b.shields[2].toLowerCase() ? -1 : 1; + break; + case 's4': + retVal = a.shields[3].toLowerCase() > b.shields[3].toLowerCase() ? -1 : 1; + break; + default: + retVal = b[sortBy] - a[sortBy]; + break; + } + if (sortOrder > 0) retVal = -retVal; //thx @jonatkins + return retVal; + }); + + var sort = window.plugin.portalslist.portalTableSort; + var html = window.plugin.portalslist.stats(); + html += '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + ''; + + + $.each(portals, function(ind, portal) { + + if (filter === 0 || filter === portal.team) { + html += '' + + '' + + '' + + ''; + + var title; + var percent; + $.each([0, 1, 2, 3 ,4 ,5 ,6 ,7], function(ind, slot) { + percent = portal.resonators[slot][4] ? Math.floor(portal.resonators[slot][3]/portal.resonators[slot][4]*100) : 0; + title = 'title="owner: ' + portal.resonators[slot][1] + '
' + + 'energy: ' + portal.resonators[slot][3] + ' / ' + portal.resonators[slot][4] + ' (' + percent + '%)
' + + 'distance: ' + portal.resonators[slot][2] + 'm'; + + html += ''; + + }); + + html += '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + ''; + + html+= ''; + } + }); + html += '
PortalLevelTR1R2R3R4R5R6R7R8Energy%LinksS1S2S3S4AP GainE/AP
' + window.plugin.portalslist.getPortalLink(portal.portal, portal.guid) + '' + portal.level + '' + portal.team + '' + portal.resonators[slot][0] + '' + prettyEnergy(portal.energy) + '' + portal.energyratio + '%' + portal.links + '' + portal.shields[0][0] + '' + portal.shields[1][0] + '' + portal.shields[2][0] + '' + portal.shields[3][0] + '' + portal.APgain + '' + portal.EAP + '
'; + + html += '
Click on portals table headers to sort by that column. ' + + 'Click on All Portals, Resistant Portals, Enlightened Portals to filter
' + + 'Thanks to @vita10gy & @xelio for their IITC plugins who inspired me. A @teo96 production. Vive la Résistance !
'; + + window.plugin.portalslist.sortOrder = window.plugin.portalslist.sortOrder*-1; + return html; } window.plugin.portalslist.stats = function(sortBy) { - //console.log('** stats'); - var html = '' - + '' - + '' - + '' - + '' - + '
All Portals : (click to filter)' + window.plugin.portalslist.listPortals.length + 'Resistant Portals : ' + window.plugin.portalslist.resP +' (' + Math.floor(window.plugin.portalslist.resP/window.plugin.portalslist.listPortals.length*100) + '%)Enlightened Portals : '+ window.plugin.portalslist.enlP +' (' + Math.floor(window.plugin.portalslist.enlP/window.plugin.portalslist.listPortals.length*100) + '%)
'; - return html; -} - -//return Html generated to export links -window.plugin.portalslist.exportLinks = function(){ - var html=''; - var stamp = new Date().getTime(); - - html+='
' - + '' - + '
'; - return html; -} - -window.plugin.portalslist.export = function(fileformat){ - //alert('format :' + fileformat); - var file = ''; - var uri = ''; - - switch (fileformat) { - case 'csv': - file = window.plugin.portalslist.exportCSV(); - break; - case 'kml': - file = window.plugin.portalslist.exportKML(); - break; - } - - if (file !== '') { - //http://stackoverflow.com/questions/4639372/export-to-csv-in-jquery - var uri = 'data:application/' + fileformat + 'csv;charset=UTF-8,' + encodeURIComponent(file); - //window.open(uri); - } - return uri; -} -window.plugin.portalslist.exportCSV = function(){ - var csv = ''; - var filter = window.plugin.portalslist.filter; - var portals = window.plugin.portalslist.listPortals; - - //headers - csv += 'Portal\tLevel\tTeam\tR1\tR2\tR3\tR4\tR5\tR6\tR7\tR8\tEnergy\tS1\tS2\tS3\tS4\tAP Gain\tE/AP\tlat\tlong\n'; - - $.each(portals, function(ind, portal) { - - if (filter === 0 || filter === portal.team){ - csv += portal.name + '\t' - + portal.level + '\t' - + portal.team + '\t'; - - $.each([0, 1, 2, 3 ,4 ,5 ,6 ,7], function(ind, slot) { - csv += portal.resonators[slot][0] + '\t'; - }); - - csv += portal.energyratio + '\t' + portal.shields[0][0] + '\t' + portal.shields[1][0] + '\t' + portal.shields[2][0] + '\t' + portal.shields[3][0] + '\t' + portal.APgain + '\t' + portal.EAP + '\t'; - csv += portal.lat + '\t' + portal.lng; - csv += '\n'; - } - }); - - return csv; -} - -window.plugin.portalslist.exportKML = function(){ - var kml = ''; - var filter = window.plugin.portalslist.filter; - // all portals informations are avalaible in the listPortals array - var portals = window.plugin.portalslist.listPortals; - - //headers - kml = '\n' - + 'Ingress Export'; - - // define colored markers as style0 (neutral), style1 (Resistance), style2 (Enlight) - kml += '' - + '' - + '\n'; - - $.each(portals, function(ind, portal) { - // add the portal in the kml file only if part of the filter choice - if (filter === 0 || filter === portal.team){ - // description contain picture of the portal, address and link to the Intel map - var description = '
' + portal.address - + '
Link to Intel Map
' - + ']]>'; - - kml += 'L' + Math.floor(portal.level) + ' - ' + portal.name + '' - + '' + description + '' - + '#style' + portal.team + ''; - - //coordinates - kml += '' + portal.lng + ',' + portal.lat + ',0'; - kml += '\n'; - } - }); - kml += '
'; - return kml; + //console.log('** stats'); + var html = '' + + '' + + '' + + '' + + '' + + '
All Portals : (click to filter)' + window.plugin.portalslist.listPortals.length + 'Resistant Portals : ' + window.plugin.portalslist.resP +' (' + Math.floor(window.plugin.portalslist.resP/window.plugin.portalslist.listPortals.length*100) + '%)Enlightened Portals : '+ window.plugin.portalslist.enlP +' (' + Math.floor(window.plugin.portalslist.enlP/window.plugin.portalslist.listPortals.length*100) + '%)
'; + return html; } // A little helper functon so the above isn't so messy @@ -383,29 +296,29 @@ window.plugin.portalslist.portalTableSort = function(name, by) { // hover: show address // code from getPortalLink function by xelio from iitc: AP List - https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/ap-list.user.js window.plugin.portalslist.getPortalLink = function(portal,guid) { - - var latlng = [portal.locationE6.latE6/1E6, portal.locationE6.lngE6/1E6].join(); - var jsSingleClick = 'window.renderPortalDetails(\''+guid+'\');return false'; - var jsDoubleClick = 'window.zoomToAndShowPortal(\''+guid+'\', ['+latlng+']);return false'; - var perma = '/intel?latE6='+portal.locationE6.latE6+'&lngE6='+portal.locationE6.lngE6+'&z=17&pguid='+guid; - - //Use Jquery to create the link, which escape characters in TITLE and ADDRESS of portal - var a = $('',{ - "class": 'help', - text: portal.portalV2.descriptiveText.TITLE, - title: portal.portalV2.descriptiveText.ADDRESS, - href: perma, - onClick: jsSingleClick, - onDblClick: jsDoubleClick - })[0].outerHTML; - var div = '
'+a+'
'; - return div; + + var latlng = [portal.locationE6.latE6/1E6, portal.locationE6.lngE6/1E6].join(); + var jsSingleClick = 'window.renderPortalDetails(\''+guid+'\');return false'; + var jsDoubleClick = 'window.zoomToAndShowPortal(\''+guid+'\', ['+latlng+']);return false'; + var perma = '/intel?latE6='+portal.locationE6.latE6+'&lngE6='+portal.locationE6.lngE6+'&z=17&pguid='+guid; + + //Use Jquery to create the link, which escape characters in TITLE and ADDRESS of portal + var a = $('
',{ + "class": 'help', + text: portal.portalV2.descriptiveText.TITLE, + title: portal.portalV2.descriptiveText.ADDRESS, + href: perma, + onClick: jsSingleClick, + onDblClick: jsDoubleClick + })[0].outerHTML; + var div = '
'+a+'
'; + return div; } var setup = function() { - $('#toolbox').append('
Portals list'); - $('head').append('