move a bunch of plugins into a 'broken' subfolder, for now

this is a quick way to remove them from test builds as they're unlikely to be practical to fix for 0.16.0 release
This commit is contained in:
Jon Atkins
2013-11-30 06:06:29 +00:00
parent f899cdbe69
commit 1de7819982
17 changed files with 0 additions and 0 deletions

View File

@ -0,0 +1,141 @@
// ==UserScript==
// @id iitc-plugin-compute-ap-stats@Hollow011
// @name IITC plugin: Compute AP statistics
// @category Info
// @version 0.3.1.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Displays the per-team AP gains available in the current view.
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @grant none
// ==/UserScript==
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
// use own namespace for plugin
window.plugin.compAPStats = function() {};
window.plugin.compAPStats.setupCallback = function() {
// add a new div to the bottom of the sidebar and style it
$('#sidebar').append('<div id="available_ap_display"></div>');
$('#available_ap_display').css({'color':'#ffce00', 'font-size':'90%', 'padding':'4px 2px'});
// do an initial calc for sidebar sizing purposes
window.plugin.compAPStats.onPositionMove();
// make the value update when the map data updates
window.addHook('mapDataRefreshEnd', window.plugin.compAPStats.onPositionMove);
}
window.plugin.compAPStats.onPositionMove = function() {
var result = window.plugin.compAPStats.compAPStats();
$('#available_ap_display').html('Available AP in this area:<table>'
+ '<tr><td>Enlightened:</td><td style="text-align:right">' + digits(result[1]) + '</td></tr>'
+ '<tr><td>Resistance:</td><td style="text-align:right">' + digits(result[0]) + '</td></tr>'
+ '</table>');
}
window.plugin.compAPStats.missingResonatorAP = function(portal) {
var resAP = 0;
var missing_resonators = 0;
$.each(portal.resonatorArray.resonators, function(ind, reso) {
if(reso === null) {
missing_resonators++;
}
});
if(missing_resonators > 0) {
resAP = window.DEPLOY_RESONATOR * missing_resonators;
resAP += window.COMPLETION_BONUS;
}
return(resAP);
};
window.plugin.compAPStats.compAPStats = function() {
var totalAP_RES = 0;
var totalAP_ENL = 0;
var allResEdges = [];
var allResFields = [];
var allEnlEdges = [];
var allEnlFields = [];
var displayBounds = map.getBounds();
// Grab every portal in the viewable area and compute individual AP stats
$.each(window.portals, function(ind, portal) {
var d = portal.options.details;
// eliminate offscreen portals (selected, and in padding)
if(!displayBounds.contains(portal.getLatLng())) return true;
var portalStats = getAttackApGain(d);
var portalSum = portalStats.resoAp + portalStats.captureAp;
if (getTeam(d) === TEAM_ENL) {
totalAP_RES += portalSum;
$.each(d.portalV2.linkedEdges||[], function(ind, edge) {
if(!edge) return true;
allEnlEdges.push(edge.edgeGuid);
});
$.each(d.portalV2.linkedFields||[], function(ind, field) {
if(!field) return true;
allEnlFields.push(field);
});
totalAP_ENL += window.plugin.compAPStats.missingResonatorAP(d);
}
else if (getTeam(d) === TEAM_RES) {
totalAP_ENL += portalSum;
$.each(d.portalV2.linkedEdges||[], function(ind, edge) {
if(!edge) return true;
allResEdges.push(edge.edgeGuid);
});
$.each(d.portalV2.linkedFields||[], function(ind, field) {
if(!field) return true;
allResFields.push(field);
});
totalAP_RES += window.plugin.compAPStats.missingResonatorAP(d);
} else {
// it's a neutral portal, potential for both teams. by definition no fields or edges
totalAP_ENL += portalSum;
totalAP_RES += portalSum;
}
});
// Compute team field AP
allResFields = uniqueArray(allResFields);
totalAP_ENL += (allResFields.length * DESTROY_FIELD);
allEnlFields = uniqueArray(allEnlFields);
totalAP_RES += (allEnlFields.length * DESTROY_FIELD);
// Compute team Link AP
allResEdges = uniqueArray(allResEdges);
totalAP_ENL += (allResEdges.length * DESTROY_LINK);
allEnlEdges = uniqueArray(allEnlEdges);
totalAP_RES += (allEnlEdges.length * DESTROY_LINK);
return [totalAP_RES, totalAP_ENL];
}
var setup = function() {
window.plugin.compAPStats.setupCallback();
}
// PLUGIN END //////////////////////////////////////////////////////////
@@PLUGINEND@@

View File

