diff --git a/code/boot.js b/code/boot.js index 1d12689b..f3ffd98e 100644 --- a/code/boot.js +++ b/code/boot.js @@ -1,5 +1,4 @@ - // SETUP ///////////////////////////////////////////////////////////// // these functions set up specific areas after the boot function // created a basic framework. All of these functions should only ever @@ -104,10 +103,10 @@ window.setupStyles = function() { window.setupMap = function() { $('#map').text(''); - var osmOpt = {attribution: 'Map data © OpenStreetMap contributors', maxZoom: 18}; + var osmOpt = {attribution: 'Map data © OpenStreetMap contributors', maxZoom: 18, detectRetina: true}; var osm = new L.TileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', osmOpt); - var cmOpt = {attribution: 'Map data © OpenStreetMap contributors, Imagery © CloudMade', maxZoom: 18}; + var cmOpt = {attribution: 'Map data © OpenStreetMap contributors, Imagery © CloudMade', maxZoom: 18, detectRetina: true}; var cmMin = new L.TileLayer('http://{s}.tile.cloudmade.com/654cef5fd49a432ab81267e200ecc502/22677/256/{z}/{x}/{y}.png', cmOpt); var cmMid = new L.TileLayer('http://{s}.tile.cloudmade.com/654cef5fd49a432ab81267e200ecc502/999/256/{z}/{x}/{y}.png', cmOpt); diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java b/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java index ea8d65b2..7a1c1db9 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java @@ -1,5 +1,7 @@ package com.cradle.iitc_mobile; +import java.io.IOException; + import com.cradle.iitc_mobile.R; import android.net.Uri; @@ -111,6 +113,11 @@ public class IITC_Mobile extends Activity { switch (item.getItemId()) { case R.id.reload_button: iitc_view.reload(); + try { + iitc_view.getWebViewClient().loadIITC_JS(this); + } catch (IOException e1) { + e1.printStackTrace(); + } return true; // print version number case R.id.version_num: diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java b/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java index 9440df04..745060fa 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java @@ -55,4 +55,8 @@ public class IITC_WebView extends WebView { } //---------------------------------------------------------------- + public IITC_WebViewClient getWebViewClient() { + return this.webclient; + } + } diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java b/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java index 8da836d6..0ef26879 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java @@ -16,7 +16,7 @@ public class IITC_WebViewClient extends WebViewClient { "body, #dashboard_container, #map_canvas { background: #000 !important; }".getBytes()); private static final ByteArrayInputStream empty = new ByteArrayInputStream("".getBytes()); - private static WebResourceResponse iitcjs; + private WebResourceResponse iitcjs; public IITC_WebViewClient(Context c) { try { @@ -26,7 +26,7 @@ public class IITC_WebViewClient extends WebViewClient { } } - private static void loadIITC_JS(Context c) throws java.io.IOException { + public void loadIITC_JS(Context c) throws java.io.IOException { InputStream input; input = c.getAssets().open("iitc.js"); @@ -59,7 +59,6 @@ public class IITC_WebViewClient extends WebViewClient { // with our own content. This is used to block loading Niantic resources // which aren’t required and to inject IITC early into the site. // via http://stackoverflow.com/a/8274881/1684530 - @SuppressWarnings("static-access") @Override public WebResourceResponse shouldInterceptRequest (final WebView view, String url) { if(url.contains("/css/common.css")) { diff --git a/plugins/scoreboard.user.js b/plugins/scoreboard.user.js new file mode 100644 index 00000000..f7ddffa4 --- /dev/null +++ b/plugins/scoreboard.user.js @@ -0,0 +1,324 @@ +// ==UserScript== +// @id iitc-plugin-scoreboard@vita10gy +// @name iitc: show a localized scoreboard. +// @version 0.1.1 +// @namespace https://github.com/breunigs/ingress-intel-total-conversion +// @updateURL https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/scoreboard.user.js +// @downloadURL https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/scoreboard.user.js +// @description A localized scoreboard. +// @include https://www.ingress.com/intel* +// @match https://www.ingress.com/intel* +// ==/UserScript== + +function wrapper() { +// ensure plugin framework is there, even if iitc is not yet loaded +if(typeof window.plugin !== 'function') window.plugin = function() {}; + + +// 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]['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]['count_shields'] = 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); + var player = val.options.data.creator.creatorGuid; + + window.plugin.scoreboard.initPlayer(player,team); + + // 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 ) { + + somethingInView = true; + scores['team'][team]['mu'] += parseInt(val.options.data.entityScore.entityScore); + scores['player'][player]['mu'] += parseInt(val.options.data.entityScore.entityScore); + scores['team'][team]['count_fields']++; + scores['player'][player]['count_fields']++; + + var largestMu = scores['team'][team]['largest']['mu']; + if(largestMu === undefined || parseInt(largestMu.options.data.entityScore.entityScore) < parseInt(val.options.data.entityScore.entityScore)) { + largestMu = val; + } + scores['team'][team]['largest']['mu'] = largestMu; + + var largestMu = scores['player'][player]['largest']['mu']; + if(largestMu === undefined || parseInt(largestMu.options.data.entityScore.entityScore) < parseInt(val.options.data.entityScore.entityScore)) { + largestMu = val; + } + scores['player'][player]['largest']['mu'] = largestMu; + } + }); + $.each(window.links, function(qk, link) { + somethingInView = true; + var team = getTeam(link.options.data); + var player = link.options.data.creator.creatorGuid; + window.plugin.scoreboard.initPlayer(player, team); + scores['team'][team]['count_links']++; + scores['player'][player]['count_links']++; + }); + $.each(window.portals, function(qk, portal) { + somethingInView = true; + var team = getTeam(portal.options.details); + 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) { + // somethingInView = true; + // scores['team'][team]['count_shields']++; + // scores['player'][mod.installingUser]['count_shields']++; + // } + //}); + + $.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.percentSpan = function(percent, cssClass) { + var retVal = ''; + if(percent > 0) { + retVal += '' + percent; + if(percent >= 7) { // anything less than this and the text doesnt fit in the span. + retVal += '%'; + } + retVal += ''; + } + return retVal; +}; + +window.plugin.scoreboard.teamTableRow = function(field,title) { + var scores = window.plugin.scoreboard.scores['team']; + var retVal = '' + + title + + '' + + window.digits(scores[TEAM_RES][field]) + + '' + + window.digits(scores[TEAM_ENL][field]) + + '' + + window.digits(scores[TEAM_RES][field] + scores[TEAM_ENL][field]) + + ''; + return retVal; +}; + +window.plugin.scoreboard.fieldInfo = 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 = '
' + + field.options.data.entityScore.entityScore + + ' - ' + window.getPlayerName(field.options.data.creator.creatorGuid) + + '
'; + } else { + retVal = 'N/A'; + } + return retVal; +}; + +window.plugin.scoreboard.playerTableRow = function(playerGuid) { + var scores = window.plugin.scoreboard.scores['player']; + var retVal = '' + + window.getPlayerName(playerGuid); + + ''; + + $.each(['mu','count_fields','count_links','count_portals','count_resonators'], function(i, field) { + retVal += '' + + window.digits(scores[playerGuid][field]) + + ''; + }); + retVal += ''; + 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 = '' + + '' + + '' + + '' + + '' + + '' + + ''; + $.each(window.plugin.scoreboard.playerGuids, function(index, guid) { + scoreHtml += window.plugin.scoreboard.playerTableRow(guid); + }); + scoreHtml += '
PlayerMuFieldsLinksPortalsResonators
'; + + return scoreHtml; +} + +// A little helper functon 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 resMu = scores['team'][TEAM_RES]['mu']; + var enlMu = scores['team'][TEAM_ENL]['mu']; + var scoreHtml = ''; + + if(somethingInView) { + + if(resMu + enlMu > 0) { + var resMuPercent = Math.round((resMu / (resMu + enlMu)) * 100); + scoreHtml += '
' + + window.plugin.scoreboard.percentSpan(resMuPercent, 'res') + + window.plugin.scoreboard.percentSpan(100-resMuPercent, 'enl') + + '
'; + } + + scoreHtml += '' + + '' + + window.plugin.scoreboard.teamTableRow('mu','Mu') + + window.plugin.scoreboard.teamTableRow('count_fields','Fields') + + window.plugin.scoreboard.teamTableRow('count_links','Links') + + window.plugin.scoreboard.teamTableRow('count_portals','Portals') + + window.plugin.scoreboard.teamTableRow('count_resonators','Resonators') + + '
ResistanceEnlightenedTotal
'; + + scoreHtml += '' + + '' + + '' + + '
ResistanceEnlightened
Largest Field' + + window.plugin.scoreboard.fieldInfo(scores['team'][TEAM_RES]['largest']['mu']) + + '' + + window.plugin.scoreboard.fieldInfo(scores['team'][TEAM_ENL]['largest']['mu']) + + '
'; + + scoreHtml += '
' + + window.plugin.scoreboard.playerTable('mu') + + '
'; + + scoreHtml += '
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.
'; + } else { + scoreHtml += 'You need something in view.'; + } + + alert('
' + scoreHtml + '
'); + $(".ui-dialog").addClass('ui-dialog-scoreboard'); + + // Setup sorting + $(document).on('click', '#players table th', function() { + $('#players').html(window.plugin.scoreboard.playerTable($(this).data('sort'))); + }); +} + +var setup = function() { + $('body').append(''); + $('#toolbox').append('scoreboard'); + $('head').append(''); +} + +// PLUGIN END ////////////////////////////////////////////////////////// + +if(window.iitcLoaded && typeof setup === 'function') { + setup(); +} else { + if(window.bootPlugins) + window.bootPlugins.push(setup); + else + window.bootPlugins = [setup]; +} +} // wrapper end +// inject code into site context +var script = document.createElement('script'); +script.appendChild(document.createTextNode('('+ wrapper +')();')); +(document.body || document.head || document.documentElement).appendChild(script);