Merge remote-tracking branch 'upstream/gh-pages' into gh-pages

Conflicts:
	style.css
This commit is contained in:
Jon Atkins 2013-02-11 13:33:10 +00:00
commit ece492f1ca
10 changed files with 142 additions and 62 deletions

View File

@ -81,6 +81,7 @@ Contributors
[JasonMillward](https://github.com/JasonMillward),
[mledoze](https://github.com/mledoze),
[OshiHidra](https://github.com/OshiHidra),
[Pirozek](https://github.com/Pirozek),
[Scrool](https://github.com/Scrool),
[sorgo](https://github.com/sorgo),
[Xelio](https://github.com/Xelio),

View File

@ -1,10 +1,10 @@
#!/usr/bin/env python
#!/usr/bin/env python3
import glob
import time
def readfile(fn):
with open(fn, 'Ur') as f:
with open(fn, 'Ur', encoding='utf8') as f:
return f.read()
c = '\n\n'.join(map(readfile, glob.glob('code/*')))
@ -14,7 +14,7 @@ m = m.split('@@INJECTHERE@@')
m.insert(1, c)
t = '\n\n'.join(m)
with open('total-conversion-build.user.js', 'w') as f:
with open('total-conversion-build.user.js', 'w', encoding='utf8') as f:
f.write(t)
# vim: ai si ts=4 sw=4 sts=4 et

View File

@ -27,17 +27,17 @@ window.setupLargeImagePreview = function() {
window.setupStyles = function() {
$('head').append('<style>' +
[ '#map { margin-right: '+(SIDEBAR_WIDTH+2)+'px } ',
'#largepreview.enl img { border:2px solid '+COLORS[TEAM_ENL]+'; } ',
[ '#largepreview.enl img { border:2px solid '+COLORS[TEAM_ENL]+'; } ',
'#largepreview.res img { border:2px solid '+COLORS[TEAM_RES]+'; } ',
'#largepreview.none img { border:2px solid '+COLORS[TEAM_NONE]+'; } ',
'#chatcontrols { bottom: '+(CHAT_SHRINKED+24)+'px; }',
'#chat { height: '+CHAT_SHRINKED+'px; } ',
'#updatestatus { width:'+(SIDEBAR_WIDTH-2*4)+'px; } ',
'#sidebar { width:'+(SIDEBAR_WIDTH + HIDDEN_SCROLLBAR_ASSUMED_WIDTH + 2 /*border*/)+'px; } ',
'.leaflet-right { margin-right: '+(SIDEBAR_WIDTH+1)+'px } ',
'#updatestatus { width:'+(SIDEBAR_WIDTH-2*4+1)+'px; } ',
'#sidebar { width:'+(SIDEBAR_WIDTH + HIDDEN_SCROLLBAR_ASSUMED_WIDTH + 1 /*border*/)+'px; } ',
'#sidebartoggle { right:'+SIDEBAR_WIDTH+'px; } ',
'#scrollwrapper { width:'+(SIDEBAR_WIDTH + 2*HIDDEN_SCROLLBAR_ASSUMED_WIDTH)+'px; right:-'+(2*HIDDEN_SCROLLBAR_ASSUMED_WIDTH-2)+'px } ',
'#sidebar input, h2, #updatestatus { width:'+(SIDEBAR_WIDTH - 2*4)+'px !important } ',
'#sidebar input, h2 { width:'+(SIDEBAR_WIDTH - 2*4)+'px !important } ',
'#sidebar > *, #gamestat span, .imgpreview img { width:'+SIDEBAR_WIDTH+'px; }'].join("\n")
+ '</style>');
}
@ -176,16 +176,15 @@ window.setupSidebarToggle = function() {
var sidebar = $('#sidebar');
if(sidebar.is(':visible')) {
sidebar.hide();
$('#map').css('margin-right','0');
$('.leaflet-right').css('margin-right','0');
toggle.html('◢<br>◥');
toggle.css('right', '0');
} else {
sidebar.show();
$('#map').css('margin-right', SIDEBAR_WIDTH+2+'px');
$('.leaflet-right').css('margin-right', SIDEBAR_WIDTH+1+'px');
toggle.html('◣<br>◤');
toggle.css('right', SIDEBAR_WIDTH+'px');
toggle.css('right', SIDEBAR_WIDTH+1+'px');
}
window.map.invalidateSize(false);
});
}

View File

@ -216,9 +216,17 @@ window.renderPortal = function(ent) {
var team = getTeam(ent[2]);
// do nothing if portal did not change
var old = window.portals[ent[0]];
if(old && old.options.level === portalLevel && old.options.team === team)
return;
var layerGroup = portalsLayers[parseInt(portalLevel)];
var old = findEntityInLeaflet(layerGroup, window.portals, ent[0]);
if(old) {
var oo = old.options;
var u = oo.team !== team;
u = u || oo.level !== portalLevel;
// nothing for the portal changed, so dont update. Let resonators
// manage themselves if they want to be updated.
if(!u) return renderResonators(ent);
removeByGuid(ent[0]);
}
// there were changes, remove old portal
removeByGuid(ent[0]);
@ -245,7 +253,7 @@ window.renderPortal = function(ent) {
details: ent[2],
guid: ent[0]});
p.on('remove', function() {
p.on('remove', function() {
var portalGuid = this.options.guid
// remove attached resonators, skip if
@ -261,13 +269,17 @@ window.renderPortal = function(ent) {
window.portalAccessIndicator = null;
}
});
p.on('add', function() {
p.on('add', function() {
// enable for debugging
if(window.portals[this.options.guid]) throw('duplicate portal detected');
window.portals[this.options.guid] = this;
// handles the case where a selected portal gets removed from the
// map by hiding all portals with said level
if(window.selectedPortal != this.options.guid)
window.portalResetColor(this);
});
p.on('click', function() { window.renderPortalDetails(ent[0]); });
p.on('dblclick', function() {
window.renderPortalDetails(ent[0]);
@ -279,11 +291,10 @@ window.renderPortal = function(ent) {
window.runHooks('portalAdded', {portal: p});
// portalLevel contains a float, need to round down
p.addTo(portalsLayers[parseInt(portalLevel)]);
p.addTo(layerGroup);
}
window.renderResonators = function(ent) {
var portalLevel = getPortalLevel(ent[2]);
if(portalLevel < getMinPortalLevel() && ent[0] != selectedPortal) return;
@ -344,8 +355,12 @@ window.portalResetColor = function(portal) {
// renders a link on the map from the given entity
window.renderLink = function(ent) {
removeByGuid(ent[0]);
if(Object.keys(links).length >= MAX_DRAWN_LINKS) return;
if(Object.keys(links).length >= MAX_DRAWN_LINKS)
return removeByGuid(ent[0]);
// assume that links never change. If they do, they will have a
// different ID.
if(findEntityInLeaflet(linksLayer, links, ent[0])) return;
var team = getTeam(ent[2]);
var edge = ent[2].edge;
@ -366,6 +381,8 @@ window.renderLink = function(ent) {
poly.on('remove', function() { delete window.links[this.options.guid]; });
poly.on('add', function() {
// enable for debugging
if(window.links[this.options.guid]) throw('duplicate link detected');
window.links[this.options.guid] = this;
this.bringToBack();
});
@ -374,8 +391,12 @@ window.renderLink = function(ent) {
// renders a field on the map from a given entity
window.renderField = function(ent) {
window.removeByGuid(ent[0]);
if(Object.keys(fields).length >= MAX_DRAWN_FIELDS) return;
if(Object.keys(fields).length >= MAX_DRAWN_FIELDS)
return window.removeByGuid(ent[0]);
// assume that fields never change. If they do, they will have a
// different ID.
if(findEntityInLeaflet(fieldsLayer, fields, ent[0])) return;
var team = getTeam(ent[2]);
var reg = ent[2].capturedRegion;
@ -391,14 +412,37 @@ window.renderField = function(ent) {
clickable: false,
smoothFactor: 10,
vertices: ent[2].capturedRegion,
lastUpdate: ent[1],
guid: ent[0]});
if(!getPaddedBounds().intersects(poly.getBounds())) return;
poly.on('remove', function() { delete window.fields[this.options.guid]; });
poly.on('add', function() {
// enable for debugging
if(window.fields[this.options.guid]) console.warn('duplicate field detected');
window.fields[this.options.guid] = this;
this.bringToBack();
});
poly.addTo(fieldsLayer);
}
// looks for the GUID in either the layerGroup or entityHash, depending
// on which is faster. Will either return the Leaflet entity or null, if
// it does not exist.
// For example, to find a field use the function like this:
// field = findEntityInLeaflet(fieldsLayer, fields, 'asdasdasd');
window.findEntityInLeaflet = function(layerGroup, entityHash, guid) {
// fast way
if(map.hasLayer(layerGroup)) return entityHash[guid] || null;
// slow way in case the layer is currently hidden
var ent = null;
layerGroup.eachLayer(function(entity) {
if(entity.options.guid !== guid) return true;
ent = entity;
return false;
});
return ent;
}

View File

@ -19,24 +19,23 @@ window.renderPortalDetails = function(guid) {
links[link.isOrigin ? 'outgoing' : 'incoming']++;
});
function linkExpl(t) { return '<tt title="↳ incoming links\n↴ outgoing links\n• is meant to be the portal.">'+t+'</tt>'; }
var linksText = linkExpl('links')+':'+linkExpl(' ↳ ' + links.incoming+'&nbsp;&nbsp;•&nbsp;&nbsp;'+links.outgoing+' ↴');
var linksText = [linkExpl('links'), linkExpl(' ↳ ' + links.incoming+'&nbsp;&nbsp;•&nbsp;&nbsp;'+links.outgoing+' ↴')];
var player = d.captured && d.captured.capturingPlayerId
? getPlayerName(d.captured.capturingPlayerId)
: null;
var playerText = player ? 'owner: ' + player : null;
var playerText = player ? ['owner', player] : null;
var time = d.captured ? unixTimeToString(d.captured.capturedTime) : null;
var sinceText = time ? 'since: ' + time : null;
var sinceText = time ? ['since', time] : null;
var linkedFields = 'fields: ' + d.portalV2.linkedFields.length;
var linkedFields = ['fields', d.portalV2.linkedFields.length];
// collect and html-ify random data
var randDetails = [playerText, sinceText, getRangeText(d), getEnergyText(d), linksText, getAvgResoDistText(d), linkedFields];
var randDetails = [playerText, sinceText, getRangeText(d), getEnergyText(d), linksText, getAvgResoDistText(d), linkedFields, getDestroyAP(d)];
randDetails = randDetails.map(function(detail) {
if(!detail) return '';
detail = detail.split(':');
detail = '<aside>'+detail.shift()+'<span>'+detail.join(':')+'</span></aside>';
detail = '<aside>'+detail[0]+'<span>'+detail[1]+'</span></aside>';
return detail;
}).join('\n');

View File

@ -6,12 +6,12 @@
// returns displayable text+link about portal range
window.getRangeText = function(d) {
var range = getPortalRange(d);
return 'range: '
return ['range',
+ '<a onclick="window.rangeLinkClick()">'
+ (range > 1000
? Math.round(range/1000) + 'km'
: Math.round(range) + 'm')
+ '</a>';
+ '</a>'];
}
// generates description text from details for portal
@ -69,17 +69,15 @@ window.getEnergyText = function(d) {
var totalNrg = getTotalPortalEnergy(d);
var inf = currentNrg + ' / ' + totalNrg;
var fill = prettyEnergy(currentNrg) + ' / ' + prettyEnergy(totalNrg)
var meter = 'energy: <tt title="'+inf+'">' + fill + '</tt>';
return meter;
return ['energy', '<tt title="'+inf+'">' + fill + '</tt>'];
}
window.getAvgResoDistText = function(d) {
var avgDist = Math.round(10*getAvgResoDist(d))/10;
return '⌀ res dist: ' + avgDist + 'm';
return ['⌀ res dist', avgDist + 'm'];
}
window.getResonatorDetails = function(d) {
console.log('rendering reso details');
var resoDetails = '';
// octant=slot: 0=E, 1=NE, 2=N, 3=NW, 4=W, 5=SW, 6=S, SE=7
// resos in the display should be ordered like this:
@ -139,3 +137,33 @@ window.renderResonatorDetails = function(slot, level, nrg, dist, nick, isLeft) {
var text = '<span class="meter-text '+cls+'">'+(nick||'')+'</span>';
return (isLeft ? text+meter : meter+text) + '<br/>';
}
// calculate AP gain from destroying portal
// so far it counts only resonators + links
window.getDestroyAP = function(d) {
var resoCount = 0;
$.each(d.resonatorArray.resonators, function(ind, reso) {
if(!reso) return true;
resoCount += 1;
});
var linkCount = d.portalV2.linkedEdges ? d.portalV2.linkedEdges.length : 0;
var fieldCount = d.portalV2.linkedFields ? d.portalV2.linkedFields.length : 0;
var resoAp = resoCount * DESTROY_RESONATOR;
var linkAp = linkCount * DESTROY_LINK;
var fieldAp = fieldCount * DESTROY_FIELD;
var sum = resoAp + linkAp + fieldAp;
function tt(text) {
var t = 'Destroy:\n';
t += resoCount + '×\tResonators\t= ' + digits(resoAp) + '\n';
t += linkCount + '×\tLinks\t\t= ' + digits(linkAp) + '\n';
t += fieldCount + '×\tFields\t\t= ' + digits(fieldAp) + '\n';
t += 'Sum: ' + digits(sum) + ' AP';
return '<tt title="'+t+'">' + digits(text) + '</tt>';
}
return [tt('AP Gain'), tt(sum)];
}

View File

@ -50,7 +50,7 @@ window.renderUpdateStatus = function() {
t += ' <span style="color:red" class="help" title="Can only render so much before it gets unbearably slow. Not all entities are shown. Zoom in or increase the limit (search for MAX_DRAWN_*).">RENDER LIMIT</span> '
if(window.failedRequestCount > 0)
t += ' <span style="color:red">' + window.failedRequestCount + ' requests failed</span>.'
t += ' <span style="color:red">' + window.failedRequestCount + ' failed</span>.'
t += '<br/>(';
var minlvl = getMinPortalLevel();

View File

@ -160,6 +160,10 @@ window.getTypeByGuid = function(guid) {
// .c == player/creator
// .d == chat messages
//
// others, not used in web:
// .5 == resources (burster/resonator)
// .6 == XM
// .4 == media items, maybe all droppped resources (?)
// resonator guid is [portal guid]-resonator-[slot]
switch(guid.slice(33)) {
case '11':

10
main.js
View File

@ -49,7 +49,6 @@ for(var i = 0; i < d.length; i++) {
// player information is now available in a hash like this:
// window.PLAYER = {"ap": "123", "energy": 123, "available_invites": 123, "nickname": "somenick", "team": "ALIENS||RESISTANCE"};
// remove complete page. We only wanted the user-data and the pages
// security context so we can access the API easily. Setup as much as
// possible without requiring scripts.
@ -81,9 +80,9 @@ document.getElementsByTagName('body')[0].innerHTML = ''
+ ' <input id="redeem" placeholder="Redeem code…" type="text"/>'
+ ' <div id="toolbox"><a onmouseover="setPermaLink(this)">permalink</a></div>'
+ ' <div id="spacer"></div>'
+ ' <div id="updatestatus"></div>'
+ ' </div>';
+ '</div>';
+ ' </div>'
+ '</div>'
+ '<div id="updatestatus"></div>';
// putting everything in a wrapper function that in turn is placed in a
// script tag on the website allows us to execute in the sites context
@ -147,6 +146,9 @@ var MIN_AP_FOR_LEVEL = [0, 10000, 30000, 70000, 150000, 300000, 600000, 1200000]
var HACK_RANGE = 40; // in meters, max. distance from portal to be able to access it
var OCTANTS = ['E', 'NE', 'N', 'NW', 'W', 'SW', 'S', 'SE'];
var DEFAULT_PORTAL_IMG = 'http://commondatastorage.googleapis.com/ingress/img/default-portal-image.png';
var DESTROY_RESONATOR = 75; //AP for destroying portal
var DESTROY_LINK = 187; //AP for destroying link
var DESTROY_FIELD = 750; //AP for destroying field
// OTHER MORE-OR-LESS CONSTANTS //////////////////////////////////////
var NOMINATIM = 'http://nominatim.openstreetmap.org/search?format=json&limit=1&q=';

View File

@ -10,39 +10,43 @@ body {
margin: 0;
}
#map {
margin-right:302px;
}
#scrollwrapper {
height: 100%;
overflow: hidden;
position: fixed;
right: -38px;
top: 0;
width: 340px;
bottom: 45px;
z-index: 1001;
/*
* NOTE: following 2 items are needed for back compatability
* between new css and old plugin versions (0.4) as of 2013-02-11 UTC.
*/
background-color: rgba(8, 48, 78, 1);
}
#sidebar {
background: #000;
border-left: 2px solid #c3c3c3;
background-color: rgba(8, 48, 78, 0.9);
border-left: 1px solid #20A8B1;
color: #888;
height: 100%;
position: relative;
left: 0;
top: 0;
max-height: 100%;
overflow-y:scroll;
overflow-x:hidden;
z-index: 3000;
}
#sidebartoggle {
display: block;
padding: 10px 5px;
padding: 20px 5px;
margin-top: -31px;
line-height: 10px;
position: absolute;
top: 50%;
z-index: 3000;
z-index: 3001;
background-color: rgba(8, 48, 78, 0.9);
color: #FFCE00;
border: 1px solid #20A8B1;
@ -257,7 +261,7 @@ summary {
/* sidebar ************************************************************/
#sidebar > * {
border-bottom: 1px solid #c3c3c3;
border-bottom: 1px solid #20A8B1;
}
@ -321,7 +325,7 @@ h2 sup, h2 sub {
/* geosearch input, and others */
input {
background: #313131;
background-color: rgba(0, 0, 0, 0.3);
color: #ffce00;
height: 22px;
line-height: 22px;
@ -369,8 +373,7 @@ h3 {
font-size: 40px;
position: absolute;
right: 10px;
/* simulate an outline with multiple shadows */
text-shadow: -2px -2px #000000, 2px -2px #000000, -2px 2px #000000, 2px 2px #000000;
text-shadow: -1px -1px #000, 1px -1px #000, -1px 1px #000, 1px 1px #000, 0 0 5px #fff;
top: 100px;
}
@ -382,7 +385,7 @@ h3 {
}
.mods span {
background: #313131;
background-color: rgba(0, 0, 0, 0.3);
/* cant use inline-block because Webkits implementation is buggy and
* introduces additional margins in random cases. No clear necessary,
* as thats solved by setting height on .mods. */
@ -527,30 +530,30 @@ aside:nth-child(odd) span {
}
#spacer {
/* cheap hack to prevent sidebar content being overlayed by the map
* status box */
height: 55px;
height: 10px;
}
/* a common portal display takes this much space (prevents moving
* content when first selecting a portal) */
#portaldetails {
min-height: 532px;
min-height: 553px;
}
/* update status */
#updatestatus {
background: #000;
background-color: rgba(8, 48, 78, 1);
border-bottom: 0;
border-top: 1px solid #c3c3c3;
border-top: 1px solid #20A8B1;
border-left: 1px solid #20A8B1;
bottom: 0;
color: #ffce00;
font-size:13px;
padding: 4px;
position: fixed;
right: 0;
z-index:3002;
}