@ -0,0 +1,811 @@
// ==UserScript==
// @id iitc-plugin-draw-resonators@xelio
// @name IITC plugin: Draw resonators
// @category Layer
// @version 0.4.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Draw resonators on map. With stylers to highlight resonators with specific criteria.
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @grant none
// ==/UserScript==
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
// use own namespace for plugin
window.plugin.drawResonators = function() {};
window.plugin.drawResonators.options;
window.plugin.drawResonators.render;
//////// Render for handling render of resonators ////////
// As long as 'window.Render.prototype.createPortalEntity' delete and recreate portal
// on any change of data, this resonator render should make resonator create and remove
// with portal correctly.
//
// Resonators will create when
// 1.Portal added to map
// 2.Zooming in to enable zoom level
//
// Resonators will remove when
// 1.Portal removed from map
// 2.Zooming out beyond enable zoom level
window.plugin.drawResonators.Render = function(options) {
this.enableZoomLevel = options['enableZoomLevel'];
this.useStyler = '';
this.stylers = {};
this.resonators = {};
this.resonatorLayerGroup = new L.LayerGroup();
this.addStyler(new window.plugin.drawResonators.Styler());
this.beforeZoomLevel = map.getZoom();
this.portalAdded = this.portalAdded.bind(this);
this.createResonatorEntities = this.createResonatorEntities.bind(this);
this.deleteResonatorEntities = this.deleteResonatorEntities.bind(this);
this.handleResonatorEntitiesBeforeZoom = this.handleResonatorEntitiesBeforeZoom.bind(this);
this.handleResonatorEntitiesAfterZoom = this.handleResonatorEntitiesAfterZoom.bind(this);
this.handleEnableZoomLevelChange = this.handleEnableZoomLevelChange.bind(this);
this.portalSelectionChange = this.portalSelectionChange.bind(this);
this.changeStyler = this.changeStyler.bind(this);
this.getStylersList = this.getStylersList.bind(this);
};
window.plugin.drawResonators.Render.prototype.registerHook = function() {
window.addHook('portalAdded', this.portalAdded);
window.addHook('portalSelected', this.portalSelectionChange);
window.map.on('zoomstart', this.handleResonatorEntitiesBeforeZoom);
window.map.on('zoomend', this.handleResonatorEntitiesAfterZoom);
}
window.plugin.drawResonators.Render.prototype.portalAdded = function(data) {
var marker = data.portal;
var render = this;
marker.on('add', function() {
render.createResonatorEntities(this); // the 'this' in here is the portal.
});
marker.on('remove', function() {
render.deleteResonatorEntities(this.options.guid); // the 'this' in here is the portal.
});
}
window.plugin.drawResonators.Render.prototype.createResonatorEntities = function(portal) {
// No need to check for existing resonators, as old resonators should be removed with the portal marker.
if(!this.isResonatorsShow()) return;
var portalDetails = portal.options.details;
var resonatorsWithConnector = new L.LayerGroup()
var portalLatLng = [portalDetails.locationE6.latE6/1E6, portalDetails.locationE6.lngE6/1E6];
var portalSelected = selectedPortal === portal.options.guid;
for(var i in portalDetails.resonatorArray.resonators) {
resoData = portalDetails.resonatorArray.resonators[i];
if(resoData === null) continue;
var resoLatLng = this.getResonatorLatLng(resoData.distanceToPortal, resoData.slot, portalLatLng);
var resoMarker = this.createResoMarker(resoData, resoLatLng, portalSelected);
var connMarker = this.createConnMarker(resoData, resoLatLng, portalLatLng, portalSelected);
resonatorsWithConnector.addLayer(resoMarker);
resonatorsWithConnector.addLayer(connMarker);
}
resonatorsWithConnector.options = {
details: portalDetails.resonatorArray.resonators,
guid: portal.options.guid
};
this.resonators[portal.options.guid] = resonatorsWithConnector;
this.resonatorLayerGroup.addLayer(resonatorsWithConnector);
// bring portal in front of resonator connector
portal.bringToFront();
}
window.plugin.drawResonators.Render.prototype.createResoMarker = function(resoData, resoLatLng, portalSelected) {
var resoProperty = this.getStyler().getResonatorStyle(resoData, portalSelected);
resoProperty.type = 'resonator';
resoProperty.details = resoData;
var reso = L.circleMarker(resoLatLng, resoProperty);
return reso;
}
window.plugin.drawResonators.Render.prototype.createConnMarker = function(resoData, resoLatLng, portalLatLng, portalSelected) {
var connProperty = this.getStyler().getConnectorStyle(resoData, portalSelected);
connProperty.type = 'connector';
connProperty.details = resoData;
var conn = L.polyline([portalLatLng, resoLatLng], connProperty);
return conn;
}
window.plugin.drawResonators.Render.prototype.getResonatorLatLng = function(dist, slot, portalLatLng) {
// offset in meters
var dn = dist*SLOT_TO_LAT[slot];
var de = dist*SLOT_TO_LNG[slot];
// Coordinate offset in radians
var dLat = dn/EARTH_RADIUS;
var dLon = de/(EARTH_RADIUS*Math.cos(Math.PI/180*portalLatLng[0]));
// OffsetPosition, decimal degrees
var lat0 = portalLatLng[0] + dLat * 180/Math.PI;
var lon0 = portalLatLng[1] + dLon * 180/Math.PI;
return [lat0, lon0];
}
window.plugin.drawResonators.Render.prototype.deleteResonatorEntities = function(portalGuid) {
if (!(portalGuid in this.resonators)) return;
var r = this.resonators[portalGuid];
this.resonatorLayerGroup.removeLayer(r);
delete this.resonators[portalGuid];
}
// Save zoom level before zoom, use to determine redraw of resonator
window.plugin.drawResonators.Render.prototype.handleResonatorEntitiesBeforeZoom = function() {
this.beforeZoomLevel = map.getZoom();
}
window.plugin.drawResonators.Render.prototype.handleResonatorEntitiesAfterZoom = function() {
if(!this.isResonatorsShow()) {
this.clearAllResonators();
return;
}
// Draw all resonators if they were not drawn
if(!this.isResonatorsShowBeforeZoom()) {
this.drawAllResonators();
}
}
window.plugin.drawResonators.Render.prototype.handleEnableZoomLevelChange = function(zoomLevel) {
this.enableZoomLevel = zoomLevel;
if(!this.isResonatorsShow()) {
this.clearAllResonators();
return;
}
// Draw all resonators if they were not drawn
if(!Object.keys(this.resonators).length > 0) {
this.drawAllResonators();
}
}
window.plugin.drawResonators.Render.prototype.clearAllResonators = function() {
this.resonatorLayerGroup.clearLayers();
this.resonators = {};
}
window.plugin.drawResonators.Render.prototype.drawAllResonators = function() {
var render = this;
// loop through level of portals, only draw if the portal is shown on map
for (var guid in window.portals) {
var portal = window.portals[guid];
// FIXME: need to find a proper way to check if a portal is added to the map without depending on leaflet internals
// (and without depending on portalsLayers either - that's IITC internal)
if (portal._map) {
render.createResonatorEntities(portal);
}
}
}
window.plugin.drawResonators.Render.prototype.portalSelectionChange = function(data) {
this.toggleSelectedStyle(data.selectedPortalGuid);
this.toggleSelectedStyle(data.unselectedPortalGuid);
}
window.plugin.drawResonators.Render.prototype.toggleSelectedStyle = function(portalGuid) {
if (!(portalGuid in this.resonators)) return;
var render = this;
var portalSelected = selectedPortal === portalGuid;
var r = this.resonators[portalGuid];
r.eachLayer(function(entity) {
var style;
if(entity.options.type === 'resonator') {
style = render.getStyler().getResonatorStyle(entity.options.details, portalSelected);
} else {
style = render.getStyler().getConnectorStyle(entity.options.details, portalSelected);
}
entity.setStyle(style);
});
}
window.plugin.drawResonators.Render.prototype.addStyler = function(styler) {
this.stylers[styler.name] = styler;
}
window.plugin.drawResonators.Render.prototype.getStylersList = function() {
return Object.keys(this.stylers);
}
window.plugin.drawResonators.Render.prototype.getStyler = function() {
var stylerName = this.useStyler in this.stylers ? this.useStyler : 'Default';
return this.stylers[stylerName];
}
// Change if styler need change, and redraw all resonators using new styler
window.plugin.drawResonators.Render.prototype.changeStyler = function(name) {
if (name === this.useStyler) return;
for(stylerName in this.stylers) {
if(stylerName === name) {
if(this.stylers[this.useStyler]) this.stylers[this.useStyler].onDisableFunc();
this.useStyler = stylerName;
this.stylers[this.useStyler].onEnableFunc();
this.clearAllResonators();
this.drawAllResonators();
return;
}
}
}
window.plugin.drawResonators.Render.prototype.refreshStyler = function() {
this.clearAllResonators();
this.drawAllResonators();
}
window.plugin.drawResonators.Render.prototype.isResonatorsShow = function() {
return map.getZoom() >= this.enableZoomLevel;
}
window.plugin.drawResonators.Render.prototype.isResonatorsShowBeforeZoom = function() {
return this.beforeZoomLevel >= this.enableZoomLevel;
}
//////// Styler for getting resonator and connector style ////////
window.plugin.drawResonators.Styler = function(options) {
options = options || {};
this.name = options['name'] || 'Default';
this.otherOptions = options['otherOptions'];
this.getResonatorStyle = options['resonatorStyleFunc'] || this.defaultResonatorStyle;
this.getConnectorStyle = options['connectorStyleFunc'] || this.defaultConnectorStyle;
this.onEnableFunc = options['onEnableFunc'] || function() {};
this.onDisableFunc = options['onDisableFunc'] || function() {};
}
window.plugin.drawResonators.Styler.prototype.DEFAULT_OPTIONS_RESONATOR_SELECTED = {
color: '#fff',
weight: 1.1,
radius: 4,
opacity: 1,
clickable: false};
window.plugin.drawResonators.Styler.prototype.DEFAULT_OPTIONS_RESONATOR_NON_SELECTED = {
color: '#aaa',
weight: 1,
radius: 3,
opacity: 1,
clickable: false};
window.plugin.drawResonators.Styler.prototype.DEFAULT_OPTIONS_RESONATOR_LINE_SELECTED = {
opacity: 0.7,
weight: 3,
color: '#FFA000',
dashArray: '0,10' + (new Array(25).join(',8,4')),
fill: false,
clickable: false};
window.plugin.drawResonators.Styler.prototype.DEFAULT_OPTIONS_RESONATOR_LINE_NON_SELECTED = {
opacity: 0.25,
weight: 2,
color: '#FFA000',
dashArray: '0,10' + (new Array(25).join(',8,4')),
fill: false,
clickable: false};
window.plugin.drawResonators.Styler.prototype.defaultResonatorStyle = function(resoDetail, selected) {
var resoSharedStyle = selected
? this.DEFAULT_OPTIONS_RESONATOR_SELECTED
: this.DEFAULT_OPTIONS_RESONATOR_NON_SELECTED;
var resoStyle = $.extend({
fillColor: COLORS_LVL[resoDetail.level],
fillOpacity: resoDetail.energyTotal/RESO_NRG[resoDetail.level],
}, resoSharedStyle);
return resoStyle;
}
window.plugin.drawResonators.Styler.prototype.defaultConnectorStyle = function(resoDetail, selected) {
var connStyle = selected
? this.DEFAULT_OPTIONS_RESONATOR_LINE_SELECTED
: this.DEFAULT_OPTIONS_RESONATOR_LINE_NON_SELECTED;
return connStyle;
}
//////// Options for storing and loading options ////////
window.plugin.drawResonators.Options = function() {
this._options = {};
this._callbacks = {};
}
window.plugin.drawResonators.Options.prototype.addCallback = function(name, callback) {
if (!this._callbacks[name]) {
this._callbacks[name] = [];
}
this._callbacks[name].push(callback);
}
window.plugin.drawResonators.Options.prototype.newOption = function(name, defaultValue) {
this._options[name] = this.loadLocal(this.getStorageKey(name), defaultValue)
}
window.plugin.drawResonators.Options.prototype.getOption = function(name) {
return this._options[name];
}
window.plugin.drawResonators.Options.prototype.removeOption = function(name) {
delete this._options[name];
delete this._callbacks[name];
}
window.plugin.drawResonators.Options.prototype.changeOption = function(name, value) {
if(!(name in this._options)) return false;
if(value === this._options[name]) return false;
this._options[name] = value;
this.storeLocal(this.getStorageKey(name), this._options[name]);
if (this._callbacks[name] !== null) {
for(var i in this._callbacks[name]) {
this._callbacks[name][i](value);
}
}
}
window.plugin.drawResonators.Options.prototype.getStorageKey = function(name) {
return 'plugin-drawResonators-option-' + name;
}
window.plugin.drawResonators.Options.prototype.loadLocal = function(key, defaultValue) {
var objectJSON = localStorage[key];
if(objectJSON) {
return JSON.parse(objectJSON);
} else {
return defaultValue;
}
}
window.plugin.drawResonators.Options.prototype.storeLocal = function(key, value) {
if(typeof(value) !== 'undefined' && value !== null) {
localStorage[key] = JSON.stringify(value);
} else {
localStorage.removeItem(key);
}
}
//////// Dialog
window.plugin.drawResonators.Dialog = function() {
this._dialogEntries = {};
}
window.plugin.drawResonators.Dialog.prototype.addLink = function() {
$('#toolbox').append('<a id="draw-reso-show-dialog" onclick="window.plugin.drawResonators.dialog.show();">Resonators</a> ');
}
window.plugin.drawResonators.Dialog.prototype.addEntry = function(name, dialogEntry) {
this._dialogEntries[name] = dialogEntry;
this.change();
}
window.plugin.drawResonators.Dialog.prototype.removeEntry = function(name) {
delete this._dialogEntries[name];
this.change();
}
window.plugin.drawResonators.Dialog.prototype.show = function() {
window.dialog({html: this.getDialogHTML(), title: 'Resonators', modal: true, id: 'draw-reso-setting'});
// Attach entries event
for(var name in this._dialogEntries) {
var events = this._dialogEntries[name].getOnEvents();
for(var i in events) {
var event = events[i];
$('#draw-reso-dialog').on(event.event, '#' + event.id, event.callback);
}
}
}
window.plugin.drawResonators.Dialog.prototype.change = function() {
if($('#draw-reso-dialog').length > 0) this.show();
}
window.plugin.drawResonators.Dialog.prototype.getDialogHTML = function() {
var html = '<div id="draw-reso-dialog">'
for(var name in this._dialogEntries) {
html += '<div>'
+ this._dialogEntries[name].getHTML()
+ '</div>';
}
html += '</div>';
return html;
}
//////// ListDialogEntry
window.plugin.drawResonators.ListDialogEntry = function(options) {
this._name = options['name'];
this._label = options['label'];
this._valueFunc = options['valueFunc'];
this._valuesList = options['valuesList'];
this._valuesListFunc = options['valuesListFunc'];
this._onChangeCallback = options['onChangeCallback'];
}
window.plugin.drawResonators.ListDialogEntry.prototype.getHTML = function() {
var curValue = this._valueFunc();
var valuesList = this._valuesList ? this._valuesList : this._valuesListFunc();
var html = '<label for="' + this.getSelectId() + '">'
+ this._label + ': '
+ '</label>'
+ '<select id="' + this.getSelectId() + '">';
var noLabel = valuesList instanceof Array;
for(var label in valuesList) {
var selected = valuesList[label] === curValue;
html += '<option value="' + valuesList[label] + '" '
+ (selected ? 'selected="selected"' : '')
+'>'
+ (noLabel ? valuesList[label] : label)
+ '</option>';
}
html += '</select>';
return html;
}
window.plugin.drawResonators.ListDialogEntry.prototype.getOnEvents = function() {
return [{'event': 'change',
'id': this.getSelectId(),
'callback': this._onChangeCallback
}];
}
window.plugin.drawResonators.ListDialogEntry.prototype.getSelectId = function() {
return 'draw-reso-option-' + this._name;
}
//////// TextboxDialogEntry
window.plugin.drawResonators.TextboxDialogEntry = function(options) {
this._name = options['name'];
this._label = options['label'];
this._valueFunc = options['valueFunc'];
this._onChangeCallback = options['onChangeCallback'];
}
window.plugin.drawResonators.TextboxDialogEntry.prototype.getHTML = function() {
var curValue = this._valueFunc();
var html = '<label for="' + this.getInputId() + '">'
+ this._label + ': '
+ '</label>'
+ '<input type="text" size="20" id="' + this.getInputId() + '" '
+ 'value="' + curValue + '" />';
return html;
}
window.plugin.drawResonators.TextboxDialogEntry.prototype.getOnEvents = function() {
return [{'event': 'change',
'id': this.getInputId(),
'callback': this._onChangeCallback
}];
}
window.plugin.drawResonators.TextboxDialogEntry.prototype.getInputId = function() {
return 'draw-reso-option-' + this._name;
}
window.plugin.drawResonators.setupStyler = function() {
var thisPlugin = window.plugin.drawResonators;
var highlightedReso = {color: '#fff', weight: 2, radius: 4, opacity: 1, clickable: false};
var normalReso = {color: '#aaa', weight: 1, radius: 3, opacity: 1, clickable: false};
var selectedReso = {color: '#eee', weight: 1.1, radius: 4, opacity: 1, clickable: false};
var highlightedConn = {opacity: 0.7, weight: 3, color: '#FFA000', dashArray: '0,10,999', color: '#FFA000', fill: false, clickable: false};
var normalConn = {opacity: 0.25, weight: 2, color: '#FFA000', dashArray: '0,10' + (new Array(25).join(',8,4')), fill: false, clickable: false};
var selectedConn = {opacity: 0.7, weight: 3, color: '#FFA000', dashArray: '0,10' + (new Array(25).join(',8,4')), fill: false, clickable: false};
// Styler for highlighting resonators deployed by me
var myReso = {
name: 'Highlight my resonators',
otherOptions: {
'highlightedReso' : highlightedReso,
'normalReso' : normalReso,
'selectedReso' : selectedReso,
'highlightedConn' : highlightedConn,
'normalConn' : normalConn,
'selectedConn' : selectedConn
},
resonatorStyleFunc: function(resoDetail, selected) {
var mine = resoDetail.ownerGuid === PLAYER.guid;
var resoSharedStyle = mine
? this.otherOptions.highlightedReso
: (selected ? this.otherOptions.selectedReso : this.otherOptions.normalReso);
var resoStyle = $.extend({
fillColor: COLORS_LVL[resoDetail.level],
fillOpacity: resoDetail.energyTotal/RESO_NRG[resoDetail.level] * (mine ? 1 : 0.75)
}, resoSharedStyle);
return resoStyle;
},
connectorStyleFunc: function(resoDetail, selected) {
var mine = resoDetail.ownerGuid === PLAYER.guid;
var connStyle = mine
? this.otherOptions.highlightedConn
: (selected ? this.otherOptions.selectedConn : this.otherOptions.normalConn);
return connStyle;
}
};
thisPlugin.render.addStyler(new thisPlugin.Styler(myReso));
// Styler for highlighting L8 resonators
var l8Reso = {
name: 'Highlight L8 resonators',
otherOptions: {
'highlightedReso' : highlightedReso,
'normalReso' : normalReso,
'selectedReso' : selectedReso,
'highlightedConn' : highlightedConn,
'normalConn' : normalConn,
'selectedConn' : selectedConn
},
resonatorStyleFunc: function(resoDetail, selected) {
var l8 = resoDetail.level === 8;
var resoSharedStyle = l8
? this.otherOptions.highlightedReso
: (selected ? this.otherOptions.selectedReso : this.otherOptions.normalReso);
var resoStyle = $.extend({
fillColor: COLORS_LVL[resoDetail.level],
fillOpacity: resoDetail.energyTotal/RESO_NRG[resoDetail.level] * (l8 ? 1 : 0.75)
}, resoSharedStyle);
return resoStyle;
},
connectorStyleFunc: function(resoDetail, selected) {
var l8 = resoDetail.level === 8;
var connStyle = l8
? this.otherOptions.highlightedConn
: (selected ? this.otherOptions.selectedConn : this.otherOptions.normalConn);
return connStyle;
}
};
thisPlugin.render.addStyler(new thisPlugin.Styler(l8Reso));
// Styler for highlighting resonators with less than X% energy
var lessThanXPctReso = {
name: 'Highlight < X% resonators',
otherOptions: {
'highlightedReso': highlightedReso,
'normalReso': normalReso,
'selectedReso': selectedReso,
'highlightedConn': highlightedConn,
'normalConn': normalConn,
'selectedConn': selectedConn,
'pct': 15,
'dialogEntry': new thisPlugin.TextboxDialogEntry({
name: 'resoLessThanPct-pct',
label: 'Percentage',
valueFunc: function() {return thisPlugin.options.getOption('styler-resoLessThanPct-pct')},
onChangeCallback: function(event) {thisPlugin.options.changeOption('styler-resoLessThanPct-pct', parseInt(event.target.value));}
})
},
resonatorStyleFunc: function(resoDetail, selected) {
var highlight = (resoDetail.energyTotal * 100) < (RESO_NRG[resoDetail.level] * this.otherOptions.pct);
var resoSharedStyle = highlight
? this.otherOptions.highlightedReso
: (selected ? this.otherOptions.selectedReso : this.otherOptions.normalReso);
var resoStyle = $.extend({
fillColor: COLORS_LVL[resoDetail.level],
fillOpacity: resoDetail.energyTotal/RESO_NRG[resoDetail.level]
}, resoSharedStyle);
return resoStyle;
},
connectorStyleFunc: function(resoDetail, selected) {
var highlight = (resoDetail.energyTotal * 100) < (RESO_NRG[resoDetail.level] * this.otherOptions.pct);
var connStyle = highlight
? this.otherOptions.highlightedConn
: (selected ? this.otherOptions.selectedConn : this.otherOptions.normalConn);
return connStyle;
},
onEnableFunc: function() {
var thisPlugin = window.plugin.drawResonators;
var thisStyler = this;
// Add option
thisPlugin.options.newOption('styler-resoLessThanPct-pct', 15);
thisPlugin.options.addCallback('styler-resoLessThanPct-pct', function(value) {
thisStyler.otherOptions.pct = value;
thisPlugin.render.refreshStyler();
});
thisStyler.otherOptions.pct = thisPlugin.options.getOption('styler-resoLessThanPct-pct');
// Add dialog entry
thisPlugin.dialog.addEntry('resoLessThanPct-pct', this.otherOptions.dialogEntry);
},
onDisableFunc: function() {
var thisPlugin = window.plugin.drawResonators;
// Remove option
thisPlugin.options.removeOption('styler-resoLessThanPct-pct');
// Remove dialog entry
thisPlugin.dialog.removeEntry('resoLessThanPct-pct');
}
};
thisPlugin.render.addStyler(new thisPlugin.Styler(lessThanXPctReso));
// Styler for highlighting resonators deployed by specific player
var resoOfSpecificPlayer = {
name: 'Highlight resonators by player',
otherOptions: {
'highlightedReso': highlightedReso,
'normalReso': normalReso,
'selectedReso': selectedReso,
'highlightedConn': highlightedConn,
'normalConn': normalConn,
'selectedConn': selectedConn,
'player': '',
'playerGuid': '',
'dialogEntry': new thisPlugin.TextboxDialogEntry({
name: 'resoOfSpecificPlayer-player',
label: 'Player name',
valueFunc: function() {return thisPlugin.options.getOption('styler-resoOfSpecificPlayer-player')},
onChangeCallback: function(event) {thisPlugin.options.changeOption('styler-resoOfSpecificPlayer-player', event.target.value);}
})
},
resonatorStyleFunc: function(resoDetail, selected) {
var highlight = resoDetail.ownerGuid === this.otherOptions.playerGuid;
var resoSharedStyle = highlight
? this.otherOptions.highlightedReso
: (selected ? this.otherOptions.selectedReso : this.otherOptions.normalReso);
var resoStyle = $.extend({
fillColor: COLORS_LVL[resoDetail.level],
fillOpacity: resoDetail.energyTotal/RESO_NRG[resoDetail.level] * (highlight ? 1 : 0.75)
}, resoSharedStyle);
return resoStyle;
},
connectorStyleFunc: function(resoDetail, selected) {
var highlight = resoDetail.ownerGuid === this.otherOptions.playerGuid;
var connStyle = highlight
? this.otherOptions.highlightedConn
: (selected ? this.otherOptions.selectedConn : this.otherOptions.normalConn);
return connStyle;
},
onEnableFunc: function() {
var thisPlugin = window.plugin.drawResonators;
var thisStyler = this;
// Add option
thisPlugin.options.newOption('styler-resoOfSpecificPlayer-player', '');
thisPlugin.options.addCallback('styler-resoOfSpecificPlayer-player', function(value) {
thisStyler.otherOptions.player = value;
thisStyler.otherOptions.playerGuid = window.playerNameToGuid(value);
thisPlugin.render.refreshStyler();
});
thisStyler.otherOptions.player = thisPlugin.options.getOption('styler-resoOfSpecificPlayer-player');
thisStyler.otherOptions.playerGuid = window.playerNameToGuid(thisStyler.otherOptions.player);
// Add dialog entry
thisPlugin.dialog.addEntry('resoOfSpecificPlayer-player', this.otherOptions.dialogEntry);
},
onDisableFunc: function() {
var thisPlugin = window.plugin.drawResonators;
// Remove option
thisPlugin.options.removeOption('styler-resoOfSpecificPlayer-player');
// Remove dialog entry
thisPlugin.dialog.removeEntry('resoOfSpecificPlayer-player');
}
};
thisPlugin.render.addStyler(new thisPlugin.Styler(resoOfSpecificPlayer));
thisPlugin.render.changeStyler(thisPlugin.options.getOption('useStyler'));
}
window.plugin.drawResonators.setupOptions = function() {
var thisPlugin = window.plugin.drawResonators;
// Initialize options
thisPlugin.options = new thisPlugin.Options();
thisPlugin.options.newOption('enableZoomLevel', 17);
thisPlugin.options.newOption('useStyler', 'Default');
}
window.plugin.drawResonators.setupDialog = function() {
var thisPlugin = window.plugin.drawResonators;
// Initialize dialog
thisPlugin.dialog = new thisPlugin.Dialog();
var enableZoomLevelDialogEntryOptions = {
name: 'enable-zoom-level',
label: 'Enable zoom level',
valueFunc: function() {return thisPlugin.options.getOption('enableZoomLevel')},
valuesList: {'15':15, '16':16, '17':17, '18':18, '19':19, '20':20, 'None':99},
onChangeCallback: function(event) {thisPlugin.options.changeOption('enableZoomLevel', parseInt(event.target.value));}
};
var enableZoomLevelDialogEntry = new thisPlugin.ListDialogEntry(enableZoomLevelDialogEntryOptions);
thisPlugin.dialog.addEntry('enable-zoom-level', enableZoomLevelDialogEntry);
var stylerDialogEntryOptions = {
name: 'use-styler',
label: 'Styler',
valueFunc: function() {return thisPlugin.options.getOption('useStyler')},
valuesListFunc: thisPlugin.render.getStylersList,
onChangeCallback: function(event) {thisPlugin.options.changeOption('useStyler', event.target.value);}
};
var stylerDialogEntry = new thisPlugin.ListDialogEntry(stylerDialogEntryOptions);
thisPlugin.dialog.addEntry('use-styler', stylerDialogEntry);
thisPlugin.dialog.addLink();
}
var setup = function() {
var thisPlugin = window.plugin.drawResonators;
// Initialize options
thisPlugin.setupOptions();
// Initialize render
var renderOptions = {'enableZoomLevel': thisPlugin.options.getOption('enableZoomLevel')};
thisPlugin.render = new thisPlugin.Render(renderOptions);
// callback run at option change
thisPlugin.options.addCallback('enableZoomLevel', thisPlugin.render.handleEnableZoomLevelChange);
thisPlugin.options.addCallback('useStyler', thisPlugin.render.changeStyler);
// Initialize Dialog
thisPlugin.setupDialog();
// Initialize styler
thisPlugin.setupStyler();
thisPlugin.render.registerHook();
window.addLayerGroup('Resonators', thisPlugin.render.resonatorLayerGroup, true);
}
// PLUGIN END //////////////////////////////////////////////////////////
@@PLUGINEND@@

