diff --git a/code/artifact.js b/code/artifact.js index b5335b8f..b1ef4e03 100644 --- a/code/artifact.js +++ b/code/artifact.js @@ -35,23 +35,7 @@ window.artifact.requestData = function() { if (isIdle()) { artifact.idle = true; } else { - // new API available in stock (2015-05-21) - 'getArtifactPortals' - // stock still uses this one, and the new method doesn't yet return anything, but they might be changing things soon... -//2015-06-13 - stock intel update using the new API -//above method takes no params, returns a list of portals. however, no longer -//1. a distinction between target portals and artifact portals -//2. some shard details in the portal summary 'unknown12' variable -// a. no sign of fragment numbers in this summary data - only in portal details -// b. not sure how resistance/enlightened targets are identified. so far, most portals have -// "[[["lightman"]], []]" (fragment at portal?) -// aod two have -// "[[["lightman"]], [["lightman"]]]" -// best guess - first array is a list of artifact types (but not numbers) at a portal -// - second array is a list of the target types for a portal -// (so "[[[]], [["lightman"]]]" would be for a target without any fragments at it - - - window.postAjax('artifacts', {}, artifact.handleSuccess, artifact.handleError); + window.postAjax('getArtifactPortals', {}, artifact.handleSuccess, artifact.handleError); } } @@ -81,34 +65,14 @@ window.artifact.handleFailure = function(data) { window.artifact.processData = function(data) { - if (data.error || !data.artifacts) { - console.warn('Failed to find artifacts in artifact response'); + if (data.error || !data.result) { + console.warn('Failed to find result in getArtifactPortals response'); return; } artifact.clearData(); - $.each (data.artifacts, function(i,artData) { - // if we have no descriptions for a type, we don't know about it - if (!artifact.getArtifactDescriptions(artData.artifactId)) { - // jarvis and amar artifacts - fragmentInfos and targetInfos - // (future types? completely unknown at this time!) - console.warn('Note: unknown artifactId '+artData.artifactId+' - guessing how to handle it'); - } - - artifact.artifactTypes[artData.artifactId] = artData.artifactId; - - if (artData.fragmentInfos) { - artifact.processFragmentInfos (artData.artifactId, artData.fragmentInfos); - } - - if (artData.targetInfos) { - artifact.processTargetInfos (artData.artifactId, artData.targetInfos); - } - - // other data in future? completely unknown! - }); - + artifact.processResult(data.result); // redraw the artifact layer artifact.updateLayer(); @@ -117,38 +81,52 @@ window.artifact.processData = function(data) { window.artifact.clearData = function() { - artifact.portalInfo = {}; artifact.artifactTypes = {}; + + artifact.entities = []; } -window.artifact.processFragmentInfos = function (id, fragments) { - $.each(fragments, function(i, fragment) { - if (!artifact.portalInfo[fragment.portalGuid]) { - artifact.portalInfo[fragment.portalGuid] = { _entityData: fragment.portalInfo }; + +window.artifact.processResult = function (portals) { + // portals is an object, keyed from the portal GUID, containing the portal entity array + + for (var guid in portals) { + var ent = portals[guid]; + var data = decodeArray.portalSummary(ent); + + // we no longer know the faction for the target portals, and we don't know which fragment numbers are at the portals + // all we know, from the portal summary data, for each type of artifact, is that each artifact portal is + // - a target portal or not - no idea for which faction + // - has one (or more) fragments, or not + + if (!artifact.portalInfo[guid]) artifact.portalInfo[guid] = {}; + + // store the decoded data - needed for lat/lng for layer markers + artifact.portalInfo[guid]._data = data; + + for(var type in data.artifactBrief.target) { + if (!artifact.artifactTypes[type]) artifact.artifactTypes[type] = {}; + + if (!artifact.portalInfo[guid][type]) artifact.portalInfo[guid][type] = {}; + + artifact.portalInfo[guid][type].target = TEAM_NONE; // as we no longer know the team... } - if (!artifact.portalInfo[fragment.portalGuid][id]) artifact.portalInfo[fragment.portalGuid][id] = {}; + for(var type in data.artifactBrief.fragment) { + if (!artifact.artifactTypes[type]) artifact.artifactTypes[type] = {}; - if (!artifact.portalInfo[fragment.portalGuid][id].fragments) artifact.portalInfo[fragment.portalGuid][id].fragments = []; + if (!artifact.portalInfo[guid][type]) artifact.portalInfo[guid][type] = {}; - $.each(fragment.fragments, function(i,f) { - artifact.portalInfo[fragment.portalGuid][id].fragments.push(f); - }); - - }); -} - -window.artifact.processTargetInfos = function (id, targets) { - $.each(targets, function(i, target) { - if (!artifact.portalInfo[target.portalGuid]) { - artifact.portalInfo[target.portalGuid] = { _entityData: target.portalInfo }; + artifact.portalInfo[guid][type].fragments = true; //as we no longer have a list of the fragments there } - if (!artifact.portalInfo[target.portalGuid][id]) artifact.portalInfo[target.portalGuid][id] = {}; - artifact.portalInfo[target.portalGuid][id].target = target.team === 'RESISTANCE' ? TEAM_RES : TEAM_ENL; - }); + // let's pre-generate the entities needed to render the map - array of [guid, timestamp, ent_array] + artifact.entities.push ( [guid, data.timestamp, ent] ); + + } + } window.artifact.getArtifactTypes = function() { @@ -159,30 +137,9 @@ window.artifact.isArtifact = function(type) { return type in artifact.artifactTypes; } -window.artifact.getArtifactDescriptions = function(type) { - var descriptions = { - 'jarvis': { 'title': "Jarvis Shards", 'fragmentName': "shards" }, - 'amar': { 'title': "Amar Artifacts", 'fragmentName': "artifacts" }, - 'helios': { 'title': "Helios Artifacts", 'fragmentName': "artifacts" }, - 'shonin': { 'title': "Sh\u014Dnin Shards", 'fragmentName': "shards" }, - 'lightman': { 'title': "Lightman Shards", 'fragmentName': "shards" }, - }; - - return descriptions[type]; -} - // used to render portals that would otherwise be below the visible level window.artifact.getArtifactEntities = function() { - var entities = []; - - // create fake entities from the artifact data - $.each (artifact.portalInfo, function(guid,data) { - var timestamp = 0; // we don't have a valid timestamp - so let's use 0 - var ent = [ guid, timestamp, data._entityData ]; - entities.push(ent); - }); - - return entities; + return artifact.entities; } window.artifact.getInterestingPortals = function() { @@ -199,103 +156,72 @@ window.artifact.getPortalData = function(guid,artifactId) { return artifact.portalInfo[guid] && artifact.portalInfo[guid][artifactId]; } +// get the target(s) at a specified portal. returns 'false'y if the portal isn't a target +window.artifact.getPortalTarget = function(guid) { + targets = {}; + if (artifact.portalInfo[guid]) { + for (var type in artifact.artifactTypes) { + if (artifact.portalInfo[guid][type].target !== undefined) { + targets[type] = artifact.portalInfo[guid][type].target; + } + } + } + + return Object.keys(targets).length == 0 ? null : targets; + +} + window.artifact.updateLayer = function() { artifact._layer.clearLayers(); $.each(artifact.portalInfo, function(guid,data) { - var latlng = L.latLng ([data._entityData[2]/1E6, data._entityData[3]/1E6]); + var latlng = L.latLng ([data._data.latE6/1E6, data._data.lngE6/1E6]); - // jarvis shard icon - var iconUrl = undefined; - var iconSize = 0; - var opacity = 1.0; + $.each(data, function(type,detail) { - // redundant as of 2014-02-05 - jarvis shards removed - if (data.jarvis) { - if (data.jarvis.target) { - // target portal - show the target marker. use the count of fragments at the target to pick the right icon - it has segments that fill up + // we'll construct the URL form the type - stock seems to do that now - var count = data.jarvis.fragments ? data.jarvis.fragments.length : 0; + var iconUrl; + if (data[type].target !== undefined) { + // target portal + var iconUrl = '//commondatastorage.googleapis.com/ingress.com/img/map_icons/marker_images/'+type+'_shard_target.png' + var iconSize = 100/2; + var opacity = 1.0; + + var icon = L.icon({ + iconUrl: iconUrl, + iconSize: [iconSize,iconSize], + iconAnchor: [iconSize/2,iconSize/2], + className: 'no-pointer-events' // the clickable: false below still blocks events going through to the svg underneath + }); + + var marker = L.marker (latlng, {icon: icon, clickable: false, keyboard: false, opacity: opacity }); + + artifact._layer.addLayer(marker); + + } else if (data[type].fragments) { + // fragment(s) at portal + + var iconUrl = '//commondatastorage.googleapis.com/ingress.com/img/map_icons/marker_images/'+type+'_shard.png' + var iconSize = 60/2; + var opacity = 0.6; + + var icon = L.icon({ + iconUrl: iconUrl, + iconSize: [iconSize,iconSize], + iconAnchor: [iconSize/2,iconSize/2], + className: 'no-pointer-events' // the clickable: false below still blocks events going through to the svg underneath + }); + + var marker = L.marker (latlng, {icon: icon, clickable: false, keyboard: false, opacity: opacity }); + + artifact._layer.addLayer(marker); - iconUrl = '//commondatastorage.googleapis.com/ingress.com/img/map_icons/marker_images/jarvis_shard_target_'+count+'.png'; - iconSize = 100/2; // 100 pixels - half that size works better - } else if (data.jarvis.fragments) { - iconUrl = '//commondatastorage.googleapis.com/ingress.com/img/map_icons/marker_images/jarvis_shard.png'; - iconSize = 60/2; // 60 pixels - half that size works better - opacity = 0.6; // these often hide portals - let's make them semi transparent } - } - // 2014-02-06: a guess at whats needed for the new artifacts - if (data.amar) { - if (data.amar.target) { - // target portal - show the target marker. use the count of fragments at the target to pick the right icon - it has segments that fill up + }); //end $.each(data, function(type,detail) - var count = data.amar.fragments ? data.amar.fragments.length : 0; - - iconUrl = '//commondatastorage.googleapis.com/ingress.com/img/map_icons/marker_images/amar_shard_target_'+count+'.png'; - iconSize = 100/2; // 100 pixels - half that size works better - } else if (data.amar.fragments) { - iconUrl = '//commondatastorage.googleapis.com/ingress.com/img/map_icons/marker_images/amar_shard.png'; - iconSize = 60/2; // 60 pixels - half that size works better - opacity = 0.6; // these often hide portals - let's make them semi transparent - } - } - - // 2014-08-09 - helios artifacts. original guess was slightly wrong - if (data.helios) { - if (data.helios.target) { - // target portal - show the target marker. helios target marker doesn't fill like the earlier jarvis/amar targets - iconUrl = '//commondatastorage.googleapis.com/ingress.com/img/map_icons/marker_images/helios_shard_target.png'; - iconSize = 100/2; // 100 pixels - half that size works better - } else if (data.helios.fragments) { - iconUrl = '//commondatastorage.googleapis.com/ingress.com/img/map_icons/marker_images/helios_shard.png'; - iconSize = 60/2; // 60 pixels - half that size works better - opacity = 0.6; // these often hide portals - let's make them semi transparent - } - } - - // 2015-03-05 - shonin shards - if (data.shonin) { - if (data.shonin.target) { - // target portal - show the target marker. - iconUrl = '//commondatastorage.googleapis.com/ingress.com/img/map_icons/marker_images/shonin_shard_target.png'; - iconSize = 100/2; // 100 pixels - half that size works better - } else if (data.shonin.fragments) { - iconUrl = '//commondatastorage.googleapis.com/ingress.com/img/map_icons/marker_images/shonin_shard.png'; - iconSize = 60/2; // 60 pixels - half that size works better - opacity = 0.6; // these often hide portals - let's make them semi transparent - } - } - - // 2015-04-22 - lightman fragments (guessed) - if (data.lightman) { - if (data.lightman.target) { - // target portal - show the target marker. - iconUrl = '//commondatastorage.googleapis.com/ingress.com/img/map_icons/marker_images/lightman_shard_target.png'; - iconSize = 100/2; // 100 pixels - half that size works better - } else if (data.lightman.fragments) { - iconUrl = '//commondatastorage.googleapis.com/ingress.com/img/map_icons/marker_images/lightman_shard.png'; - iconSize = 60/2; // 60 pixels - half that size works better - opacity = 0.6; // these often hide portals - let's make them semi transparent - } - } - - if (iconUrl) { - var icon = L.icon({ - iconUrl: iconUrl, - iconSize: [iconSize,iconSize], - iconAnchor: [iconSize/2,iconSize/2], - className: 'no-pointer-events' // the clickable: false below still blocks events going through to the svg underneath - }); - - var marker = L.marker (latlng, {icon: icon, clickable: false, keyboard: false, opacity: opacity }); - - artifact._layer.addLayer(marker); - } else { - console.warn('Oops! no URL for artifact portal icon?!'); - } - }); + }); //end $.each(artifact.portalInfo, function(guid,data) } @@ -309,9 +235,9 @@ window.artifact.showArtifactList = function() { var first = true; $.each(artifact.artifactTypes, function(type,type2) { - var description = artifact.getArtifactDescriptions(type); - - var name = description ? description.title : ('unknown artifact type: '+type); + // no nice way to convert the Niantic internal name into the correct display name + // (we do get the description string once a portal with that shard type is selected - could cache that somewhere?) + var name = type.substr(0,1).toUpperCase() + type.substr(1) + ' shards'; if (!first) html += '
In Summer 2015, Niantic changed the data format for artifact portals. We no longer know:
" + + "You can select a portal and the detailed data contains the list of shard numbers, but there's still no" + + " more information on targets.
"; + dialog({ title: 'Artifacts', html: html, diff --git a/code/entity_decode.js b/code/entity_decode.js index edf2b5d5..5a6398f4 100644 --- a/code/entity_decode.js +++ b/code/entity_decode.js @@ -25,7 +25,33 @@ energy: arr[2], }; } - function parseArtifact(arr) { + function parseArtifactBrief(arr) { + if (arr === null) return null; + + // array index 0 is for fragments at the portal. index 1 is for target portals + // each of those is two dimensional - not sure why. part of this is to allow for multiple types of artifacts, + // with their own targets, active at once - but one level for the array is enough for that + + // making a guess - first level is for different artifact types, second index would allow for + // extra data for that artifact type + + function decodeArtifactArray(arr) { + var result = {}; + for (var i=0; i