Merge pull request #13 from jonatkins/master

Pull from upstream.
This commit is contained in:
nexushoratio 2013-12-08 22:36:50 -08:00
commit d66472a316
20 changed files with 281 additions and 908 deletions

View File

@ -12,49 +12,53 @@
;(function(){
var requestParameterMunges = [
// obsolete munge sets (they don't have some of the new parameters) deleted
// all old munge sets deleted - there's no sign that any old ones will become active again
// set 10 - 2013-11-27
// set 11 - 2013-12-06
{
'dashboard.getArtifactInfo': 'artifacts', // GET_ARTIFACT_INFO
'dashboard.getGameScore': '4oid643d9zc168hs', // GET_GAME_SCORE
'dashboard.getPaginatedPlexts': 's1msyywq51ntudpe', // GET_PAGINATED_PLEXTS
'dashboard.getThinnedEntities': '4467ff9bgxxe4csa', // GET_THINNED_ENTITIES
'dashboard.getPortalDetails': 'c00thnhf1yp3z6mn', // GET_PORTAL_DETAILS
'dashboard.redeemReward': '66l9ivg39ygfqqjm', // REDEEM_REWARD
'dashboard.sendInviteEmail': 'cgb7hi5hglv0xx8k', // SEND_INVITE_EMAIL
'dashboard.sendPlext': 'etn9xq7brd6947kq', // SEND_PLEXT
'dashboard.redeemReward': 'ivshfv9zvyfxyqcd', // REDEEM_REWARD
'dashboard.sendInviteEmail': '1rsx15vc0m8wwdax', // SEND_INVITE_EMAIL
'dashboard.sendPlext': 'tods2imd0xcfsug6', // SEND_PLEXT
// common parameters
method: 'yyngyttbmmbuvdpa',
version: 'avz401t36lzrapis',
version_parameter: 'c5d0a5d608f729a1232bebdc12fb86ba5fb6c43f',
method: '0wvzluo8av4sk17f',
version: 'paeh4g353xu06kfg',
version_parameter: '4acc1e3230c3fd66be3422c0df8dc637336bbd7c',
// GET_THINNED_ENTITIES
quadKeys: '1mpmxz2yun22rwnn',
quadKeys: 'ilgv0w4dlldky1yh',
// GET_PORTAL_DETAILS
guid: '7o8tzmj6oxz1n5w3',
// REDEEM_REWARD
passcode: 'passcode', // no munging on this parameter
// SEND_INVITE_EMAIL
inviteeEmailAddress: 'p4rwszdfovuwfdgp',
// GET_PAGINATED_PLEXTS
desiredNumItems: 'nzd23jqm9k1cnnij',
minLatE6: '0dod6onpa1s4fezp',
minLngE6: 'soass3t7mm7anneo',
maxLatE6: 'cvarmr3o00ngylo1',
maxLngE6: 'udzwnlx07hzd3bfo',
minTimestampMs: '9iiiks138gkf8xho',
maxTimestampMs: '94wm0u3sc3sgzq7x',
chatTab: 'tqfj4a3okzn5v5o1',
ascendingTimestampOrder: '5jv1m90sq35u6utq',
desiredNumItems: 'kxsbuvc90l6f40xn',
minLatE6: 'llizye3i5dbapxac',
minLngE6: 'w01zpiba1mn5tsab',
maxLatE6: 'd5phhqzj2tbsq599',
maxLngE6: 'avq5srnvg431aehn',
minTimestampMs: 'mhsav5by25wi4s46',
maxTimestampMs: 'hpu7l8h7eccwytyt',
chatTab: 'q9343nem7hs1v37b',
ascendingTimestampOrder: '7pc5c9ggh03pig1b',
// SEND_PLEXT
message: '8exta9k7y8huhqmc',
latE6: 'kqek161gza3kjcry',
lngE6: '3dlxsqrjj2vcmhbc',
// chatTab: 'efaznrayv5n3jxs0', //guessed parameter name - only seen munged
latE6: '7ffwyf3zd2yf8xam',
lngE6: 'n7ewiach2v22iy20',
// chatTab: 'q9343nem7hs1v37b', // duplicate from GET_PAGINATED_PLEXTS
// GET_PORTAL_DETAILS
guid: 'seg6ohxgnqf9xu9w',
// SEND_INVITE_EMAIL
inviteeEmailAddress: '8exta9k7y8huhqmc',
},
];

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 892 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 393 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 601 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 712 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 958 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -19,20 +19,20 @@
android:showAsAction="ifRoom"
android:title="@string/layer_chooser">
</item>
<item
android:id="@+id/reload_button"
android:icon="@drawable/ic_action_refresh"
android:orderInCategory="110"
android:showAsAction="never"
android:title="@string/reload">
</item>
<item
android:id="@+id/toggle_fullscreen"
android:icon="@drawable/ic_action_full_screen"
android:orderInCategory="120"
android:orderInCategory="110"
android:showAsAction="ifRoom"
android:title="@string/toggle_fullscreen">
</item>
<item
android:id="@+id/reload_button"
android:icon="@drawable/ic_action_refresh"
android:orderInCategory="120"
android:showAsAction="ifRoom"
android:title="@string/reload">
</item>
<item
android:id="@+id/menu_clear_cookies"
android:orderInCategory="130"
@ -41,7 +41,6 @@
</item>
<item
android:id="@+id/action_settings"
android:icon="@drawable/ic_action_settings"
android:orderInCategory="200"
android:showAsAction="never"
android:title="@string/action_settings">

View File

@ -150,9 +150,9 @@
<string name="msg_copied">Copied to clipboard…</string>
<string name="notice_do_not_show_again">Do not show again</string>
<string name="tab_map">Map</string>
<string name="tab_map">Locate</string>
<string name="tab_share">Share</string>
<string name="tab_browser">Browser</string>
<string name="tab_browser">Intel</string>
<string name="label_highlighter">Highlighter</string>
<string name="label_base_layer">Base Layer</string>

View File

@ -324,6 +324,12 @@ public class IITC_Mobile extends Activity implements OnSharedPreferenceChangeLis
super.onStop();
}
@Override
protected void onDestroy() {
unregisterReceiver(mBroadcastReceiver);
super.onDestroy();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);

View File

@ -71,7 +71,15 @@ public class IITC_WebView extends WebView {
@Override
public void run() {
if (isInFullscreen() && (getFullscreenStatus() & (FS_NAVBAR)) != 0) {
setSystemUiVisibility(SYSTEM_UI_FLAG_HIDE_NAVIGATION);
int systemUiVisibility = SYSTEM_UI_FLAG_HIDE_NAVIGATION;
// in immersive mode the user can interact with the app while the navbar is hidden
// this mode is available since KitKat
// you can leave this mode by swiping down from the top of the screen. this does only work
// when the app is in total-fullscreen mode
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && (mFullscreenStatus & FS_SYSBAR) != 0) {
systemUiVisibility |= SYSTEM_UI_FLAG_IMMERSIVE;
}
setSystemUiVisibility(systemUiVisibility);
}
}
};
@ -165,12 +173,7 @@ public class IITC_WebView extends WebView {
public void loadJS(String js) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
evaluateJavascript(js, new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
// maybe we want to add stuff here
}
});
evaluateJavascript(js, null);
} else {
// if in edit text mode, don't load javascript otherwise the keyboard closes.
HitTestResult testResult = getHitTestResult();
@ -190,20 +193,22 @@ public class IITC_WebView extends WebView {
@Override
public boolean onTouchEvent(MotionEvent event) {
getHandler().removeCallbacks(mNavHider);
getHandler().postDelayed(mNavHider, 2000);
getHandler().postDelayed(mNavHider, 3000);
return super.onTouchEvent(event);
}
@Override
public void setSystemUiVisibility(int visibility) {
getHandler().postDelayed(mNavHider, 2000);
if ((visibility & SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) {
getHandler().postDelayed(mNavHider, 3000);
}
super.setSystemUiVisibility(visibility);
}
@Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
if (hasWindowFocus) {
getHandler().postDelayed(mNavHider, 2000);
getHandler().postDelayed(mNavHider, 3000);
} else {
getHandler().removeCallbacks(mNavHider);
}
@ -225,7 +230,7 @@ public class IITC_WebView extends WebView {
attrs.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
}
if ((mFullscreenStatus & FS_NAVBAR) != 0) {
setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
getHandler().post(mNavHider);
}
if ((mFullscreenStatus & FS_STATUSBAR) != 0) {
loadUrl("javascript: $('#updatestatus').hide();");

View File

@ -9,6 +9,7 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
@ -37,6 +38,10 @@ public class IntentListView extends ListView {
}
private class IntentAdapter extends ArrayAdapter<ResolveInfo> {
// actually the mdpi pixel size is 48, but this looks ugly...so scale icons down for listView
private static final int MDPI_PX = 36;
private IntentAdapter() {
super(IntentListView.this.getContext(), android.R.layout.simple_list_item_1);
}
@ -48,11 +53,19 @@ public class IntentListView extends ListView {
ActivityInfo info = getItem(position).activityInfo;
CharSequence label = info.loadLabel(mPackageManager);
// get icon and scale it manually to ensure that all have the same size
Drawable icon = info.loadIcon(mPackageManager);
DisplayMetrics dm = new DisplayMetrics();
((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(dm);
float densityScale = dm.density;
float scaledWidth = MDPI_PX * densityScale;
float scaledHeight = MDPI_PX * densityScale;
icon.setBounds(0,0,Math.round(scaledWidth),Math.round(scaledHeight));
view.setText(label);
view.setCompoundDrawablePadding((int) getResources().getDimension(R.dimen.icon_margin));
view.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);
view.setCompoundDrawables(icon, null, null, null);
return view;
}

View File

@ -81,7 +81,7 @@ public class ShareActivity extends FragmentActivity implements ActionBar.TabList
String geoUri = "geo:" + mLl;
Intent geoIntent = new Intent(android.content.Intent.ACTION_VIEW, Uri.parse(geoUri));
intents.add(geoIntent);
addTab(intents, R.string.tab_map, R.drawable.ic_action_map);
addTab(intents, R.string.tab_map, R.drawable.ic_action_place);
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(getUrl()));
addTab(intent, R.string.tab_browser, R.drawable.ic_action_web_site);
@ -122,6 +122,9 @@ public class ShareActivity extends FragmentActivity implements ActionBar.TabList
setupShareIntent(intent.getStringExtra("shareString"));
}
// show portal name as action bar title, if available
if (mTitle != getString(R.string.app_name)) actionBar.setTitle(mTitle);
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mFragmentAdapter);

View File

@ -2,7 +2,7 @@
// @id iitc-plugin-bing-maps
// @name IITC plugin: Bing maps
// @category Map Tiles
// @version 0.1.1.@@DATETIMEVERSION@@
// @version 0.1.2.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
@ -23,7 +23,7 @@ window.plugin.mapBing = function() {};
window.plugin.mapBing.setupBingLeaflet = function() {
@@INCLUDERAW:external/Bing.js@@
}
window.plugin.mapBing.setup = function() {
window.plugin.mapBing.setupBingLeaflet();
@ -37,12 +37,35 @@ window.plugin.mapBing.setup = function() {
'AerialWithLabels': "Aerial with labels",
};
// bing maps has an annual usage limit, which will likely be hit in 6 months at this time.
// it seems that the usage is counted on initialising the L.BingLayer, when the metadata is retrieved.
// so, we'll create some dummy layers and add those to the map, then, the first time a layer is added,
// create the L.BingLayer. This will eliminate all usage for users who install but don't use the map,
// and only create usage for the map layers actually selected in use
var bingMapContainers = [];
for (type in bingTypes) {
var name = bingTypes[type];
var bingMap = new L.BingLayer(bingApiKey, {type: type, maxZoom:20});
layerChooser.addBaseLayer(bingMap, 'Bing '+name);
bingMapContainers[type] = new L.LayerGroup();
layerChooser.addBaseLayer(bingMapContainers[type], 'Bing '+name);
}
// now a leaflet event to catch base layer changes and create a L.BingLayer when needed
map.on('baselayerchange', function(e) {
for (type in bingMapContainers) {
if (e.layer == bingMapContainers[type]) {
if (bingMapContainers[type].getLayers().length == 0) {
// dummy layer group is empty - create the bing layer
console.log('basemap-bing: creating '+type+' layer');
var bingMap = new L.BingLayer (bingApiKey, {type: type, maxZoom:20});
bingMapContainers[type].addLayer(bingMap);
}
}
}
});
};
var setup = window.plugin.mapBing.setup;

View File

@ -1,811 +0,0 @@
// ==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

@ -1,15 +1,116 @@
// ==UserScript==
// @id iitc-plugin-draw-resonators@xelio
// @name IITC plugin: Draw resonators
// @category Deleted
// @version 0.4.0.@@DATETIMEVERSION@@
// @category Layer
// @version 0.4.1.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description PLUGIN CURRENTLY UNAVAILABLE
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Draw resonators on map for currently selected portal.
// @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 ////////////////////////////////////////////////////////
window.RESONATOR_MIN_ZOOM = 16;
// use own namespace for plugin
window.plugin.drawResonators = function() {};
window.plugin.drawResonators.levelLayerGroup = null;
window.plugin.drawResonators.handledata = function(data) {
window.plugin.drawResonators.levelLayerGroup.clearLayers();
window.plugin.drawResonators.drawData(data);
}
window.plugin.drawResonators.drawData = function(portal) {
if(window.map.getZoom() < window.RESONATOR_MIN_ZOOM) return;
var portalDetails = portal.portalDetails;
var portalLatLng = [portalDetails.locationE6.latE6/1E6, portalDetails.locationE6.lngE6/1E6];
for(var i in portalDetails.resonatorArray.resonators) {
resoData = portalDetails.resonatorArray.resonators[i];
if(resoData === null) continue;
var resoLatLng = window.plugin.drawResonators.getResonatorLatLng(resoData.distanceToPortal, resoData.slot, portalLatLng);
var resoMarker = window.plugin.drawResonators.createResoMarker(resoData, resoLatLng);
var connMarker = window.plugin.drawResonators.createConnMarker(resoData, resoLatLng, portalLatLng);
window.plugin.drawResonators.levelLayerGroup.addLayer(resoMarker);
window.plugin.drawResonators.levelLayerGroup.addLayer(connMarker);
}
}
window.plugin.drawResonators.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.createResoMarker = function(resoData, resoLatLng) {
var resoProperty = {
fillColor: COLORS_LVL[resoData.level],
fillOpacity: resoData.energyTotal/RESO_NRG[resoData.level],
color: '#aaa',
weight: 1,
radius: 3,
opacity: 1,
clickable: false};
resoProperty.type = 'resonator';
resoProperty.details = resoData;
var reso = L.circleMarker(resoLatLng, resoProperty);
return reso;
}
window.plugin.drawResonators.createConnMarker = function(resoData, resoLatLng, portalLatLng) {
var connProperty = {
opacity: 0.25,
weight: 2,
color: '#FFA000',
dashArray: '0,10' + (new Array(25).join(',8,4')),
fill: false,
clickable: false};
connProperty.type = 'connector';
connProperty.details = resoData;
var conn = L.polyline([portalLatLng, resoLatLng], connProperty);
return conn;
}
window.plugin.drawResonators.zoomListener = function() {
if(window.map.getZoom() < window.RESONATOR_MIN_ZOOM) {
window.plugin.drawResonators.levelLayerGroup.clearLayers();
};
}
var setup = function() {
window.plugin.drawResonators.levelLayerGroup = new L.LayerGroup();
window.addLayerGroup('Draw Reso', window.plugin.drawResonators.levelLayerGroup, true);
window.addHook('portalDetailsUpdated', window.plugin.drawResonators.handledata);
window.map.on('zoomend', function() {
window.plugin.drawResonators.zoomListener();
});
}
// PLUGIN END //////////////////////////////////////////////////////////
@@PLUGINEND@@

View File

@ -2,7 +2,7 @@
// @id iitc-plugin-guess-player-levels@breunigs
// @name IITC plugin: guess player level
// @category Info
// @version 0.5.0.@@DATETIMEVERSION@@
// @version 0.5.1.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
@ -119,56 +119,80 @@ window.plugin.guessPlayerLevels.extractPortalData = function(data) {
var r = data.details.resonatorArray.resonators;
//due to the Jarvis Virus/ADA Refactor it's possible for a player to own resonators on a portal
//at a higher level than the player themselves. It is not possible to detect for sure when this
//has happened, but in many cases it will result in an impossible deployment arrangement
//(over 1 L8/7 res, over 2 L6/5 res, etc). if we detect this case, ignore all resonators owned
//by that player on the portal
/* Due to the Jarvis Virus/ADA Refactor it's possible for a player to own resonators on a portal at a higher level
than the player themselves. It is not possible to detect for sure when this has happened, but in many cases it will
result in an impossible deployment arrangement (more than 1 L8/7 res, more than 2 L6/5 res, etc). If we detect this
case, we ignore all resonators owned by that player on the portal
Hint: This can only happen to the owner of the portal, so resonators by other players can be used to determine
their minimal level */
// TODO? go further, and just ignore all resonators owned by the portal owner?
// or; have a 'guessed' level and a 'certain' level. 'certain' comes from res from non-owner, and COMM deploy
// while 'guessed' comes from resonators of the portal owner
var owner = data.details.captured && data.details.captured.capturingPlayerId || "";
var ownerModCount = 0;
data.details.portalV2.linkedModArray.forEach(function(mod) {
if(mod && mod.installingUser == owner)
ownerModCount++;
});
var perPlayerResMaxLevel = {};
var perPlayerResMaxLevelCount = {};
var players = {};
$.each(r, function(ind, reso) {
if(!reso) return true;
if(!perPlayerResMaxLevel[reso.ownerGuid] || reso.level > perPlayerResMaxLevel[reso.ownerGuid]) {
perPlayerResMaxLevel[reso.ownerGuid] = reso.level;
perPlayerResMaxLevelCount[reso.ownerGuid] = 0;
}
if (reso.level == perPlayerResMaxLevel[reso.ownerGuid]) perPlayerResMaxLevelCount[reso.ownerGuid]++;
if(!players[reso.ownerGuid]) players[reso.ownerGuid] = [];
if(players[reso.ownerGuid][reso.level] === undefined)
players[reso.ownerGuid][reso.level] = 1
else
players[reso.ownerGuid][reso.level]++;
});
$.each(perPlayerResMaxLevel, function(guid, level) {
if (perPlayerResMaxLevelCount[guid] <= window.MAX_RESO_PER_PLAYER[level]) {
window.plugin.guessPlayerLevels.savePlayerLevel(guid, level);
for(nickname in players) {
var ignore = false;
var minLevel = 0;
if(nickname == owner) {
if(ownerModCount > 2) // more than 2 mods by capturing player --> portal was flipped, ignore their resonators
continue;
var certain = false;
} else { // not deployed by owner - player must be at least that level
var certain = true;
}
});
players[nickname].forEach(function(count, level) {
if(MAX_RESO_PER_PLAYER[level] < count)
ignore = true;
if(count > 0)
minLevel = level;
});
if(ignore)
continue;
window.plugin.guessPlayerLevels.savePlayerLevel(nickname, minLevel, certain);
}
}
window.plugin.guessPlayerLevels.extractChatData = function(data) {
data.raw.result.forEach(function(msg) {
var plext = msg[2].plext;
if(plext.plextType == 'SYSTEM_BROADCAST'
&& plext.markup.length==5
&& plext.markup[0][0] == 'PLAYER'
&& plext.markup[1][0] == 'TEXT'
&& plext.markup[1][1].plain == ' deployed an '
&& plext.markup[2][0] == 'TEXT'
&& plext.markup[2][0] == 'TEXT'
&& plext.markup[3][0] == 'TEXT'
&& plext.markup[3][1].plain == ' Resonator on ') {
var nick = plext.markup[0][1].plain;
var lvl = parseInt(plext.markup[2][1].plain.substr(1));
window.plugin.guessPlayerLevels.savePlayerLevel(nick, lvl, true);
}
});
data.raw.result.forEach(function(msg) {
var plext = msg[2].plext;
if(plext.plextType == 'SYSTEM_BROADCAST'
&& plext.markup.length==5
&& plext.markup[0][0] == 'PLAYER'
&& plext.markup[1][0] == 'TEXT'
&& plext.markup[1][1].plain == ' deployed an '
&& plext.markup[2][0] == 'TEXT'
&& plext.markup[2][0] == 'TEXT'
&& plext.markup[3][0] == 'TEXT'
&& plext.markup[3][1].plain == ' Resonator on ') {
var nick = plext.markup[0][1].plain;
var lvl = parseInt(plext.markup[2][1].plain.substr(1));
window.plugin.guessPlayerLevels.savePlayerLevel(nick, lvl, true);
}
});
};
window.plugin.guessPlayerLevels.savePlayerLevel = function(nick, level, safe) {
window.plugin.guessPlayerLevels.savePlayerLevel = function(nick, level, certain) {
var cache = window.plugin.guessPlayerLevels._loadLevels();
var details = cache['#' + nick];
@ -177,7 +201,7 @@ window.plugin.guessPlayerLevels.savePlayerLevel = function(nick, level, safe) {
if(typeof details === 'number')
details = {min: 1, guessed: details};
if(safe) {
if(certain) {
if(details.min >= level)
return;

View File

@ -26,10 +26,16 @@ window.plugin.panControl.setup = function() {
try { console.log('Loading Leaflet.Pancontrol JS now'); } catch(e) {}
@@INCLUDERAW:external/L.Control.Pan.js@@
try { console.log('done loading Leaflet.Pancontrol JS'); } catch(e) {}
// prevent Pancontrol from being activated by default (e.g. in minimap)
L.Map.mergeOptions({
panControl: false
});
window.map.panControl = L.control.pan({panOffset: 350});
window.map.addControl(window.map.panControl);
if(map.zoomControl._map) { // Move above the zoom control
window.map.removeControl(map.zoomControl);
window.map.zoomControl = L.control.zoom();