View File

@ -0,0 +1,107 @@
// ==UserScript==
// @id iitc-plugin-players-resonators@rbino
// @name IITC plugin: Player's Resonators
// @version 0.1.5.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] The plugins finds the resonators of a given player. The input is in the sidebar.
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @grant none
// ==/UserScript==
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
/*********************************************************************************************************
* Changelog:
*
* 0.1.5 Added portal and reso counter and reso details (Thanks BJT)
* 0.1.4 Added focus link in the toolbox. Some renaming. Removed div to use sidebar style.
* 0.1.3 Effective player name (with wrong capitalization) if it finds some reso
* 0.1.2 Made nickname case insensitive
* 0.1.1 Added mouseover for portal location. Dirty hack to not show mousehover when the alert is fired.
* 0.1.0 First public release
*********************************************************************************************************/
// use own namespace for plugin
window.plugin.playersResonators = function() {};
window.plugin.playersResonators.findReso = function(playername) {
var s = "";
var portalSet = {};
var effectiveNick = "";
var portalCounter = 0;
var resoCounter = 0;
// Assuming there can be no agents with same nick with different lower/uppercase
var nickToFind = playername.toLowerCase();
$.each(window.portals, function(ind, portal){
var resoLevels = {};
var r = portal.options.details.resonatorArray.resonators;
$.each(r, function(ind, reso) {
if (!reso) return true;
var nick = getPlayerName(reso.ownerGuid);
if (nick.toLowerCase() === nickToFind){
resoCounter += 1;
if (!effectiveNick) {
effectiveNick = nick;
}
if (reso.level in resoLevels){
resoLevels[reso.level] += 1;
} else {
resoLevels[reso.level] = 1;
}
if (!portalSet.hasOwnProperty(portal.options.guid)){
portalSet[portal.options.guid] = true;
var latlng = [portal.options.details.locationE6.latE6/1E6, portal.options.details.locationE6.lngE6/1E6].join();
var guid = portal.options.guid;
var zoomPortal = 'window.zoomToAndShowPortal(\''+guid+'\', ['+latlng+']);return false';
var perma = '/intel?latE6='+portal.options.details.locationE6.latE6+'&lngE6='+portal.options.details.locationE6.lngE6+'&z=17&pguid='+guid;
var a = $('<a>',{
"class": 'help',
text: portal.options.details.portalV2.descriptiveText.TITLE,
title: portal.options.details.portalV2.descriptiveText.ADDRESS,
href: perma,
onClick: zoomPortal
})[0].outerHTML;
portalCounter += 1;
s += a + ": ";
}
}
});
if (portalSet.hasOwnProperty(portal.options.guid)){
for (var i = 8; i>0; i--){
if (i in resoLevels)
s += resoLevels[i] + "xL" + i + " ";
}
s += "\n";
}
});
if (s) {
// Showing the playername as a "fake" link to avoid the auto-mouseover effect on the first portal
fakeLinkPlayer = '<a href="#" onClick="return false;">' + effectiveNick + '</a>'
s = fakeLinkPlayer + " has " + resoCounter + " resonators on " + portalCounter + " portals:\n\n" + s;
} else {
s = playername + " has no resonators in this range\n";
}
alert(s);
}
var setup = function() {
var content = '<input id="playerReso" placeholder="Type player name to find resonators..." type="text">';
$('#sidebar').append(content);
$('#toolbox').append(' <a onclick=$("#playerReso").focus() title="Find all portals with resonators of a certain player">Player\'s Reso</a>');
$("#playerReso").keypress(function(e) {
if((e.keyCode ? e.keyCode : e.which) !== 13) return;
var data = $(this).val();
window.plugin.playersResonators.findReso(data);
});
}
// PLUGIN END //////////////////////////////////////////////////////////
@@PLUGINEND@@

