· 9 years ago · Dec 09, 2016, 03:20 PM
1// ==UserScript==
2// @name FleetLogBeautifier
3// @namespace kelder.ogame.org
4// @description Fleetlog parser
5// @include http://*.ogame.*/game/admin2/flottenlog.php?session=*&uid=*&list=*
6// @include https://*.ogame.*/game/admin2/flottenlog.php?session=*&uid=*&list=*
7// @include http://*.ogame.*/game/admin2/flottenlog.php?session=*&showplanet=*
8// @include https://*.ogame.*/game/admin2/flottenlog.php?session=*&showplanet=*
9// @version 2016.2.10
10// @grant none
11// ==/UserScript==
12//** Copyright © 2008 by Kelder for ogame.org community. **
13//** May only be used by ogame staff. If you are not ogame staff, then delete this script immediately. **
14//** Obtain permission before redistributing. **
15// ******** CONSTANTS ********
16// Config settings can be set from a javascript console while logged into the AT:
17// Just type localStorage['COMBINE_FLEETS_AND_RESOURCES'] = 1 to set the option.
18// localStorage['COMBINE_FLEETS_AND_RESOURCES'] boolean (0 = false, 1 = true)
19// localStorage['externalCSS'] string (0 = off, else 'http://<yourCSSfilehere>' )
20// localStorage['DATE_FORMAT'] string (default = '%d/%m %H:%M:%S' )
21// -> see http://www.opengroup.org/onlinepubs/007908799/xsh/strftime.html for info on format.
22//
23//
24//SSL link addition by zohar88 from ogame.org comunity. **
25(function() {
26var LNG_START_BUTTON = 'Beautify!';
27// The function that contains all the REAL stuff to parse logs and display them
28function DoModify() {
29var CONV = new Array();
30var CLS = new Array();
31// ***************
32// LANGUAGE CONFIG
33// ***************
34// Mission names (do not have to be exact like in admin tool)
35var LNG_ESPIONAGE = 'Espionage';
36var LNG_ATTACK = 'Attack';
37var LNG_TRANSPORT = 'Transport';
38var LNG_HARVEST = 'Harvest';
39var LNG_DEPLOYMENT = 'Deployment';
40var LNG_EXPEDITION = 'Expedition';
41var LNG_ACS_ATTACK = 'ACS Attack';
42var LNG_COLONIZATION = 'Colonization';
43var LNG_MOON_DESTRUCTION = 'Moon Destruction';
44var LNG_ACS_DEFEND = 'ACS Defend';
45var LNG_IPM = 'IPM';
46// table header text
47var LNG_HDR_MISSION = 'Mission';
48var LNG_HDR_PLAYER1 = 'Player 1';
49var LNG_HDR_PLAYER2 = 'Player 2';
50var LNG_HDR_ORIGIN = 'From';
51var LNG_HDR_DESTINATION = 'To';
52var LNG_HDR_LAUNCH = 'Start';
53var LNG_HDR_ARRIVAL = 'Arrival';
54var LNG_HDR_RESOURCES = 'Res';
55var LNG_HDR_FLEET = 'Fleet';
56var LNG_HDR_RETURN_TIME = 'Return';
57var LNG_HDR_RETURN_RES = 'Res';
58var LNG_HDR_RETURN_FLEET = 'Fleet';
59// coordinates stuff
60var LNG_SHORT_DF = 'D';
61var LNG_SHORT_MOON = 'M';
62var LNG_SHORT_PLANET = 'P';
63var LNG_NO_COORDS = '?:?:?';
64
65// for each CSS class name give the label of the button
66var mission = {
67 Att: 'Attack',
68 Esp: 'Espionage',
69 Exp: 'Exp',
70 Own: 'Own',
71 Tra: 'Transport',
72 Dep: 'Deploy',
73 Col: 'Colonize',
74 Hrv: 'Harvest',
75 ACS: 'any ACS',
76 Des: 'Moon destr',
77 Def: 'ACS Def',
78 Ipm: 'IPM',
79 returns: 'Recalled'
80};
81var LNG_OLD_LOGS_BUTTON = 'Old logs';
82// misc+missions
83var LNG_CONV_DF = /^debris field/;
84var LNG_CONV_MOON = /\(M\) \[/;
85//Copy EXACTLY like it appears in admin tool
86var LNG_FLEET_ARRIVES_TO_TARGET = 'Fleet Arrives to Target';
87var LNG_SPACE_PLAYER_NAME = 'space';
88var LNG_UNKNOWN_PLAYER_NAME = 'unknown';
89var LNG_UNKNOWN_PLANET_NAME = 'unknown';
90// Copy what's between CONV[' and '] = EXACTLY like it appears in admin tool
91// res
92CONV['Metal'] = 'M';
93CONV['Crystal'] = 'C';
94CONV['Deuterium'] = 'D';
95// ships
96CONV['Small Cargo'] = 'SC';
97CONV['Large Cargo'] = 'LC';
98CONV['Light Fighter'] = 'LF';
99CONV['Heavy Fighter'] = 'HF';
100CONV['Cruiser'] = 'CR';
101CONV['Espionage Probe'] = 'ESP';
102CONV['Battleship'] = 'BS';
103CONV['Bomber'] = 'BOM';
104CONV['Battlecruiser'] = 'BC';
105CONV['Destroyer'] = 'DES';
106CONV['Deathstar'] = 'RIP';
107CONV['Colony Ship'] = 'COL';
108CONV['Recycler'] = 'REC';
109CONV['Solar Sattellite'] = 'SAT';
110// END OF CONFIG
111// *********************
112// no changes below here
113//chrome additions
114if (Date.prototype.toLocaleFormat == null) {
115 function pad(n) { return n < 10 ? '0' + n : n; }
116 Date.prototype.toLocaleFormat = function() {
117 return this.getFullYear() + '-' + pad(this.getMonth()+1) + '-' + pad(this.getDate()) + ' '
118 + pad(this.getHours()) + ':' + pad(this.getMinutes()) + ':' + pad(this.getSeconds()); };
119}
120//end chrome additions
121getValue = function(name, defaultValue) {
122 var value = localStorage.getItem(name);
123 if (value === undefined || value == null) {
124 return defaultValue;
125 }
126 return value;
127}
128var COMBINE_FLEETS_AND_RESOURCES = getValue('COMBINE_FLEETS_AND_RESOURCES', false);
129var LNG_DATE_FORMAT = getValue('DATE_FORMAT','%d/%m %H:%M:%S');
130var ORIG_DATE_FORMAT = getValue('ORIG_DATE_FORMAT','%Y-%m-%d %H:%M:%S');
131var OPT_EXTERNAL_CSS = getValue('externalCSS',false);
132var UNI_SPEED = getValue(window.location.hostname + '_UNI_SPEED',1);
133if (isNaN(UNI_SPEED)) { UNI_SPEED = 1; }
134// missions (CLS means CSS class for that mission log)
135CLS[LNG_ATTACK] = 'Att ';
136CLS[LNG_ACS_ATTACK] = 'Att ACS ';
137CLS[LNG_TRANSPORT] = 'Tra ';
138CLS[LNG_DEPLOYMENT] = 'Dep ';
139CLS[LNG_ACS_DEFEND] = 'Def ACS ';
140CLS[LNG_ESPIONAGE] = 'Esp ';
141CLS[LNG_COLONIZATION] = 'Col ';
142CLS[LNG_HARVEST] = 'Hrv ';
143CLS[LNG_MOON_DESTRUCTION] = 'Des ';
144CLS[LNG_IPM] = 'Ipm ';
145CLS[LNG_EXPEDITION] = 'Exp ';
146// use mission number to find short name. the 1 in "Attack 1" up to " 15"
147var CONV_SHORT_MISSION = [0,
148 LNG_ATTACK, LNG_ACS_ATTACK, LNG_TRANSPORT, LNG_DEPLOYMENT,
149 LNG_ACS_DEFEND, LNG_ESPIONAGE, LNG_COLONIZATION, LNG_HARVEST,
150 LNG_MOON_DESTRUCTION, LNG_IPM, 0, 0,
151 0, 0, LNG_EXPEDITION];
152// contains the CSS class names to put under the buttons
153var missionButtons = [ 'Att', 'Esp', 'Own', 'Tra', 'Dep', 'Col', 'Hrv', 'ACS', 'Exp', 'Des', 'Def', 'Ipm', 'returns'];
154var head = document.getElementsByTagName('head')[0];
155// load external css
156if (OPT_EXTERNAL_CSS) { createEl({n:'link',a:{rel:'stylesheet', '@type': 'text/css', href: OPT_EXTERNAL_CSS}}, head);
157} else { createStyle('flb_extCSS','.Esp {background-color:#8F813D}.Att{background-color:#8F3D3D}.Att.ACS{background-color:#8F3D5A}.Des{background-color:#AF1B94}.Def.ACS{background-color:#8F553C}.Ipm{background-color:#8F6C3D}.Tra{background-color:#3C5A8F}.Tra.Own{background-color:#3E3C8F}.Dep{background-color:#623C8F}.Col{background-color:#418F3C}.Exp{background-color:#999}.Hrv{background-color:#3C8F6B}.returns{color:black}.arrived{color:white}.res .tp{color:#FFF;font-weight:bold;margin-right:.2em}.fleet .tp{color:#FF9;font-weight:bold;margin-right:.2em; font-size:.8em}.res.return .tp{color:#FFF}.fleet.return .tp{color:#BFB}.res .am,.fleet .am{color:#EEE;margin-right:1em}.score{font-size:70%;color:#9FF}.state{color:#FF4}td.player{cursor:pointer}#GM_menu_middle{position:absolute;top:140px;left:240px;padding:5px;border:1px solid orange;max-width:650px}#GM_menu_bar{position:fixed;top:0px;left:10px;padding:3px;border:1px solid orange;background-color:black;z-index:5}.DisplayButton.GM__HIDDEN,.FilterButton.GM__HIDDEN{color:#F33}.DisplayButton.GM__SHOW_ONLY,.FilterButton.GM__SHOW_ONLY{color:#3FF}.FilterButton{margin:3px;padding:1px;border:1px solid #666;display:inline-block;text-align:center;min-width:9em}.FilterButton .score{display:none}span.res,span.fleet{display:inline-block}body,table,td{font-size:10pt}#GM_fleetlog{position:absolute;top:500px;left:10px;padding-bottom:20px;z-index:2}#GM_fleetlog td{background-image:none}.DisplayButton{margin-right:1em}.GM__MINIMIZED div.fleet,.GM__MINIMIZED div.res {display:inline}tr.GM__MINIMIZED td{ font-size:1px;padding:0;margin:0;height:4px;}.st{text-decoration:line-through}.empty{font-size:.8em}#OGB_DISP_UNI_SPEED{width:1.8em;font-size:80%}td.p2{cursor:pointer}td.mission{cursor:row-resize}th.t1,th.t2,th.t3{width:6.2em}.GM_TextBox {z-index:3;min-width:700px}'); }
158function createStyle(id, content) { //custom GM_addStyle to have id for later removal
159 return createEl({n: 'style', a: {type:'text/css', '@id':id, textContent:content}}, head);
160}
161
162document.getElementById('GM_ActivateButton').parentNode.removeChild(document.getElementById('GM_ActivateButton'));
163var PLAYERS = new Object();
164
165function Player(td) {
166 if (arguments.length > 1) {
167 this.name = arguments[1];
168 this.uid = arguments[2];
169 this.score = 0;
170 this.state = '';
171 this.dom = createEl( // trg attribute is to know which uid to toggle when clicked
172 {n: 'td', a: {'@class' : 'st player', '@trg': 'u' + this.uid, textContent: this.name}}
173 , null);
174 return;
175 }
176 this.uid = td.firstChild.href.replace( /^.+uid=(\d+).*$/, '$1');
177 this.name = td.firstChild.firstChild.nodeValue;
178 if (this.name == null) this.name = td.firstChild.firstChild.firstChild.nodeValue; // font tag around name
179 if (this.name == LNG_UNKNOWN_PLAYER_NAME) {
180 this.name = 'uid ' + this.uid;
181 this.score = '?';
182 this.state = '';
183 this.dom = createEl(
184 {n: 'td', a: {'@class' : 'st player', '@trg': 'u' + this.uid, textContent: this.name}}
185 , null);
186 return;
187 }
188 this.state = '';
189 if (td.childNodes.length) {
190 var i = td.childNodes.length - 1;
191 while ((td.childNodes.item(i)) && (td.childNodes.item(i).nodeType != 3)) --i;
192 this.score = ''+td.childNodes.item(i).nodeValue.match(/\d[\d+\.]*/);
193 i = 2;
194 while (td.childNodes.item(++i)) {
195 if (td.childNodes.item(i).tagName == 'FONT') this.state += td.childNodes.item(i).firstChild.nodeValue;
196 }
197 } else { this.score = 0; }
198 if (this.state == '') {
199 this.dom = createEl( // removed: '@class': 'u1',
200 // {n: 'td', a: {'@trg': 'u' + this.uid, textContent: this.name + ' (' + this.score + ')'}}
201 {n: 'td', a: {'@class': 'player', '@trg': 'u' + this.uid },
202 c: [ this.name, {n:'span', a: {'@class': 'score', textContent: ' ' + this.score}} ]}
203 , null);
204 } else {
205 this.dom = createEl( // removed: '@class': 'u1',
206 // {n: 'td', a: {'@trg': 'u' + this.uid, textContent: this.name + this.state + ' (' + this.score + ')'}}
207 {n: 'td', a: {'@class': this.state + ' player', '@trg': 'u' + this.uid },
208 c: [ this.name,
209 {n:'span', a: {'@class': 'state ' + this.state, textContent: ' (' + this.state + ')'}},
210 {n:'span', a: {'@class': 'score', textContent: ' ' + this.score}} ]}
211 , null);
212 }
213}
214Player.prototype.domElem = function() { return this.dom.cloneNode(true); }
215PLAYERS['u0'] = new Player(null, '*'+LNG_UNKNOWN_PLAYER_NAME+'*', 0);
216PLAYERS['u99999'] = new Player(null, LNG_SPACE_PLAYER_NAME, 99999);
217function getPlayer(td) {
218 if (td.firstChild.nodeName == 'A') {
219 //find uid
220 var uid = td.firstChild.href.replace( /^.+uid=(\d+).*$/, "$1");
221 return PLAYERS['u'+uid] || (PLAYERS['u'+uid] = new Player(td));
222 } else return PLAYERS['u0'];
223}
224
225// show or hide all elements of a certain class (for menu buttons)
226function toggleDisplay(evt) {
227 var cls = this.getAttribute('trg');
228 var e = document.getElementById('GM__STYLE_' + cls);
229 if (e) {
230 e.parentNode.removeChild(e);
231 this.className = this.className.replace(/\bGM__HIDDEN\b|\bGM__SHOW_ONLY\b/,'');
232 } else { var s; // create style
233 // specialcase the Old Logs button...
234 if (cls == 'GM_TextBox') { this.className += ' GM__HIDDEN'; s = 'div.GM_TextBox {display:none;}';
235 } else if (evt.ctrlKey) {
236 s = 'table tr.'+cls+'{display:table-row;}tr.arrived,tr.returns{display:none;}';
237 this.className += ' GM__SHOW_ONLY';
238 } else {
239 s = 'table#newTable tr.'+cls+'{display:none;}';
240 this.className += ' GM__HIDDEN';
241 }
242 createStyle('GM__STYLE_' + cls, s);
243 }
244}
245
246// show or hide all elements of a certain class (for players/planets, creates click box)
247function toggleDisplay2(evt,td) {
248 if (!td) td = this;
249 var cls = td.getAttribute('trg');
250 var e = document.getElementById('GM__STYLE_' + cls);
251 if (e) {
252 e.parentNode.removeChild(e);
253 e = document.getElementById('GM__FILTER_' + cls);
254 if (e) { e.parentNode.removeChild(e); }
255 }
256 else { var s; // create style
257 e = createEl({n: 'span', a: { '@id': 'GM__FILTER_' + cls, '@class': 'FilterButton ',
258 '@trg': cls, innerHTML: td.innerHTML }},menu_mid_div);
259 e.addEventListener('click', toggleDisplay2, true);
260 if (evt.ctrlKey) {
261 s = 'tr.arrived.'+cls+',tr.returns.'+cls+'{display:table-row;}tr.arrived,tr.returns{display:none;}';
262 e.className += ' GM__SHOW_ONLY';
263 } else {
264 s = 'table#newTable tr.'+cls+'{display:none;}';
265 e.className += ' GM__HIDDEN';
266 }
267 createStyle('GM__STYLE_' + cls, s);
268 }
269}
270
271// minimizes parent
272function minimizeDisplay(td) {
273 var p = td.parentNode;
274 if (p.className.match(/\bGM__MINIMIZED\b/)) p.className = p.className.replace(/ ?\bGM__MINIMIZED\b/,'')
275 else p.className += ' GM__MINIMIZED';
276}
277
278// add resources or fleet to a TD container. Create new container if needed
279function stuffConvert(res, isfleet, isreturn, container) {
280 var f;
281 if (isfleet) f = 'fleet';
282 else f = 'res';
283 if (isreturn) f += ' return';
284 var parts = res.match(/(?:[^\s:]+(?: [^\s:]+)*) : [.\d]+/g);
285 //if (!container) container = createEl({n: 'td', a: {'@class': f}}, null);
286 if (!container) container = createEl({n: 'td'}, null);
287 if (parts == null) return container;
288 var p;
289 for (var i = 0;i < parts.length; i++) {
290 p = parts[i].match(/(.+)\s:\s([.\d]+)/);
291 createEl({n: 'span', a: {'@class': f}, c: [
292 {n: 'span', a: {'@class': 'tp', textContent: CONV[p[1]] || p[1]}},
293 {n: 'span', a: {'@class': 'am', textContent: p[2]}}
294 ]},container);
295 }
296 return container;
297}
298
299// input: "2007-12-01 22:09:58" output: new Date(input)
300function parseTime(time) {
301 return new Date(time.replace(/-/g,'/') + ' GMT');
302}
303function Planet(pCell) {
304 if (pCell == null) return;
305 if (pCell.firstChild.nodeType == 3) { // unknown planet
306 this.name = LNG_UNKNOWN_PLANET_NAME;
307 this.id = 'p0';
308 this.type = '';
309 this.coords = LNG_NO_COORDS;
310 } else { // planet exists
311 this.name = pCell.firstChild.firstChild.nodeValue;
312 this.id = pCell.firstChild.href.replace( /^.+planet=(\d+).*$/, "p$1" );
313 this.coords = this.name.replace( /^.*\[([\d:]+)\].*$/, "$1");
314 this.type = (this.name.match(LNG_CONV_DF) ? LNG_SHORT_DF : (this.name.match(LNG_CONV_MOON) ? LNG_SHORT_MOON : LNG_SHORT_PLANET));
315 this.name = this.name.replace(/\s*[\(\[].+$/,'');
316 }
317}
318
319// Get main content box
320var textbox = document.evaluate('/html/body/div[@class="contbox"]/div[2]/div[1]', document, null, XPathResult.ELEMENT_NODE, null).iterateNext()
321var fl_div = createEl({n: 'div', a: {'@id': 'GM_fleetlog', textContent:''}},document.body);
322var menu_bar_div = createEl({n: 'div', a: {'@id': 'GM_menu_bar', textContent:''}},document.body);
323var menu_mid_div = createEl({n: 'div', a: {'@id': 'GM_menu_middle', textContent:''}},document.body);
324var newtable = createEl({n: 'table', a: {'@class': 'newTable', id: 'newTable'}});
325function tableClick(event) {
326 if (!event || !event.target) return;
327 var t = event.target;
328 if (!t.tagName || t.tagName == 'TABLE' || t.tagName == 'TH' || t.tagName == 'TR' ) return;
329 if (t.tagName == 'DIV' || t.tagName == 'SPAN') t = t.parentNode;
330 if (t.tagName != 'TD') { console.log("didn't find tag :(" + event.target); }
331 // found correct TD, not check className to know which action to do
332 if (t.className.match(/\bmission\b/)) { minimizeDisplay(t); }
333 if (t.className.match(/\bplayer\b/)) { toggleDisplay2(event, t); }
334 if (t.className.match(/\bp2\b/)) { toggleDisplay2(event, t); }
335
336}
337newtable.addEventListener('click', tableClick, true);
338//create menu items to show/hide stuff
339for (var b in missionButtons) {
340 var a = createEl({n: 'a', a: { '@id': 'OGB_DISP_'+missionButtons[b], '@class': 'DisplayButton',
341 '@trg': missionButtons[b], textContent: mission[missionButtons[b]] }},menu_bar_div);
342 a.addEventListener('click', toggleDisplay, true);
343}
344createEl({n: 'a', a: { '@id': 'OGB_DISP_GM_TextBox', '@class': 'DisplayButton GM__HIDDEN',
345 '@trg': 'GM_TextBox', textContent: LNG_OLD_LOGS_BUTTON }},menu_bar_div)
346 .addEventListener('click', toggleDisplay, true);
347
348function updateSpeed() {
349 var box = document.getElementById('OGB_DISP_UNI_SPEED');
350 if (!box.value.match(/^\d+(\.\d+)?$/)) box.value = 1;
351 localStorage.setItem(window.location.hostname + '_UNI_SPEED', box.value);
352
353}
354createEl({n: 'input', a: { '@id': 'OGB_DISP_UNI_SPEED',
355 '@type': 'input', '@maxlength': '5', value: UNI_SPEED }},menu_bar_div)
356 .addEventListener('blur', updateSpeed, true);
357updateSpeed();
358//log header:
359createEl({n: 'tr', a: {'@class': 'header'}, c: [
360 {n: 'th', a: {'@class': 'mission', textContent: LNG_HDR_MISSION}},
361 {n: 'th', a: {'@class': 'u1', textContent: LNG_HDR_PLAYER1}},
362 {n: 'th', a: {'@class': 'u2', textContent: LNG_HDR_PLAYER2}},
363 {n: 'th', a: {'@class': 'p1', textContent: LNG_HDR_ORIGIN}},
364 {n: 'th', a: {'@class': 'p2', textContent: LNG_HDR_DESTINATION}},
365 {n: 'th', a: {'@class': 't1', textContent: LNG_HDR_LAUNCH}},
366 {n: 'th', a: {'@class': 't2', textContent: LNG_HDR_ARRIVAL}},
367 COMBINE_FLEETS_AND_RESOURCES ? null : {n: 'th', a: {'@class': 'res', textContent: LNG_HDR_RESOURCES}},
368 {n: 'th', a: {'@class': 'fleet', textContent: LNG_HDR_FLEET}},
369 {n: 'th', a: {'@class': 't3', textContent: LNG_HDR_RETURN_TIME}},
370 COMBINE_FLEETS_AND_RESOURCES ? null : {n: 'th', a: {'@class': 'res return', textContent: LNG_HDR_RETURN_RES}},
371 {n: 'th', a: {'@class': 'fleet return', textContent: LNG_HDR_RETURN_FLEET}},
372]}, newtable);
373
374// check all tables and br's to recompose logs
375var currlog = 0;
376var xpres = document.evaluate('table[@width="650"]|br', textbox, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
377for (var i=0; i<xpres.snapshotLength; ++i) {
378 var logitem = xpres.snapshotItem(i);
379 if (logitem.nodeName == "TABLE") {
380 // parse each td of the table, they should have fixed order and contents
381 var cells = document.evaluate('.//td', logitem, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
382 if (cells.snapshotLength != 12) {
383 console.log('INCORRECT TABLE STRUCTURE, aborting:' + cells.snapshotLength + '; ' + cells.innerHTML);
384 return;
385 }
386 var mission = cells.snapshotItem(0).textContent;
387 var player1 = getPlayer(cells.snapshotItem(1));
388 var player2 = getPlayer(cells.snapshotItem(2));
389 var arrival = cells.snapshotItem(3).textContent == LNG_FLEET_ARRIVES_TO_TARGET;
390 var planet1 = new Planet(cells.snapshotItem(5));
391 var planet2 = new Planet(cells.snapshotItem(6));
392 var fleet = cells.snapshotItem(8).textContent;
393 var res = cells.snapshotItem(9).textContent;
394 var time1 = cells.snapshotItem(10).textContent;
395 var time2 = cells.snapshotItem(11).textContent;
396 res = stuffConvert(res,0,0,null);
397 fleet = stuffConvert(fleet,1,0,COMBINE_FLEETS_AND_RESOURCES ? res : null);
398 var p1d = player1.domElem();
399 var p2d = player2.domElem();
400
401 var cls = '';
402 mission = CONV_SHORT_MISSION[mission.match(/ \(?(\d*)\)?$/)[1]];
403 cls += CLS[mission];
404 cls += planet2.id;
405 if (player1.uid == player2.uid) {
406 if (mission == LNG_TRANSPORT) { cls += ' Own'; }
407 cls += ' u' + player1.uid;
408 } else { cls += ' u' + player1.uid + ' u' + player2.uid; }
409 cls += (arrival ? ' arrived' : ' returns');
410
411 var logitem = xpres.snapshotItem(++i);
412 if ((logitem.nodeName == "BR") || (mission == LNG_DEPLOYMENT)) { // (deployments do not need return)
413 if (mission == LNG_IPM) { //IPMs
414 if (time2.match(/^1970/)) {
415 if ((planet1.coords == LNG_NO_COORDS) || (planet2.coords == LNG_NO_COORDS)) time2 = '??'
416 else {
417 time2 = new Date(parseTime(time1).getTime() + (
418 30000 + // 30 seconds in-system + 60 seconds per SS
419 60000 * Math.abs(planet2.coords.match(/:(\d+):/)[1] - planet1.coords.match(/:(\d+):/)[1] )) / UNI_SPEED
420 );
421 time2.setMinutes(time2.getMinutes() + time2.getTimezoneOffset());
422 time2 = time2.toLocaleFormat(ORIG_DATE_FORMAT)
423 }
424 }
425 cls = cls.replace(/ returns$/, ' arrived');
426 createEl({n: 'tr', a: {'@class': cls}, c: [
427 {n: 'td', a: {'@class': 'mission', textContent: mission}},
428 p1d,
429 p2d,
430 {n: 'td', a: {'@class': 'p1', textContent: planet1.coords + planet1.type}},
431 {n: 'td', a: {'@class': 'p2', '@trg': planet2.id, textContent: planet2.coords + planet2.type}},
432 {n: 'td', a: {'@class': 't1', textContent: time1}},
433 {n: 'td', a: {'@class': 't2', textContent: time2}},
434 COMBINE_FLEETS_AND_RESOURCES?null:res, fleet,
435 {n: 'td', a: {'@class': 'empty st', '@colspan': COMBINE_FLEETS_AND_RESOURCES?2:3, textContent: '' }}
436 ]}, newtable);
437 } else {
438 //NO RETURN FLEET - create log entry
439 var time3 = new Date(2 * parseTime(time2).getTime() - parseTime(time1).getTime());
440 time3.setMinutes(time3.getMinutes() + time3.getTimezoneOffset());
441 createEl({n: 'tr', a: {'@class': cls}, c: [
442 {n: 'td', a: {'@class': 'mission', textContent: mission}},
443 p1d,
444 p2d,
445 {n: 'td', a: {'@class': 'p1', textContent: planet1.coords + planet1.type}},
446 {n: 'td', a: {'@class': 'p2', '@trg': planet2.id, textContent: planet2.coords + planet2.type}},
447 {n: 'td', a: {'@class': 't1', textContent: time1}},
448 {n: 'td', a: {'@class': 't2', textContent: time2}},
449 COMBINE_FLEETS_AND_RESOURCES?null:res,
450 fleet,
451 {n: 'td', a: {'@class': 'empty st', '@colspan': COMBINE_FLEETS_AND_RESOURCES?2:3,
452 textContent: (mission == LNG_DEPLOYMENT ? '' :(arrival?'not returned? >':'recalled <') + time3.toLocaleFormat(ORIG_DATE_FORMAT))}}
453 ]}, newtable);
454 }
455 } else if(logitem.nodeName == "TABLE") {
456 //PARSE RETURN FLEET
457 // parse each td of the table, they should have fixed order and contents
458 var cells = document.evaluate('.//td', logitem, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
459 if (cells.snapshotLength != 12) {
460 console.log('INCORRECT TABLE STRUCTURE for return, aborting:' + cells.snapshotLength + '; ' + cells.innerHTML);
461 return;
462 }
463 var fleet2 = cells.snapshotItem(8).textContent;
464 var res2 = cells.snapshotItem(9).textContent;
465 var time3 = new Date(2 * parseTime(time2).getTime() - parseTime(time1).getTime());
466 time3.setMinutes(time3.getMinutes() + time3.getTimezoneOffset());
467 res2 = stuffConvert(res2,0,1);
468 fleet2 = stuffConvert(fleet2,1,1,COMBINE_FLEETS_AND_RESOURCES?res2:null);
469
470 //create log entry
471 createEl({n: 'tr', a: {'@class': cls}, c: [
472 {n: 'td', a: {'@class': 'mission', textContent: mission}},
473 p1d,
474 p2d,
475 {n: 'td', a: {'@class': 'p1', textContent: planet1.coords + planet1.type}},
476 {n: 'td', a: {'@class': 'p2', '@trg': planet2.id, textContent: planet2.coords + planet2.type}},
477 {n: 'td', a: {'@class': 't1', textContent: time1}},
478 {n: 'td', a: {'@class': 't2', textContent: time2}},
479 COMBINE_FLEETS_AND_RESOURCES?null:res,
480 fleet,
481 {n: 'td', a: {'@class': 't3', textContent: time3.toLocaleFormat(ORIG_DATE_FORMAT)}},
482 COMBINE_FLEETS_AND_RESOURCES?null:res2,
483 fleet2
484 ]}, newtable);
485 // END RETURN FLEET
486 }
487 }
488}
489
490fl_div.appendChild(newtable);
491textbox.parentNode.parentNode.className += ' GM_TextBox';
492createEl({n: 'style', a: {type:'text/css', '@id':'GM__STYLE_GM_TextBox', textContent:'div.GM_TextBox {display:none;}'}}, head);
493} //end of DoModify
494
495// create DOM nodes using hash syntax and add it to end of parent node (if != null)
496function createEl(elObj, parent) {
497 var el;
498 if (elObj == null) return;
499 if (typeof elObj == 'string') {
500 el = document.createTextNode(elObj);
501 } else if (elObj.nodeType) { // it's an Element node already
502 el = elObj;
503 } else if (elObj.n) { // it's the hash type thing
504 el = document.createElement(elObj.n);
505 if (elObj.a) {
506 attributes = elObj.a;
507 for (var key in attributes) {
508 if (key.charAt(0) == '@')
509 el.setAttribute(key.substring(1), attributes[key]);
510 else
511 el[key] = attributes[key];
512 }
513 }
514 if (elObj.evl) {
515 el.addEventListener(elObj.evl.type, elObj.evl.f, elObj.evl.bubble);
516 }
517 if (elObj.c) {
518 elObj.c.forEach(function (v, i, a) { createEl(v, el); });
519 }
520 } else {
521 alert(elObj.toString());
522 el = elObj;
523 }
524 if (parent)
525 parent.appendChild(el);
526 return el;
527}
528// Get main content box
529var textbox = document.evaluate('/html/body/div[@class="contbox"]/div[2]/div[1]/h3[1]', document, null, XPathResult.ELEMENT_NODE, null).iterateNext();
530//create activate button
531createEl({n: 'style', a: {type:'text/css', textContent:'#GM_ActivateButton { margin-left:10px; }'}},document.getElementsByTagName('head')[0]);
532var activateButton = createEl({n: 'button', a: {'@id':'GM_ActivateButton', name:'GM_ActivateButton', textContent:LNG_START_BUTTON }},textbox)
533 .addEventListener('click',DoModify,true);
534})();