View File

@ -0,0 +1,171 @@
// ==UserScript==
// @id iitc-plugin-defense@gluckies
// @name IITC plugin: portal defense
// @category Layer
// @version 0.2.2.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Shows the defense values of every portal (see also "hightlight portals total mitigation" highlighter)
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// ==/UserScript==
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
// use own namespace for plugin
window.plugin.portalDefense = function() {};
window.plugin.portalDefense.MIN_MAP_ZOOM = 15;
window.plugin.portalDefense.DETAIL_MAP_ZOOM = 17;
window.plugin.portalDefense.DisplayEnum = {
OFF : 0,
SIMPLE : 1,
DETAIL : 2
};
window.plugin.portalDefense.regionLayers = {};
// Use portal add and remove event to control render of regions
window.plugin.portalDefense.portalAdded = function(data) {
data.portal.on('add', function() {
plugin.portalDefense.renderAttackRegion(this);
});
data.portal.on('remove', function() {
plugin.portalDefense.removeAttackRegion(this);
});
}
window.plugin.portalDefense.getDisplay = function() {
if (map.getZoom() >= window.plugin.portalDefense.DETAIL_MAP_ZOOM) {
return window.plugin.portalDefense.DisplayEnum.DETAIL;
} else if (map.getZoom() >= window.plugin.portalDefense.MIN_MAP_ZOOM) {
return window.plugin.portalDefense.DisplayEnum.SIMPLE;
}
return window.plugin.portalDefense.DisplayEnum.OFF;
}
window.plugin.portalDefense.renderAttackRegion = function(portal) {
plugin.portalDefense.removeAttackRegion(portal);
if (window.plugin.portalDefense.currentDisplay == window.plugin.portalDefense.DisplayEnum.OFF) return;
plugin.portalDefense.regionLayers[portal.options.guid] = [];
var defense = window.getPortalMitigationDetails(portal.options.details);
if (defense.total) {
var display = defense.total;
if (window.plugin.portalDefense.currentDisplay == window.plugin.portalDefense.DisplayEnum.DETAIL) {
if (defense.shields) {
display += "<br>"+"\u2297"+defense.shields;
}
if(defense.links) {
display += "<br>"+"\u21b1"+defense.links;
}
}
var region = L.marker(portal.getLatLng(), {
icon: L.divIcon({
className: 'plugin-iic-defense',
clickable: false,
iconAnchor: [-10,10],
html: "<div class='defense-label'>"+display+"</div>"
}),
guid: portal.options.guid
});
plugin.portalDefense.regionLayers[portal.options.guid].push(region);
region.addTo(plugin.portalDefense.regionLayerGroup);
}
}
window.plugin.portalDefense.reload = function() {
$.each(window.portals, function(ind, portal) {
// only render mitigation details for portals added to the map
if (portal._map) {
window.plugin.portalDefense.renderAttackRegion(portal)
}
});
}
window.plugin.portalDefense.removeAttackRegion = function(portal) {
var previousLayers = plugin.portalDefense.regionLayers[portal.options.guid];
if (previousLayers) {
for (var i = 0; i < previousLayers.length; i++) {
plugin.portalDefense.regionLayerGroup.removeLayer(previousLayers[i]);
}
delete plugin.portalDefense.regionLayers[portal.options.guid];
}
}
window.plugin.portalDefense.regions = {}
window.plugin.portalDefense.showOrHide = function() {
var ctrl = $('.leaflet-control-layers-selector + span:contains("Portal Defense")').parent();
var display = window.plugin.portalDefense.getDisplay();
if (display != window.plugin.portalDefense.DisplayEnum.OFF) {
// show the layer
if(!window.plugin.portalDefense.regionLayerGroup.hasLayer(window.plugin.portalDefense.defenseLayerGroup)) {
window.plugin.portalDefense.regionLayerGroup.addLayer(window.plugin.portalDefense.defenseLayerGroup);
}
ctrl.removeClass('disabled').attr('title', '');
} else {
// hide the layer
if(window.plugin.portalDefense.regionLayerGroup.hasLayer(window.plugin.portalDefense.defenseLayerGroup)) {
window.plugin.portalDefense.regionLayerGroup.removeLayer(window.plugin.portalDefense.defenseLayerGroup);
}
ctrl.addClass('disabled').attr('title', 'Zoom in to show those.');
}
if (window.plugin.portalDefense.currentDisplay != display) {
window.plugin.portalDefense.currentDisplay = display;
window.plugin.portalDefense.reload()
}
}
var setup = function() {
$('#toolbox').append(' <a onclick="window.plugin.portalDefense.reload()">Reload Defense</a>');
$("<style>")
.prop("type", "text/css")
.html(".plugin-iic-defense {\
font-size: 10px;\
color: #FFFFBB;\
font-family: monospace;\
text-align: center;\
text-shadow: 0 0 0.5em black, 0 0 0.5em black, 0 0 0.5em black;\
pointer-events: none;\
-webkit-text-size-adjust:none;\
}\
.defense-label {\
position:relative;\
background-color:#1B3E59;\
opacity:.6;\
border:0.5px solid #FFCE00;\
width:22px;\
text-align:center;\
color:#FFFFFF;\
text-align:center;\
border-radius:6px;\
}")
.appendTo("head");
window.plugin.portalDefense.currentDisplay = window.plugin.portalDefense.getDisplay();
map.on('zoomend', window.plugin.portalDefense.showOrHide);
// this layer is added to the layer chooser, to be toggled on/off
window.plugin.portalDefense.regionLayerGroup = new L.LayerGroup();
// this layer is added into the above layer, and removed from it when we zoom out too far
window.plugin.portalDefense.defenseLayerGroup = new L.LayerGroup();
window.plugin.portalDefense.regionLayerGroup.addLayer(window.plugin.portalDefense.defenseLayerGroup);
window.addLayerGroup('Portal Defense', window.plugin.portalDefense.regionLayerGroup, true);
window.addHook('portalAdded', window.plugin.portalDefense.portalAdded);
window.plugin.portalDefense.showOrHide();
}
// PLUGIN END //////////////////////////////////////////////////////////
@@PLUGINEND@@

View File

@ -0,0 +1,49 @@
// ==UserScript==
// @id iitc-plugin-highlight-bad-deployment-distance@cathesaurus
// @name IITC plugin: highlight badly-deployed portals
// @category Highlighter
// @version 0.1.1.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Uses the fill color of the portals to show the effective resonator deployment range, where that average is less than 36 metres
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @grant none
// ==/UserScript==
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
// use own namespace for plugin
window.plugin.portalHighlighterBadDeploymentDistance = function() {};
window.plugin.portalHighlighterBadDeploymentDistance.highlight = function(data) {
var d = data.portal.options.details;
var portal_deployment = 0;
if(getTeam(d) !== 0) {
var avgDist = window.getAvgResoDist(d);
if(avgDist > 0 && avgDist < window.HACK_RANGE*0.9) {
portal_deployment = (window.HACK_RANGE - avgDist)/window.HACK_RANGE;
}
if(portal_deployment > 0) {
var fill_opacity = portal_deployment*.85 + .15;
// magenta for *exceptionally* close deployments (spoofing? under 1m average), then shades of
// red, orange and yellow for further out
color = avgDist < 1 ? 'magenta' : avgDist < (window.HACK_RANGE*.25) ? 'red' : avgDist < (window.HACK_RANGE*.6) ? 'orange' : 'yellow';
var params = {fillColor: color, fillOpacity: fill_opacity};
data.portal.setStyle(params);
}
}
}
var setup = function() {
window.addPortalHighlighter('Bad Deployment Distance', window.plugin.portalHighlighterBadDeploymentDistance.highlight);
}
// PLUGIN END //////////////////////////////////////////////////////////
@@PLUGINEND@@

View File

@ -0,0 +1,74 @@
// ==UserScript==
// @id iitc-plugin-highlight-portals-upgrade@vita10gy
// @name IITC plugin: highlight portals you can upgrade to a specific level
// @category Highlighter
// @version 0.1.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Uses the fill color of the portals to highlight portals you can upgrade to a specific level.
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @grant none
// ==/UserScript==
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
// use own namespace for plugin
window.plugin.portalHighligherPortalsCanMakeLevel = function() {};
window.plugin.portalHighligherPortalsCanMakeLevel.highlight = function(data,highlight_level) {
var d = data.portal.options.details;
var current_level = Math.floor(getPortalLevel(d));
var potential_level = Math.floor(window.potentialPortalLevel(d));
var opacity = .7;
if( potential_level > current_level && potential_level === highlight_level) {
color = 'red';
data.portal.setStyle({fillColor: color, fillOpacity: opacity});
}
}
//determines the level of poral a user can make all on their own
window.plugin.portalHighligherPortalsCanMakeLevel.playerCanSoloLevel = function(lvl) {
var resonators_total = 0;
var resonators_placed = 0;
var resonator_level = PLAYER.level
while(resonators_placed < 8) {
for(var i = 0; i<MAX_RESO_PER_PLAYER[resonator_level]; i++) {
if(resonators_placed < 8) {
resonators_total += resonator_level;
resonators_placed++;
}
}
resonator_level--;
}
return(Math.floor(resonators_total/8));
}
window.plugin.portalHighligherPortalsCanMakeLevel.getHighlighter = function(lvl) {
return(function(data){
window.plugin.portalHighligherPortalsCanMakeLevel.highlight(data,lvl);
});
}
var setup = function() {
// This is the maximum level of a portal a user can be the "last piece of"
// yes, even a level 1 can be the difference in bumping a portal up to level 7
var max_can_complete = 7;
if(PLAYER.level === 8) {
max_can_complete = 8;
}
// The rational behind the "minimum" level below is that showing a level 7 player, for example, all the portals they can make
// a level 5 would be silly, as they can make ANY portal a level 5.
for(var ptl_lvl = window.plugin.portalHighligherPortalsCanMakeLevel.playerCanSoloLevel()+1; ptl_lvl<=max_can_complete; ptl_lvl++) {
window.addPortalHighlighter('Can Make Level ' + ptl_lvl, window.plugin.portalHighligherPortalsCanMakeLevel.getHighlighter(ptl_lvl));
}
}
// PLUGIN END //////////////////////////////////////////////////////////
@@PLUGINEND@@

View File

@ -0,0 +1,64 @@
// ==UserScript==
// @id iitc-plugin-highlight-imminent-decay@cathesaurus
// @name IITC plugin: highlight portals with resonators about to decay
// @category Highlighter
// @version 0.1.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Uses the fill color of the portals to show resonators due to decay within the next day. Red = portal will decay completely, orange = portal will drop all links, yellow = one or more resonators will decay completely.
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @grant none
// ==/UserScript==
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
// use own namespace for plugin
window.plugin.portalHighlighterImminentDecay = function() {};
window.plugin.portalHighlighterImminentDecay.highlight = function(data) {
var d = data.portal.options.details;
if(getTeam(d) !== 0) {
//Check the energy of every resonator.
var resImminentDecayCount = 0;
var resCount = 0;
$.each(d.resonatorArray.resonators, function(ind, reso) {
if(reso !== null) {
var level = parseInt(reso.level);
var maxResonatorEnergy = window.RESO_NRG[level];
var currentResonatorEnergy = parseInt(reso.energyTotal);
if((currentResonatorEnergy / maxResonatorEnergy) < 0.15) {
resImminentDecayCount++;
}
resCount++;
}
});
if(resImminentDecayCount > 0) {
if(resImminentDecayCount === resCount) {
var color = 'red';
} else if((resCount - resImminentDecayCount) < 3) {
color = 'orange';
} else {
color = 'yellow';
}
// Apply colour to portal.
var params = {fillColor: color, fillOpacity: 1};
data.portal.setStyle(params);
}
}
window.COLOR_SELECTED_PORTAL = '#f0f';
}
var setup = function() {
window.addPortalHighlighter('Imminent Decay', window.plugin.portalHighlighterImminentDecay.highlight);
}
// PLUGIN END //////////////////////////////////////////////////////////
@@PLUGINEND@@

View File

@ -0,0 +1,48 @@
// ==UserScript==
// @id iitc-plugin-highlight-mitigation@jonatkins
// @name IITC plugin: hightlight portals total mitigation
// @category Highlighter
// @version 0.1.1.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Uses the fill color of the portals to show mitigation. Shades of red to the maximum of 95, then tints towards purple for over 95
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @grant none
// ==/UserScript==
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
// use own namespace for plugin
window.plugin.portalHighligherMitigation = function() {};
window.plugin.portalHighligherMitigation.highlight = function(data) {
var defense = window.getPortalMitigationDetails(data.portal.options.details);
if (defense.total > 0) {
var fill_opacity = (defense.total/95)*.85 + .15;
var blue = Math.max(0,Math.min(255,Math.round(defense.excess/80*255)));
var colour = 'rgb(255,0,'+blue+')';
var params = {fillColor: colour, fillOpacity: fill_opacity};
data.portal.setStyle(params);
}
}
var setup = function() {
window.addPortalHighlighter('Mitigation (defense)', window.plugin.portalHighligherMitigation.highlight);
}
// PLUGIN END //////////////////////////////////////////////////////////
@@PLUGINEND@@

View File

@ -0,0 +1,103 @@
// ==UserScript==
// @id iitc-plugin-highlight-portals-mods@vita10gy
// @name IITC plugin: highlight portal mods
// @category Highlighter
// @version 0.1.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Uses the fill color of the portals to denote if the portal has the selected mod.
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @grant none
// ==/UserScript==
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
// use own namespace for plugin
window.plugin.portalHighligherMods = function() {};
window.plugin.portalHighligherMods.highlight = function(data, mod_type) {
var d = data.portal.options.details;
if(!jQuery.isArray(mod_type)) {
mod_type = [mod_type];
}
var mod_effect = 0;
$.each(d.portalV2.linkedModArray, function(ind, mod) {
if(mod !== null && jQuery.inArray(mod.type, mod_type) > -1) {
switch(mod.rarity){
case 'COMMON':
mod_effect++;
break;
case 'RARE':
mod_effect+=2;
break;
case 'VERY_RARE':
mod_effect+=3;
break;
}
}
});
if(mod_effect > 0) {
var fill_opacity = mod_effect/12*.8 + .2;
var color = 'red';
fill_opacity = Math.round(fill_opacity*100)/100;
var params = {fillColor: color, fillOpacity: fill_opacity};
data.portal.setStyle(params);
}
}
window.plugin.portalHighligherMods.highlightNoMods = function(data) {
var d = data.portal.options.details;
var mods = 0;
$.each(d.portalV2.linkedModArray, function(ind, mod) {
if(mod !== null) {
mods += 1;
}
});
if(mods == 0) {
var fill_opacity = .6;
var color = 'red';
var params = {fillColor: color, fillOpacity: fill_opacity};
data.portal.setStyle(params);
} else if(mods <4) {
var fill_opacity = .6;
var color = 'yellow';
var params = {fillColor: color, fillOpacity: fill_opacity};
data.portal.setStyle(params);
}
}
window.plugin.portalHighligherMods.getHighlighter = function(type) {
return(function(data){
window.plugin.portalHighligherMods.highlight(data,type);
});
}
var setup = function() {
$.each(MOD_TYPE, function(ind, name){
window.addPortalHighlighter('Mod: '+name, window.plugin.portalHighligherMods.getHighlighter(ind));
});
window.addPortalHighlighter('Mod: Hackability', window.plugin.portalHighligherMods.getHighlighter(['MULTIHACK', 'HEATSINK']));
window.addPortalHighlighter('Mod: Attack', window.plugin.portalHighligherMods.getHighlighter(['FORCE_AMP', 'TURRET']));
window.addPortalHighlighter('Mod: Defense', window.plugin.portalHighligherMods.getHighlighter(['RES_SHIELD', 'FORCE_AMP', 'TURRET']));
window.addPortalHighlighter('Mod: None', window.plugin.portalHighligherMods.highlightNoMods);
}
// PLUGIN END //////////////////////////////////////////////////////////
@@PLUGINEND@@

View File

@ -0,0 +1,53 @@
// ==UserScript==
// @id iitc-plugin-highlight-portals-my-8-portals@vita10gy
// @name IITC plugin: highlight my level 8's on portals
// @category Highlighter
// @version 0.1.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Uses the fill color of the portals to denote portals you have a level 8 on.
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @grant none
// ==/UserScript==
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
// use own namespace for plugin
window.plugin.portalHighligherMy8sOnPortals = function() {};
window.plugin.portalHighligherMy8sOnPortals.highlight = function(data) {
var d = data.portal.options.details;
var portal_weakness = 0;
if(getTeam(d) !== 0) {
var color = 'red';
var opacity = .7;
var resCount = false;
$.each(d.resonatorArray.resonators, function(ind, reso) {
if(reso !== null && reso.ownerGuid === PLAYER.guid && reso.level == 8) {
resCount = true;
}
});
if(resCount) {
data.portal.setStyle({fillColor: color, fillOpacity: opacity});
}
}
}
var setup = function() {
//Don't list it if it isn't applicable yet
if(PLAYER.level == 8) {
window.addPortalHighlighter('My Level 8 Resonators', window.plugin.portalHighligherMy8sOnPortals.highlight);
}
}
// PLUGIN END //////////////////////////////////////////////////////////
@@PLUGINEND@@

View File

@ -0,0 +1,70 @@
// ==UserScript==
// @id iitc-plugin-highlight-portals-my-portals@vita10gy
// @name IITC plugin: highlight my portals
// @category Highlighter
// @version 0.1.1.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Uses the fill color of the portals to denote portals you have a hand in. Orange is just ownership. Yellow is shields. Red is Resonators. Red trumps both, yellow trumps orange.
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @grant none
// ==/UserScript==
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
// use own namespace for plugin
window.plugin.portalHighligherMyPortals = function() {};
window.plugin.portalHighligherMyPortals.highlight = function(data) {
var d = data.portal.options.details;
var portal_weakness = 0;
if(getTeam(d) !== 0) {
var color = '';
var opacity = .7;
if(PLAYER.guid === d.captured.capturingPlayerId) {
color = 'orange';
}
var modCount = 0;
$.each(d.portalV2.linkedModArray, function(ind, mod) {
if(mod !== null && mod.installingUser === PLAYER.guid) {
color = 'yellow';
modCount++;
}
});
if(modCount > 0) {
opacity = modCount*.25*.7 + .3;
}
var resCount = 0;
$.each(d.resonatorArray.resonators, function(ind, reso) {
if(reso !== null && reso.ownerGuid === PLAYER.guid) {
color = 'red';
resCount++;
}
});
if(resCount > 0) {
opacity = resCount*.125*.7 + .3;
}
if(color !== '') {
data.portal.setStyle({fillColor: color, fillOpacity: opacity});
}
}
}
var setup = function() {
window.addPortalHighlighter('My Portals', window.plugin.portalHighligherMyPortals.highlight);
}
// PLUGIN END //////////////////////////////////////////////////////////
@@PLUGINEND@@

View File

@ -0,0 +1,104 @@
// ==UserScript==
// @id iitc-plugin-highlight-portals-by-ap-by-energy-relative@vita10gy
// @name IITC plugin: highlight portals by ap/energy (relative)
// @category Highlighter
// @version 0.1.1.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Uses the fill color of the portals to denote AP/Energy value relative to what's currently on the screen. Brighter is better. Orange means your standard 8 down 8 up swap.
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @grant none
// ==/UserScript==
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
// use own namespace for plugin
window.plugin.portalHighligherPortalAPPerEnergyRelative = function() {};
window.plugin.portalHighligherPortalAPPerEnergyRelative.minAP = null;
window.plugin.portalHighligherPortalAPPerEnergyRelative.maxAP = null;
//This is the AP for a run of the mill takedown/putback
window.plugin.portalHighligherPortalAPPerEnergyRelative.baseSwapAP = 2350;
window.plugin.portalHighligherPortalAPPerEnergyRelative.highlight = function(data) {
var d = data.portal.options.details;
var color = 'red';
if(window.plugin.portalHighligherPortalAPPerEnergyRelative.minAP == null ||
window.plugin.portalHighligherPortalAPPerEnergyRelative.maxAP == null) {
window.plugin.portalHighligherPortalAPPerEnergyRelative.calculateAPLevels();
}
var minApE = window.plugin.portalHighligherPortalAPPerEnergyRelative.minAP;
var maxApE = window.plugin.portalHighligherPortalAPPerEnergyRelative.maxAP;
if(PLAYER.team !== d.controllingTeam.team) {
var ap = getAttackApGain(d);
var energy = getCurrentPortalEnergy(d);
if(energy < 1) {
energy = 1;
}
portal_ap = ap.enemyAp;
var opacity = 1;
if(minApE !== maxApE) {
opacity = ((ap.enemyAp / energy) - minApE) / (maxApE - minApE);
}
if(opacity < 0) {
opacity = 0;
}
if(opacity > 1) {
opacity = 1;
}
data.portal.setStyle({fillColor: color, fillOpacity: opacity});
}
}
window.plugin.portalHighligherPortalAPPerEnergyRelative.resetAPLevels = function() {
window.plugin.portalHighligherPortalAPPerEnergyRelative.minAP = null;
window.plugin.portalHighligherPortalAPPerEnergyRelative.maxAP = null;
}
window.plugin.portalHighligherPortalAPPerEnergyRelative.calculateAPLevels = function() {
var displayBounds = map.getBounds();
$.each(window.portals, function(qk, portal) {
if(displayBounds.contains(portal.getLatLng())) {
if(PLAYER.team !== portal.options.details.controllingTeam.team) {
var ap = getAttackApGain(portal.options.details);
var energy = getCurrentPortalEnergy(portal.options.details);
if(energy < 1) {
energy = 1;
}
var portal_ap = ap.enemyAp / energy;
if(window.plugin.portalHighligherPortalAPPerEnergyRelative.minAP === null ||
portal_ap < window.plugin.portalHighligherPortalAPPerEnergyRelative.minAP) {
window.plugin.portalHighligherPortalAPPerEnergyRelative.minAP = portal_ap;
}
if(window.plugin.portalHighligherPortalAPPerEnergyRelative.maxAP === null ||
portal_ap > window.plugin.portalHighligherPortalAPPerEnergyRelative.maxAP) {
window.plugin.portalHighligherPortalAPPerEnergyRelative.maxAP = portal_ap;
}
}
}
});
}
var setup = function() {
window.addPortalHighlighter('AP/Energy (Relative)', window.plugin.portalHighligherPortalAPPerEnergyRelative.highlight);
window.addHook('requestFinished', window.plugin.portalHighligherPortalAPPerEnergyRelative.resetAPLevels);
}
// PLUGIN END //////////////////////////////////////////////////////////
@@PLUGINEND@@

View File

@ -0,0 +1,99 @@
// ==UserScript==
// @id iitc-plugin-highlight-portals-by-ap-relative@vita10gy
// @name IITC plugin: highlight portals by ap relative
// @category Highlighter
// @version 0.1.1.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Uses the fill color of the portals to denote AP value relative to what's currently on the screen. Brighter is better. Orange means your standard 8 down 8 up swap.
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @grant none
// ==/UserScript==
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
// use own namespace for plugin
window.plugin.portalHighligherPortalAPRelative = function() {};
window.plugin.portalHighligherPortalAPRelative.minAP = null;
window.plugin.portalHighligherPortalAPRelative.maxAP = null;
//This is the AP for a run of the mill takedown/putback
window.plugin.portalHighligherPortalAPRelative.baseSwapAP = 2350;
window.plugin.portalHighligherPortalAPRelative.highlight = function(data) {
var d = data.portal.options.details;
var color = 'red';
if(window.plugin.portalHighligherPortalAPRelative.minAP == null ||
window.plugin.portalHighligherPortalAPRelative.maxAP == null) {
window.plugin.portalHighligherPortalAPRelative.calculateAPLevels();
}
var minAp = window.plugin.portalHighligherPortalAPRelative.minAP;
var maxAp = window.plugin.portalHighligherPortalAPRelative.maxAP;
var ap = getAttackApGain(d);
var portal_ap = ap.friendlyAp;
if(PLAYER.team !== d.controllingTeam.team) {
portal_ap = ap.enemyAp;
if(portal_ap === window.plugin.portalHighligherPortalAPRelative.baseSwapAP) {
color = 'orange';
}
}
var opacity = 1;
if(minAp !== maxAp) {
opacity = (portal_ap - minAp) / (maxAp - minAp);
}
if(opacity < 0) {
opacity = 0;
}
if(opacity > 1) {
opacity = 1;
}
data.portal.setStyle({fillColor: color, fillOpacity: opacity});
}
window.plugin.portalHighligherPortalAPRelative.resetAPLevels = function() {
window.plugin.portalHighligherPortalAPRelative.minAP = null;
window.plugin.portalHighligherPortalAPRelative.maxAP = null;
}
window.plugin.portalHighligherPortalAPRelative.calculateAPLevels = function() {
var displayBounds = map.getBounds();
$.each(window.portals, function(qk, portal) {
if(displayBounds.contains(portal.getLatLng())) {
var ap = getAttackApGain(portal.options.details);
var portal_ap = ap.friendlyAp;
if(PLAYER.team !== portal.options.details.controllingTeam.team) {
portal_ap = ap.enemyAp;
}
if(window.plugin.portalHighligherPortalAPRelative.minAP === null ||
portal_ap < window.plugin.portalHighligherPortalAPRelative.minAP) {
window.plugin.portalHighligherPortalAPRelative.minAP = portal_ap;
}
if(window.plugin.portalHighligherPortalAPRelative.maxAP === null ||
portal_ap > window.plugin.portalHighligherPortalAPRelative.maxAP) {
window.plugin.portalHighligherPortalAPRelative.maxAP = portal_ap;
}
}
});
}
var setup = function() {
window.addPortalHighlighter('AP (Relative)', window.plugin.portalHighligherPortalAPRelative.highlight);
window.addHook('requestFinished', window.plugin.portalHighligherPortalAPRelative.resetAPLevels);
}
// PLUGIN END //////////////////////////////////////////////////////////
@@PLUGINEND@@

View File

@ -0,0 +1,60 @@
// ==UserScript==
// @id iitc-plugin-highlight-portals-by-ap@vita10gy
// @name IITC plugin: highlight portals by ap
// @category Highlighter
// @version 0.1.1.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Uses the fill color of the portals to denote AP value. Brighter is better. Orange means your standard 8 down 8 up swap.
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @grant none
// ==/UserScript==
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
// use own namespace for plugin
window.plugin.portalHighligherPortalAP = function() {};
window.plugin.portalHighligherPortalAP.minAP = 65;
//Anything over max AP will be 100% opacity.
window.plugin.portalHighligherPortalAP.maxAP = 6000;
//This is the AP for a run of the mill takedown/putback
window.plugin.portalHighligherPortalAP.baseSwapAP = 2350;
window.plugin.portalHighligherPortalAP.highlight = function(data) {
var d = data.portal.options.details;
var color = 'red';
var ap = getAttackApGain(d);
var portal_ap = ap.friendlyAp;
if(PLAYER.team !== d.controllingTeam.team) {
portal_ap = ap.enemyAp;
if(portal_ap === window.plugin.portalHighligherPortalAP.baseSwapAP) {
color = 'orange';
}
}
var opacity = (portal_ap - window.plugin.portalHighligherPortalAP.minAP) / window.plugin.portalHighligherPortalAP.maxAP;
if(opacity < 0) {
opacity = 0;
}
if(opacity > 1) {
opacity = 1;
}
data.portal.setStyle({fillColor: color, fillOpacity: opacity});
}
var setup = function() {
window.addPortalHighlighter('AP (Static)', window.plugin.portalHighligherPortalAP.highlight);
}
// PLUGIN END //////////////////////////////////////////////////////////
@@PLUGINEND@@

View File

@ -0,0 +1,80 @@
// ==UserScript==
// @id iitc-plugin-highlight-portals-upgrade@vita10gy
// @name IITC plugin: highlight portals you can upgrade
// @category Highlighter
// @version 0.2.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Upgradable - Yellow: you can upgrade it at all. Orange: you can change the level. Red: you can make it your level or higher. To Elite: Yellow - To Level 6. Orange - To Level 7. Red - To Level 8.
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @grant none
// ==/UserScript==
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
// use own namespace for plugin
window.plugin.portalHighligherPortalsUpgrade = function() {};
window.plugin.portalHighligherPortalsUpgrade.highlight = function(data) {
var d = data.portal.options.details;
var current_level = getPortalLevel(d);
var potential_level = window.potentialPortalLevel(d);
var player_level = PLAYER.level;
var opacity = .7;
if( potential_level > current_level) {
potential_level = Math.floor(potential_level);
current_level = Math.floor(current_level);
//console.log(potential_level + '>' + current_level);
var color = 'yellow';
if(potential_level > current_level) {
color = 'orange';
if(potential_level >= player_level) {
color = 'red';
}
}
data.portal.setStyle({fillColor: color, fillOpacity: opacity});
}
}
window.plugin.portalHighligherPortalsUpgrade.highlight_elite = function(data) {
var d = data.portal.options.details;
var current_level = getPortalLevel(d);
var potential_level = window.potentialPortalLevel(d);
var opacity = .8;
var color = '';
potential_level = Math.floor(potential_level);
current_level = Math.floor(current_level);
if( potential_level > current_level && potential_level >= 6) {
switch(potential_level) {
case 6:
color = 'yellow';
break;
case 7:
color = 'orange';
break;
case 8:
color = 'red';
opacity = .9;
break;
}
data.portal.setStyle({fillColor: color, fillOpacity: opacity});
}
}
var setup = function() {
window.addPortalHighlighter('Upgradable', window.plugin.portalHighligherPortalsUpgrade.highlight);
window.addPortalHighlighter('Upgradable to Elite', window.plugin.portalHighligherPortalsUpgrade.highlight_elite);
}
// PLUGIN END //////////////////////////////////////////////////////////
@@PLUGINEND@@

View File

@ -0,0 +1,453 @@
// ==UserScript==
// @id iitc-plugin-portals-list@teo96
// @name IITC plugin: show list of portals
// @category Info
// @version 0.0.18.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Display a sortable list of all visible portals with full details about the team, resonators, shields, etc.
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @grant none
// ==/UserScript==
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
/* whatsnew
* 0.0.15: Add 'age' column to display how long each portal has been controlled by its current owner.
* 0.0.14: Add support to new mods (S:Shield - T:Turret - LA:Link Amp - H:Heat-sink - M:Multi-hack - FA:Force Amp)
* 0.0.12: Use dialog() instead of alert so the user can drag the box around
* 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 available via tooltips (who deployed, energy, ...), new E/AP column
* 0.0.6 : Add power charge information into a new column + bugfix
* 0.0.5 : Filter portals by clicking on 'All portals', 'Res Portals' or 'Enl Portals'
* 0.0.4 : Add link to portals name, one click to display full information in portal panel, double click to zoom on portal, hover to show address
* 0.0.3 : sorting ascending/descending and add numbers of portals by faction on top on table
* 0.0.2 : add sorting feature when click on header column
* 0.0.1 : initial release, show list of portals with level, team, resonators and shield information
*
* Display code inspired from @vita10gy's scoreboard plugin : iitc-plugin-scoreboard@vita10gy - https://github.com/breunigs/ingress-intel-total-conversion
* Portal link code from xelio - iitc: AP List - https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/ap-list.user.js
*
* todo : export as GPX, Open in Google Maps, more statistics in the header, what else ?
*/
// use own namespace for plugin
window.plugin.portalslist = function() {};
window.plugin.portalslist.listPortals = []; // structure : name, team, level, resonators = Array, Shields = Array, APgain, Age
window.plugin.portalslist.sortOrder=-1;
window.plugin.portalslist.enlP = 0;
window.plugin.portalslist.resP = 0;
window.plugin.portalslist.filter=0;
//fill the listPortals array with portals avaliable 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;
var displayBounds = map.getBounds();
window.plugin.portalslist.listPortals = [];
//get portals informations from IITC
$.each(window.portals, function(i, portal) {
// eliminate offscreen portals (selected, and in padding)
if(!displayBounds.contains(portal.getLatLng())) return true;
retval=true;
var d = portal.options.details;
var name = d.portalV2.descriptiveText.TITLE;
var address = d.portalV2.descriptiveText.ADDRESS;
var img = getPortalImageUrl(d);
var team = portal.options.team;
var now = new Date();
var now_ms = now.getTime();// + (now.getTimezoneOffset() * 60000);
var age_in_seconds = 0;
var age_string_long = 'This portal is not captured.';
var age_string_short = 'n/a';
if(portal.options.details.hasOwnProperty('captured') && portal.options.details.captured.hasOwnProperty('capturedTime')) {
var age_in_seconds = Math.floor((now_ms - portal.options.details.captured.capturedTime)/1000);
var age_string_long = window.plugin.portalslist.secondsToString(age_in_seconds, 'l');
var age_string_short = window.plugin.portalslist.secondsToString(age_in_seconds, 's');
}
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 mods informations
var mods = [];
$.each(d.portalV2.linkedModArray, function(ind, mod) {
var modShortName='';
if (mod) {
switch (mod.displayName) {
case 'Portal Shield':
modShortName = 'S';
break;
case 'Force Amp':
modShortName = 'FA';
break;
case 'Link Amp':
modShortName = 'LA';
break;
case 'Heat Sink':
modShortName = 'H';
break;
case 'Multi-hack':
modShortName = 'M';
break;
case 'Turret':
modShortName = 'T';
break;
default:
modShortName = '';
break;
}
if (modShortName === '') {
mods[ind] = ['', '', ''];
} else {
if ((modShortName === 'S') &&
((mod.rarity=='COMMON' && mod.stats.MITIGATION == 6) ||
(mod.rarity=='RARE' && mod.stats.MITIGATION == 8) ||
(mod.rarity=='VERY_RARE' && mod.stats.MITIGATION == 10)))
modShortName=modShortName+'!';
mods[ind] = [mod.rarity, getPlayerName(mod.installingUser), modShortName, mod.displayName];
}
}else { mods[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,
'mods': mods,
'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,
'age': age_in_seconds,
'age_string_long': age_string_long,
'age_string_short': age_string_short};
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;
if (window.plugin.portalslist.getPortals()) {
html += window.plugin.portalslist.portalTable('level', window.plugin.portalslist.sortOrder,window.plugin.portalslist.filter);
} else {
html = '<table><tr><td>Nothing to show!</td></tr></table>';
};
dialog({
html: '<div id="portalslist">' + html + '</div>',
dialogClass: 'ui-dialog-portalslist',
title: 'Portal list: ' + window.plugin.portalslist.listPortals.length + ' ' + (window.plugin.portalslist.listPortals.length == 1 ? 'portal' : 'portals'),
id: 'portal-list',
width: 800
});
//run the name resolving process
resolvePlayerNames();
//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];
if (retVal)
break;
case 'r2':
retVal = b.resonators[1][0] - a.resonators[1][0];
if (retVal)
break;
case 'r3':
retVal = b.resonators[2][0] - a.resonators[2][0];
if (retVal)
break;
case 'r4':
retVal = b.resonators[3][0] - a.resonators[3][0];
if (retVal)
break;
case 'r5':
retVal = b.resonators[4][0] - a.resonators[4][0];
if (retVal)
break;
case 'r6':
retVal = b.resonators[5][0] - a.resonators[5][0];
if (retVal)
break;
case 'r7':
retVal = b.resonators[6][0] - a.resonators[6][0];
if (retVal)
break;
case 'r8':
retVal = b.resonators[7][0] - a.resonators[7][0];
break;
case 's1':
retVal = a.mods[0][2] > b.mods[0][2] ? -1 : 1;
break;
case 's2':
retVal = a.mods[1][2] > b.mods[1][2] ? -1 : 1;
break;
case 's3':
retVal = a.mods[2][2] > b.mods[2][2] ? -1 : 1;
break;
case 's4':
retVal = a.mods[3][2] > b.mods[3][2] ? -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 += '<table>'
+ '<tr><th ' + sort('names', sortBy, -1) + '>Portal</th>'
+ '<th ' + sort('level', sortBy, -1) + '>Level</th>'
+ '<th title="Team" ' + sort('team', sortBy, -1) + '>T</th>'
+ '<th ' + sort('r1', sortBy, -1) + '>R1</th>'
+ '<th ' + sort('r2', sortBy, -1) + '>R2</th>'
+ '<th ' + sort('r3', sortBy, -1) + '>R3</th>'
+ '<th ' + sort('r4', sortBy, -1) + '>R4</th>'
+ '<th ' + sort('r5', sortBy, -1) + '>R5</th>'
+ '<th ' + sort('r6', sortBy, -1) + '>R6</th>'
+ '<th ' + sort('r7', sortBy, -1) + '>R7</th>'
+ '<th ' + sort('r8', sortBy, -1) + '>R8</th>'
+ '<th ' + sort('energy', sortBy, -1) + '>Energy</th>'
+ '<th ' + sort('energyratio', sortBy, -1) + '>%</th>'
+ '<th ' + sort('links', sortBy, -1) + '>Links</th>'
+ '<th ' + sort('s1', sortBy, -1) + '>M1</th>'
+ '<th ' + sort('s2', sortBy, -1) + '>M2</th>'
+ '<th ' + sort('s3', sortBy, -1) + '>M3</th>'
+ '<th ' + sort('s4', sortBy, -1) + '>M4</th>'
+ '<th ' + sort('mitigation', sortBy, -1) + '>Mit.</th>'
+ '<th ' + sort('APgain', sortBy, -1) + '>AP Gain</th>'
+ '<th title="Energy / AP Gain ratio" ' + sort('EAP', sortBy, -1) + '>E/AP</th>'
+ '<th ' + sort('age', sortBy, -1) + '>Age</th></tr>';
$.each(portals, function(ind, portal) {
if (filter === 0 || filter === portal.team) {
html += '<tr class="' + (portal.team === 1 ? 'res' : (portal.team === 2 ? 'enl' : 'neutral')) + '">'
+ '<td style="">' + window.plugin.portalslist.getPortalLink(portal.portal, portal.guid) + '</td>'
+ '<td class="L' + Math.floor(portal.level) +'">' + portal.level + '</td>'
+ '<td style="text-align:center;">' + portal.team + '</td>';
var mitigationDetails = getPortalMitigationDetails(portal.portal);
portal.mitigation = mitigationDetails.total + mitigationDetails.excess;
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: <b>' + portal.resonators[slot][1] + '</b><br>'
+ 'energy: ' + portal.resonators[slot][3] + ' / ' + portal.resonators[slot][4] + ' (' + percent + '%)<br>'
+ 'distance: ' + portal.resonators[slot][2] + 'm';
html += '<td class="L' + portal.resonators[slot][0] +'" ' + title + '">' + portal.resonators[slot][0] + '</td>';
});
html += '<td style="cursor:help" title="'+ portal.energy +'">' + prettyEnergy(portal.energy) + '</td>'
+ '<td style="cursor:help" title="' + portal.energy + ' / ' + portal.maxenergy +'">' + portal.energyratio + '%</td>'
+ '<td style="cursor:help" title="' + portal.links + '">' + portal.links + '</td>'
+ '<td style="cursor:help; background-color: '+COLORS_MOD[portal.mods[0][0]]+';" title="Mod : ' + portal.mods[0][3] + '\nInstalled by : ' + portal.mods[0][1] + '\nRarity : ' + portal.mods[0][0] + '">' + portal.mods[0][2] + '</td>'
+ '<td style="cursor:help; background-color: '+COLORS_MOD[portal.mods[1][0]]+';" title="Mod : ' + portal.mods[1][3] + '\nInstalled by : ' + portal.mods[1][1] + '\nRarity : ' + portal.mods[1][0] + '">' + portal.mods[1][2] + '</td>'
+ '<td style="cursor:help; background-color: '+COLORS_MOD[portal.mods[2][0]]+';" title="Mod : ' + portal.mods[2][3] + '\nInstalled by : ' + portal.mods[2][1] + '\nRarity : ' + portal.mods[2][0] + '">' + portal.mods[2][2] + '</td>'
+ '<td style="cursor:help; background-color: '+COLORS_MOD[portal.mods[3][0]]+';" title="Mod : ' + portal.mods[3][3] + '\nInstalled by : ' + portal.mods[3][1] + '\nRarity : ' + portal.mods[3][0] + '">' + portal.mods[3][2] + '</td>'
+ '<td>' + portal.mitigation + '</td>'
+ '<td>' + portal.APgain + '</td>'
+ '<td>' + portal.EAP + '</td>'
+ '<td style="cursor:help;" title="' + portal.age_string_long + '">' + portal.age_string_short + '</td>';
html+= '</tr>';
}
});
html += '</table>';
html += '<div class="disclaimer">Click on portals table headers to sort by that column. '
+ 'Click on <b>All Portals, Resistance Portals, Enlightened Portals</b> to filter<br>'
+ 'Thanks to @vita10gy & @xelio for their IITC plugins who inspired me. A <a href="https://plus.google.com/113965246471577467739">@teo96</a> production. Vive la Résistance !</div>';
window.plugin.portalslist.sortOrder = window.plugin.portalslist.sortOrder*-1;
return html;
}
window.plugin.portalslist.stats = function(sortBy) {
//console.log('** stats');
var html = '<table><tr>'
+ '<td class="filterAll" style="cursor:pointer" onclick="window.plugin.portalslist.portalTable(\'level\',-1,0)"><a href=""></a>All Portals : (click to filter)</td><td class="filterAll">' + window.plugin.portalslist.listPortals.length + '</td>'
+ '<td class="filterRes" style="cursor:pointer" class="sorted" onclick="window.plugin.portalslist.portalTable(\'level\',-1,1)">Resistance Portals : </td><td class="filterRes">' + window.plugin.portalslist.resP +' (' + Math.floor(window.plugin.portalslist.resP/window.plugin.portalslist.listPortals.length*100) + '%)</td>'
+ '<td class="filterEnl" style="cursor:pointer" class="sorted" onclick="window.plugin.portalslist.portalTable(\'level\',-1,2)">Enlightened Portals : </td><td class="filterEnl">'+ window.plugin.portalslist.enlP +' (' + Math.floor(window.plugin.portalslist.enlP/window.plugin.portalslist.listPortals.length*100) + '%)</td>'
+ '</tr>'
+ '</table>';
return html;
}
// A little helper function so the above isn't so messy
window.plugin.portalslist.portalTableSort = function(name, by) {
var retVal = 'data-sort="' + name + '"';
if(name === by) {
retVal += ' class="sorted"';
}
return retVal;
};
// portal link - single click: select portal
// double click: zoom to and select portal
// 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 = $('<a>',{
"class": 'help',
text: portal.portalV2.descriptiveText.TITLE,
title: portal.portalV2.descriptiveText.ADDRESS,
href: perma,
onClick: jsSingleClick,
onDblClick: jsDoubleClick
})[0].outerHTML;
var div = '<div class="portalTitle">'+a+'</div>';
return div;
}
// length can be "s" or "l" for "short" or "long"
window.plugin.portalslist.secondsToString = function(seconds, length) {
var numdays = Math.floor(seconds / 86400);
var numhours = Math.floor((seconds % 86400) / 3600);
var numminutes = Math.floor(((seconds % 86400) % 3600) / 60);
var numseconds = ((seconds % 86400) % 3600) % 60;
if(length === "l") {
return numdays + " days " + numhours + " hours " + numminutes + " minutes " + numseconds + " seconds";
} else {
return numdays + "d" + numhours + "h";
}
}
var setup = function() {
$('#toolbox').append(' <a onclick="window.plugin.portalslist.displayPL()" title="Display a list of portals in the current view">Portals list</a>');
$('head').append('<style>' +
//style.css sets dialog max-width to 700px - override that here
// (the width: 800 parameter to dialog is NOT enough to override that css limit)
'#dialog-portal-list {max-width: 800px !important;}' +
'#portalslist table {margin-top:5px; border-collapse: collapse; empty-cells: show; width:100%; clear: both;}' +
'#portalslist table td, #portalslist table th {border-bottom: 1px solid #0b314e; padding:3px; color:white; background-color:#1b415e}' +
'#portalslist table tr.res td { background-color: #005684; }' +
'#portalslist table tr.enl td { background-color: #017f01; }' +
'#portalslist table tr.neutral td { background-color: #000000; }' +
'#portalslist table th { text-align: center;}' +
'#portalslist table td { text-align: center;}' +
'#portalslist table td.L0 { cursor: help; background-color: #000000 !important;}' +
'#portalslist table td.L1 { cursor: help; background-color: #FECE5A !important;}' +
'#portalslist table td.L2 { cursor: help; background-color: #FFA630 !important;}' +
'#portalslist table td.L3 { cursor: help; background-color: #FF7315 !important;}' +
'#portalslist table td.L4 { cursor: help; background-color: #E40000 !important;}' +
'#portalslist table td.L5 { cursor: help; background-color: #FD2992 !important;}' +
'#portalslist table td.L6 { cursor: help; background-color: #EB26CD !important;}' +
'#portalslist table td.L7 { cursor: help; background-color: #C124E0 !important;}' +
'#portalslist table td.L8 { cursor: help; background-color: #9627F4 !important;}' +
'#portalslist table td:nth-child(1) { text-align: left;}' +
'#portalslist table th { cursor:pointer; text-align: right;}' +
'#portalslist table th:nth-child(1) { text-align: left;}' +
'#portalslist table th.sorted { color:#FFCE00; }' +
'#portalslist .filterAll { margin-top: 10px;}' +
'#portalslist .filterRes { margin-top: 10px; background-color: #005684 }' +
'#portalslist .filterEnl { margin-top: 10px; background-color: #017f01 }' +
'#portalslist .disclaimer { margin-top: 10px; font-size:10px; }' +
'#portalslist .portalTitle { display: inline-block; width: 160px !important; min-width: 160px !important; max-width: 160px !important; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }' +
'</style>');
// 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));
});
}
// PLUGIN END //////////////////////////////////////////////////////////
@@PLUGINEND@@

View File

@ -0,0 +1,340 @@
// ==UserScript==
// @id iitc-plugin-scoreboard@vita10gy
// @name IITC plugin: show a localized scoreboard.
// @category Info
// @version 0.1.9.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] A localized scoreboard.
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @grant none
// ==/UserScript==
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
// use own namespace for plugin
window.plugin.scoreboard = function() {};
window.plugin.scoreboard.scores = {};
window.plugin.scoreboard.playerGuids = new Array();
window.plugin.scoreboard.resetTeam = function(team) {
var scores = window.plugin.scoreboard.scores['team'];
scores[team] = {};
scores[team]['mu'] = 0;
scores[team]['count_fields'] = 0;
scores[team]['count_links'] = 0;
scores[team]['count_portals'] = 0;
scores[team]['count_resonators'] = 0;
scores[team]['count_mods'] = 0;
scores[team]['link_length'] = 0;
scores[team]['field_area'] = 0;
scores[team]['largest'] = {};
};
window.plugin.scoreboard.initPlayer = function(player, team) {
var scores = window.plugin.scoreboard.scores['player'];
if(scores[player] === undefined) {
scores[player] = {};
scores[player]['team'] = team;
scores[player]['mu'] = 0;
scores[player]['count_fields'] = 0;
scores[player]['count_links'] = 0;
scores[player]['count_portals'] = 0;
scores[player]['count_resonators'] = 0;
scores[player]['link_length'] = 0;
scores[player]['field_area'] = 0;
scores[player]['count_mods'] = 0;
scores[player]['largest'] = {};
window.plugin.scoreboard.playerGuids.push(player);
}
}
window.plugin.scoreboard.compileStats = function() {
var somethingInView = false;
window.plugin.scoreboard.playerGuids = new Array();
window.plugin.scoreboard.scores = {'team': {}, 'player': {}};
var scores = window.plugin.scoreboard.scores;
window.plugin.scoreboard.resetTeam(TEAM_RES);
window.plugin.scoreboard.resetTeam(TEAM_ENL);
$.each(window.fields, function(qk, val) {
var team = getTeam(val.options.data);
// Google sends fields long since dead in the data. This makes sure it's still actually up.
if(window.portals[val.options.vertices.vertexA.guid] !== undefined ||
window.portals[val.options.vertices.vertexB.guid] !== undefined ||
window.portals[val.options.vertices.vertexC.guid] !== undefined ) {
var fieldArea = window.plugin.scoreboard.fieldArea(val);
somethingInView = true;
scores['team'][team]['count_fields']++;
scores['team'][team]['field_area'] += fieldArea;
val.options.data.fieldArea = fieldArea;
var largestArea = scores['team'][team]['largest']['field_area'];
if(largestArea === undefined || largestArea.options.data.fieldArea < val.options.data.fieldArea) {
largestArea = val;
}
scores['team'][team]['largest']['field_area'] = largestArea;
}
});
$.each(window.links, function(qk, link) {
somethingInView = true;
var team = getTeam(link.options.data);
scores['team'][team]['count_links']++;
var linkLength = window.plugin.scoreboard.portalDistance(link.options.data.edge.destinationPortalLocation,link.options.data.edge.originPortalLocation);
scores['team'][team]['link_length'] += linkLength;
var largestLink = scores['team'][team]['largest']['link'];
if(largestLink === undefined || largestLink.distance < linkLength) {
largestLink = {};
largestLink.distance = linkLength;
}
scores['team'][team]['largest']['link'] = largestLink;
});
$.each(window.portals, function(qk, portal) {
somethingInView = true;
var team = getTeam(portal.options.details);
if(team !== TEAM_NONE) {
var player = portal.options.details.captured.capturingPlayerId;
window.plugin.scoreboard.initPlayer(player, team);
scores['team'][team]['count_portals']++;
scores['player'][player]['count_portals']++;
$.each(portal.options.details.portalV2.linkedModArray, function(ind, mod) {
if(mod !== null) {
window.plugin.scoreboard.initPlayer(mod.installingUser, team);
somethingInView = true;
scores['team'][team]['count_mods']++;
scores['player'][mod.installingUser]['count_mods']++;
}
});
$.each(portal.options.details.resonatorArray.resonators, function(ind, reso) {
if(reso !== null) {
somethingInView = true;
window.plugin.scoreboard.initPlayer(reso.ownerGuid, team);
scores['team'][team]['count_resonators']++;
scores['player'][reso.ownerGuid]['count_resonators']++;
}
});
}
});
return somethingInView;
};
window.plugin.scoreboard.teamTableRow = function(field,title) {
var scores = window.plugin.scoreboard.scores['team'];
var retVal = '<tr><td>'
+ title
+ '</td><td class="number">'
+ window.digits(Math.round(scores[TEAM_RES][field]))
+ '</td><td class="number">'
+ window.digits(Math.round(scores[TEAM_ENL][field]))
+ '</td><td class="number">'
+ window.digits(Math.round(scores[TEAM_RES][field] + scores[TEAM_ENL][field]))
+ '</td></tr>';
return retVal;
};
window.plugin.scoreboard.fieldInfoArea = function(field) {
var title = '';
var retVal = '';
if(field !== undefined) {
var portal = window.portals[field.options.vertices.vertexA.guid];
if(portal !== undefined) {
title = ' @' + portal.options.details.portalV2.descriptiveText.TITLE;
}
retVal = '<div title="' + title + '">'
+ window.digits(Math.round(field.options.data.fieldArea))
+ '</div>';
} else {
retVal = 'N/A';
}
return retVal;
};
window.plugin.scoreboard.playerTableRow = function(playerGuid) {
var scores = window.plugin.scoreboard.scores['player'];
var retVal = '<tr class="'
+ (scores[playerGuid]['team'] === TEAM_RES ? 'res' : 'enl')
+'"><td>'
+ window.getPlayerName(playerGuid);
+ '</td>';
$.each(['count_portals','count_resonators','count_mods'], function(i, field) {
retVal += '<td class="number">'
+ window.digits(Math.round(scores[playerGuid][field]))
+ '</td>';
});
retVal += '</tr>';
return retVal;
};
window.plugin.scoreboard.playerTable = function(sortBy) {
// Sort the playerGuid array by sortBy
window.plugin.scoreboard.playerGuids.sort(function(a, b) {
var playerA = window.plugin.scoreboard.scores['player'][a];
var playerB = window.plugin.scoreboard.scores['player'][b];
var retVal = 0;
if(sortBy === 'names') {
retVal = window.getPlayerName(a).toLowerCase() < window.getPlayerName(b).toLowerCase() ? -1 : 1;
} else {
retVal = playerB[sortBy] - playerA[sortBy];
}
return retVal;
});
var sort = window.plugin.scoreboard.playerTableSort;
var scoreHtml = '<table>'
+ '<tr><th ' + sort('names', sortBy) + '>Player</th>'
+ '<th ' + sort('count_portals', sortBy) + '>Portals</th>'
+ '<th ' + sort('count_resonators', sortBy) + '>Resonators</th>'
+ '<th ' + sort('count_mods', sortBy) + '>Mods</th></tr>';
$.each(window.plugin.scoreboard.playerGuids, function(index, guid) {
scoreHtml += window.plugin.scoreboard.playerTableRow(guid);
});
scoreHtml += '</table>';
return scoreHtml;
}
// A little helper function so the above isn't so messy
window.plugin.scoreboard.playerTableSort = function(name, by) {
var retVal = 'data-sort="' + name + '"';
if(name === by) {
retVal += ' class="sorted"';
}
return retVal;
};
window.plugin.scoreboard.display = function() {
var somethingInView = window.plugin.scoreboard.compileStats();
var scores = window.plugin.scoreboard.scores;
var scoreHtml = '';
var title = '';
if(somethingInView) {
scoreHtml += '<table>'
+ '<tr><th></th><th class="number">Resistance</th><th class="number">Enlightened</th><th class="number">Total</th></tr>'
+ window.plugin.scoreboard.teamTableRow('count_fields','Field #')
+ window.plugin.scoreboard.teamTableRow('field_area','Field (km&sup2;)')
+ window.plugin.scoreboard.teamTableRow('count_links','Link #')
+ window.plugin.scoreboard.teamTableRow('link_length','Link (m)')
+ window.plugin.scoreboard.teamTableRow('count_portals','Portals')
+ window.plugin.scoreboard.teamTableRow('count_resonators','Resonators')
+ window.plugin.scoreboard.teamTableRow('count_mods','Mods')
+ '</table>';
scoreHtml += '<table>'
+ '<tr><th></th><th>Resistance</th><th>Enlightened</th></tr>'
+ '<tr><td>Largest Field (km&sup2;)</td><td>'
+ window.plugin.scoreboard.fieldInfoArea(scores['team'][TEAM_RES]['largest']['field_area'])
+ '</td><td>'
+ window.plugin.scoreboard.fieldInfoArea(scores['team'][TEAM_ENL]['largest']['field_area'])
+ '</td></tr>'
+ '<tr><td>Longest Link (m)</td><td>';
if(scores['team'][TEAM_RES]['largest']['link'] === undefined) {
scoreHtml += 'N/A';
}
else {
scoreHtml += window.digits(Math.round(scores['team'][TEAM_RES]['largest']['link']['distance']));
}
scoreHtml += '</td><td>';
if(scores['team'][TEAM_ENL]['largest']['link'] === undefined) {
scoreHtml += 'N/A';
}
else {
scoreHtml += window.digits(Math.round(scores['team'][TEAM_ENL]['largest']['link']['distance']));
}
scoreHtml += '</td></tr>'
+ '</table>'
+ '<div id="players">'
+ window.plugin.scoreboard.playerTable('count_portals')
+ '</div>';
scoreHtml += '<div class="disclaimer">Click on player table headers to sort by that column. '
+ 'Score is subject to portals available based on zoom level. '
+ 'If names are unresolved try again. For best results wait until updates are fully loaded.</div>';
} else {
scoreHtml += 'You need something in view.';
title = 'nothing in view';
}
dialog({
html: '<div id="scoreboard">' + scoreHtml + '</div>',
title: 'Scoreboard: ' + title,
dialogClass: 'ui-dialog-scoreboard',
id: 'scoreboard'
});
//run the name resolving process
resolvePlayerNames();
}
window.plugin.scoreboard.portalDistance = function(portalAE6Location, portalBE6Location) {
portalA = new L.LatLng(portalAE6Location.latE6 / 1E6, portalAE6Location.lngE6 / 1E6);
portalB = new L.LatLng(portalBE6Location.latE6 / 1E6, portalBE6Location.lngE6 / 1E6);
return (portalA.distanceTo(portalB));
}
window.plugin.scoreboard.fieldArea = function(field) {
var verts = field.options.vertices;
var sideA = window.plugin.scoreboard.portalDistance(verts.vertexA.location,verts.vertexB.location) / 1000;
var sideB = window.plugin.scoreboard.portalDistance(verts.vertexB.location,verts.vertexC.location) / 1000;
var sideC = window.plugin.scoreboard.portalDistance(verts.vertexC.location,verts.vertexA.location) / 1000;
// Heron's Formula;
var perimeter = sideA + sideB + sideC;
var s = perimeter/2;
return Math.sqrt(s*(s-sideA)*(s-sideB)*(s-sideC));
}
var setup = function() {
$('#toolbox').append(' <a onclick="window.plugin.scoreboard.display()" title="Display a scoreboard per team for the current view">Scoreboard</a>');
$('head').append('<style>' +
'.ui-dialog-scoreboard {width: auto !important; min-width: 400px !important; max-width: 600px !important;}' +
'#scoreboard table {margin-top:10px; border-collapse: collapse; empty-cells: show; width:100%; clear: both;}' +
'#scoreboard table td, #scoreboard table th {border-bottom: 1px solid #0b314e; padding:3px; color:white; background-color:#1b415e}' +
'#scoreboard table tr.res td { background-color: #005684; }' +
'#scoreboard table tr.enl td { background-color: #017f01; }' +
'#scoreboard table tr:nth-child(even) td { opacity: .8 }' +
'#scoreboard table tr:nth-child(odd) td { color: #ddd !important; }' +
'#scoreboard table th { text-align:left }' +
'#scoreboard table td.number, #scoreboard table th.number { text-align:right }' +
'#players table th { cursor:pointer; text-align: right;}' +
'#players table th:nth-child(1) { text-align: left;}' +
'#scoreboard table th.sorted { color:#FFCE00; }' +
'#scoreboard .disclaimer { margin-top:10px; font-size:10px; }' +
'.mu_score { margin-bottom: 10px; }' +
'.mu_score span { overflow: hidden; padding-top:2px; padding-bottom: 2px; display: block; font-weight: bold; float: left; box-sizing: border-box; -moz-box-sizing:border-box; -webkit-box-sizing:border-box; }' +
'.mu_score span.res { background-color: #005684; text-align: right; padding-right:4px; }' +
'.mu_score span.enl { background-color: #017f01; padding-left: 4px; }' +
'</style>');
// Setup sorting
$(document).on('click', '#players table th', function() {
$('#players').html(window.plugin.scoreboard.playerTable($(this).data('sort')));
});
}
// PLUGIN END //////////////////////////////////////////////////////////
@@PLUGINEND@@