您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Create a searchable map on all the islands/cities you have visited.
// ==UserScript== // @name Ikariam Xplorer // @namespace greasyfork.org // @homepage http://greasyfork.org/ // @description Create a searchable map on all the islands/cities you have visited. // @version 0.1.1 // @include http://s*.ikariam.*/* // @exclude http://support*.ikariam.*/* // @license GNU GPL v3 (http://www.gnu.org/copyleft/gpl.html), Copyright (c) 2012-2015, Viper // @grant unsafeWindow // @grant GM_addStyle // @grant GM_getValue // @grant GM_setValue // @grant GM_log // ==/UserScript== // Version history: /* 0.1.1/8.7.2015 First release. Feature: Autoscan worldmap view to get base island information (Worldscan) Feature: Autoscan defined area's island views (Scan) Feature: Collect city information from island view Feature: Display island/city information on a map interface Feature: Filter players, alliances, cities Feature: Collect player score information from island view Feature: Collect information from world map */ /* ROADMAP [HIGH] Collect information from alliance member list view [HIGH] Display allied cities on the map [HIGH] Detect and highlight allied cities [HIGH] Collect information from high score views. [HIGH] Collect information from combat reports [HIGH] Display stationed troops and troop movements. [MED] Remove highlight colors from used alliance colors [MED] Show/highligh player cities on map when hoovering over player's info [MED] Grouping (and thus coloring) by other fields in addition to alliance [LOW] "Travel Time" functionality with source and target island selection [LOW] Make grid ticks visible when zooming [LOW] Make containers "dockable" or at least their visibility selectable [LOW] Define and restrict minimum size of window to prevent misaligned/overlapping ui elements) */ const version = '0.1.1'; const scriptURL = 'http://userscripts.org/scripts/source/xxxxx.user.js' const scriptMetaURL = 'http://userscripts.org/scripts/source/xxxxx.meta.js' const scriptHomepage = 'http://userscripts.org/scripts/show/xxxxx'; const updateCheckInterval = 24*60*60*1000; //24 hours const versionTag = '// @version'; const mapDBVersion = '001'; const mapDBKey = 'mapDB'; const syslogLogLevel = 4; // Higher number results in finer logging, 1-4 const syslogJavaConsoleEnabled = false; const syslogFirebugEnabled = true; var consoleBackup = unsafeWindow.console; // store the original console pointer since some pages overwrite/disable it const defaultWindowWidth = 1024; const defaultWindowHeight = 810; const mapXOffset = 20; const mapYOffset = 45; const defaultMapScaleRatio = 55; var mapScaleRatio = defaultMapScaleRatio; var mapScale = 1; const islandScale = 4; const generalsScoreIslandScale = 100; const totalScoreIslandScale = 5000; const goldIslandScale = 100000; const playerScale = 4; const generalsScorePlayerScale = 100; const totalScorePlayerScale = 5000; const goldPlayerScale = 100000; const IMAGES = { xplorer:'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAADAFBMVEUMCAjUiSCMkJT6xTnqzZicimzKzM7rxWjcpizYqlybXwv85Jb532TJsZf76cxQTlC4iEC8jV/Epkj821jEp4SwsbXmw4LgzbXow0zn6ezkhnydZhH04rvcwJTwtzGcglT202f3z1LcmSrClkHctnx8ZiykGxTt4Mz889LmuV/63oL03JTEm1/fuUTw2LTysSzUr3z31XzVtZR+eGz88LjMqJT87pzky6T5+PDc29zvzGjl5+TEwLTCnXzXwKfYMizm2cS2hjD80US0mnzeqEnkzlysdTCdoKPSqHC4h1HEjGzxyFzKmEzkemzsnoyygDL3xUSFiIn88Gf41nTjoSbu1YzUnozisEj87tTNqoyodBjQJBz89YbisjyAgIHIooFERkT046mwrqjjunAsKiy3W0/25MT01lH89ODFm3P03rvr0qvuzHS8jiTS09PgqDz26dT75lz1yE7quDzoulTQsIz42n3YupX89cT8/vzj4uP8yjrMqIS3uLrszXzh0rjv8PGkSjwcGhxgYF5EQDiPemGkjmzAwMTkhkSsWjTUdizUljycgmzYjizkVkykaiDu16a0qpz87qnMPDS8fmScknz86WScJhTHuqecYhW0gEMUEhT86IzVt4zZsVzAkEDQrnCRj4ftu0WVmJvAkkzClXHMokzdoT/EmjSsooyocyTClGPskoQ0NjSseTz883SQiHz03nS8HhzkqpTboTTqsVTbkSOlqKy8Ihz67tznwnTkwoz84ozcqlTU1tzqy4xEQkTcxrT81lzMgmzw0pTixpbmvlyEfnTdxqbcKiTESjy0fkzotpzNnn3fsnH46pzMtpX74lykbhT56rTkvoHMol/8/vS8jiysehz86qTkvnT8+uPMonQkIiRkZlzExsr03qzkykz8+sz89rf89pzy3sSsejT5ykT89mz06sTxvjz89qz30FzYljTiqTTMpmTbwJzs4dTUukzs2LzpsDTNroTy1ISEenTUppzizaze3uTMmlTcJiS0knShIxzcsGTflboUAAABAHRSTlP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AP//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////ex4nOAAACN5JREFUeJzll39MG9cdwIOMBrWLGzdWbA3Hs2kWQ2iOcnVjj9WpCwSFkAlqoJyzsRPKYs5nJmzI42xxwtrSTtuqjCzd0pDWyYbi0oQ1CRtBvYQpS5ZUbK2JCURRRFcNEUoghLoyRrW6Nfu+MxAg0LWa+te+YB9+ft8P31/v+95b4/sfZc3XCajN1+trp2rh7dGvDOgaV+uyD42Oer2j3tHRQ7069fhXAYxs0V27uyCjt0dv3727Vbdl5EsCRqq6tt5eJnhga1e1+ksA8rp1P0hI17uP33y+tPT5m49ndc0N6brz/hugeovNduaM7cz2t9KlIG0g+Hn9re3isG3LzBcDUmttd2w225bdUmnr6eJgyGJxhoLB4tOtUuluQN+x3dme+gUAXaoH66uvS9tOB4O8HSES2clAGs9bFEfbpNdHgH3Hk7oqQDfjsR0+/OiPpW3vOemgJYCUyB5TImUMOP+mnYC4OQATPDOrALq0AwMDnpF0aVGQBhU6FuZMcVM8HufCgAmTfLAIjPB4PAPalQHN+fr82hlpWzGNAognNxAslih+IzhOiZnFbdIZfX5+fvNKgDJJmaQ5VdqmCILVyGXCmpqxMNvHajDGBYNhiyJdmtpcViYZfxjQ0KDX66ulbUGaViITwcbfd4DIOS6On8AgTAjRlmC6tApmlumXA3LbdTrdu+ltO3mSV7rYqGbsr6Aul8f9fvmEPIFwKWOcfWebtESXp2tfDmjUdTXl7pYqQD9MRFlQDv1JLnfL5wUjoq4wIu0K6e7criZd41JAXlZvb++b0qM0yQcgeNj46N/lcoqiHPCi5hAsEVBy/FHpm73ZvfvylgCme69dq0xvDcYQ8mN90JXvfZHKpNxWSqDcIgLbQCAUsLSmV8quyaYXA/KyjIfunkiHBID/LPadklMvvioXBIdfoIRMgaLcIoF12VFQ0bbrrvFQVt4iwHSN11uTXhRSKjlC/P9gPGP4/A8CY40yjIAJmaINUBFKni5qrRn1yuoXAQqh8dxvVUDxu1jNnD4l7H1Ozqj8DIhoAyUSXFBQitaPvV5v4QPA+Raj0VhaFEKojx1zTIA+aAjMM3/8JrMtypgBAFZgAnYigrhQUanReKglZQGQlX3rVsup93iSdgEAkgd++w0q/+fPGcL+YWaYsX5DnpkwYYwlIFPFp1pu3crOWgCk9PbK7p8KIsRFcQQh6JmM1e+37n3ne8+ohsEE/yUDGCESWGJDAHWeOiaTyRYsqJndvHnz8Y+CPDKJEYAAgANg+aeb/vYbl9k8LCTiAOnEUehDJP3RE6AyWzMHqJSVl5eXHg3SkENIAUUJAlYZFlSvvfOqijEb3OCFmAwIr4YllHzw6FpdebnsygJgamqqtJiO8XHRgsxMrG8eNst/sulf7zMqK/yZSIXcDRaYeBQqLs2bmnpjdg6QW97QoC6FZQBV7JhwYxNAnxk2mz/d9P1fcX7QHxYzAUGYgHIMcLyitGxcXz4PqNNLJNq1CjvJsZGoKg4hEAWqL/raL3++05525JLf4BZwEOTboNI5DinWaiUSfd0cIE8vadYWd/IIEf40TuWIqralKS0nLQXOgl80yc5yZDgtDL+RS1GHO+JnCSilzrWTAMibA6TkNzdPHu+E/suykT6H6AEjGKyXnk17+dvf2m/AnxJpoOQRlYblMKC9uXk8ZR4wLmmePNHJkyTBanAdi0EEx83utJde3/9bJhHE+UJgEWfvPCFZDCiTSCS7Op1KpSmRxkQWzGahz3xkzUsvxM24mAQmUcysSYksT+4ClbJ5F2YbcnJyPut00rwr0QoEHEYIvBUy+dJPP/wEntgJWJE4ja4Y7+zcBSoNlXOAg3UVFRWvPOkkYS2JlShawJgFSKT85TWPPZsIgTC3HvsQCt3YlVGRUXdwfi1U9iQlvXLDicRCENcCJVj9qk8gDO6fffijF4YNKivD4CzijkByyHnjXlJSz+aFxVTX0dNz4GMnTyqJhcVg8FvBcTNl+c7r+7/r9hsWGgKh5Owf3DjQ09Ox/sFqPAc+PLIjRKKI2NDcmYlU4mo6yTz99pFEChI5wP1gxyOgcO5BP/AVarU5+3Z8gMiYaa6jQQvCngtCGmP4x1loT4m+qmFNiEP076q0Wm3hwQeAe1CYkv4dFgvPsQkn5NDTRAsiDPPDv7jnHYAq4nl6Rz9M195b1BP3VExKJvdtpIMIFiS2AccRL2uGusRQ7rePiF1ZNCBmt9AbsySTkxV7Fu8LHdU5OTP9G0MBMhaHrpboq7iiKAIev3/aLXb1MXCARKGN/TMwu2PJxpJ1LqOiomroKZpEJBHViAS3aMYYNv4xR0KfIBHHx9ZX4RDuWbo3Zk339PT0X+B5DgXiOA6O+V0R237y13hvJFyQJp6/cD8Jcpi1dG/0DV1MAhkCAkJ4dxpzJBAqv7gvntVAAv002mCnL6w/ADMvrl8G8KWch+F7F6/STgvi+xIbLAgRFh9haANX4XxA88kX7iX1JJ0/71sO8LVUHejJ6EhO5kMkB/2ZIDTgiMbfB//bwUb7TAi8C/FXknHVFrYQDwOuztZnZGQUXjkYoO0caScRkTgk4SMSBA+REUSTV64UwqT62au+hwG+odnp7oru+sp/Jtt5KDfEo3DEFOkzXU1DsRjiSJ5Prqmsr+hOrZ8d8q0E8O3JrZrOma6vq6mJ8JYCS4QkyQA+a5JchC6g+UhNzfmZ6emcqtw9vpUBvv5ydfVMo3Zf9uBgHypQYmWLEnoqUtIoeXAwG387o67b6FsN4BtKKWlvbG9vLJEZjYOuDUipLMCHtg2uwQljtvjVZEnKBd/qAF/8nK6hTK1uUDc03TLCGcDonfB6M73GmqbtMFqmbtAdW6rw8H3hWMoUHBhH4LVd19Qrg8PQG106/ZxMlSzXX+nGUlWy7vK62nVLBT5fvlzyZ9NDs1e6Mz1VqL48sFQ8A+tq1VWBFSavfGujP6tvrx3weGy2w/DjGRjQl9XfQCtOXf3eWHy8o36msbFRWz3d/YRi1Wlf6831/wXwH5gC7KdtkjI7AAAAAElFTkSuQmCC' }; var xplorerDB = null; var windowResizeTimeOut = null; var windowRef = null; var mapContainer = null; var statusContainer = null; var legendContainer = null; var previewContainer = null; var searchContainer = null; var ikaCoreAddContainer = null; var mapCanvas = null; var dragMouseDown = false; var dragPrevX = 0; var dragPrevY = 0; var allianceInput = null; var playerInput = null; var cityInput = null; var playerStatusSelect = null; var distanceSelect = null; var luxuryResourceSelect = null; var townHallLevelLowSelect = null; var townHallLevelHighSelect = null; var militaryScoreLowInput = null; var militaryScoreHighInput = null; var reportSelect = null; var highlightInactiveCheckbox = null; var highlightVacationCheckbox = null; var updateButton = null; var scanCenterXInput = null; var scanCenterYInput = null; var scanRangeInput = null; var scanDelayMinInput = null; var scanDelayMaxInput = null; var rescanWaitTimeInput = null; var ownIslands = []; var selectedOwnCity = null; var cities = []; var alliances = []; var players = []; var islands = []; var filterIndex = 0; var filtersApplied = false; var searchStore = []; var searchStoreSelect = null; var worldMapViewOriginalHandleMapData; const HTML_ELEMENT = { br: 'br', div: 'div', tbody: 'tbody', tr: 'tr', th: 'th', td: 'td', img: 'img', button: 'input', a: 'a', h1: 'h1', h2: 'h2', h3: 'h3', h4: 'h4', h5: 'h5' }; const ALLIANCE_COLOR = { 0: 'green', 1: 'red', 2: 'blue', 3: 'olive', 4: 'grey', 5: 'yellow', 6: 'aqua', 7: 'purple', 8: 'fuchsia', 9: 'orange', 10: 'orchid', 11: 'peru', 12: 'rosybrown', 13: 'salmon', 14: 'skyblue' } const ALLIANCE_TEXT_COLOR = { 0: 'white', 1: 'white', 2: 'white', 3: 'white', 4: 'white', 5: 'black', 6: 'black', 7: 'white', 8: 'white', 9: 'white', 10: 'white', 11: 'white', 12: 'white', 13: 'white', 14: 'white' } const REPORT_TYPE = { rtIslands: 'Islands', rtIslandsGenerals: 'Islands - Generals', rtIslandsScore: 'Islands - Score', rtIslandsGold: 'Islands - Gold', rtPlayers: 'Players', rtPlayersGenerals: 'Players - Generals', rtPlayersScore: 'Players - Score', rtPlayersGold: 'Players - Gold' }; const REPORT_TYPE_INDEX = [ REPORT_TYPE.rtIslands, REPORT_TYPE.rtIslandsGenerals, REPORT_TYPE.rtIslandsScore, REPORT_TYPE.rtIslandsGold, REPORT_TYPE.rtPlayers, REPORT_TYPE.rtPlayersGenerals, REPORT_TYPE.rtPlayersScore, REPORT_TYPE.rtPlayersGold ]; const PLAYER_STATUS_SELECT = { psAny: 'Any', psActive: 'Active', psVacation: 'Vacation', psInactive: 'Inactive' }; const PLAYER_STATUS_SELECT_INDEX = [ PLAYER_STATUS_SELECT.psAny, PLAYER_STATUS_SELECT.psActive, PLAYER_STATUS_SELECT.psVacation, PLAYER_STATUS_SELECT.psInactive ]; const LUXURY_RESOURCE_SELECT = { lrAny: 'Any', lrWine: 'Wine', lrMarble: 'Marble', lrCrystal: 'Crystal', lrSulfur: 'Sulfur' }; const LUXURY_RESOURCE_SELECT_INDEX = [ LUXURY_RESOURCE_SELECT.lrAny, LUXURY_RESOURCE_SELECT.lrWine, LUXURY_RESOURCE_SELECT.lrMarble, LUXURY_RESOURCE_SELECT.lrCrystal, LUXURY_RESOURCE_SELECT.lrSulfur ]; const ISLAND_LUXURY = ['wine','sulphur', 'marble', 'crystal']; const PLAYER_STATUS = { 0: 'active', 1: 'vacation', 2: 'inactive' }; /* const ISLAND_LUXURY = { 0: 'unknown', 1: 'wine', 2: 'marble', 3: 'crystal', 4: 'sulfur' } */ // remove multiple, leading or trailing spaces function trim(s) { s = s.replace(/(^\s*)|(\s*$)/gi,""); s = s.replace(/[ ]{2,}/gi," "); s = s.replace(/\n /,"\n"); return s; } // Array.unique( strict ) - Remove duplicate values (have to sort array before using) Array.prototype.unique = function() { var result = []; for(i=0; i < this.length; i++ ) { if(i==0) result.push(this[i]); if((i>0) && (this[i].toCSVString().localeCompare(this[i-1].toCSVString()) != 0)) { result.push(this[i]); } } return result; }; Array.prototype.removeById = function(id) { for(i=0; i < this.length; i++ ) { if(this[i].id == id) { this.splice(i,1); break; } } } function removeElementsByClassname(root, className, parent) { var elems = root.getElementsByClassName(className); while(elems.length > 0) { parent.removeChild(elems[0]); } } function stringToBoolean(str){ return (str == 'true'); } function sumArray(array) { var result = 0; for (var i in array) { if(typeof(array[i] == 'number')){result += array[i];} } return result; } function getTimestamp() { var currentTime = new Date(); var year = currentTime.getFullYear(); var month = currentTime.getMonth(); var day = currentTime.getDay(); var hours = currentTime.getHours(); var minutes = currentTime.getMinutes(); var seconds = currentTime.getSeconds(); var ts = year + '-'; if(month < 10){ts = ts + '0' + month + '-';} else{ts = ts + month + '-';} if(day < 10){ts = ts + '0' + day + ' ';} else{ts = ts + day + ' ';} if(hours < 10){ts = ts + '0' + hours + ':';} else{ts = ts + hours + ':';} if(minutes < 10){ts = ts + '0' + minutes + ':';} else{ts = ts + minutes + ':';} if(seconds < 10){ts = ts + '0' + seconds;} else{ts = ts + seconds;} return ts; } // Firebug console log function consoleLog(object){ console.log(object); //if(consoleBackup){ // consoleBackup.log(object); //} } // Firebug console dir function consoleDir(object){ console.dir(object); } // Firebug console time function consoleTime(name){ if (syslogLogLevel > 2) { console.time(name); } } // Firebug console timeEnd function consoleTimeEnd(name){ if (syslogLogLevel > 2) { console.timeEnd(name); } } // Generic syslog targeting Java and/or Firebug console function syslog(logMessage, logLevel){ if(logLevel == null){ logLevel = 4; } var syslogMessage = getTimestamp() + ' ' + arguments.callee.caller.name + ' ("' + logMessage + '")'; // log only if loglevel lower than globally set log level if(logLevel <= syslogLogLevel){ // Log into Java Console if enabled if(syslogJavaConsoleEnabled){ GM_log(syslogMessage); } // Log into Firebug if enabled if(syslogFirebugEnabled){ consoleLog(syslogMessage); } } } function intToString(num){ return num + ''; } function removeAllChildElements(item) { while(item.hasChildNodes()) { item.removeChild(item.firstChild); } } function xplorerSearchDiv() { result = document.createElement('div'); result.setAttribute('class', 'xplorer_searchDiv'); return result; } function xplorerSearchInputDiv(parent, caption, width, value, onKeyUp) { var div = xplorerSearchDiv(); div.appendChild(xplorerCaption(caption)); var input = xplorerInput(); input.style.width = width; input.value = value; if(onKeyUp != '') input.addEventListener('keyup', onKeyUp, false); div.appendChild(input); parent.appendChild(div); return input; } function xplorerSearchSelectDiv(parent, caption, values, onChange) { var div = xplorerSearchDiv(); div.appendChild(xplorerCaption(caption)); var select = xplorerSelect(); if(onChange != '') select.addEventListener('change', onChange, false); for(i=0; i < values.length; i++ ) { select.appendChild(new Option(values[i],i)); } div.appendChild(select); parent.appendChild(div); return select; } function xplorerButtonsDiv(buttonDefs) { var div = htmlDiv(); div.style.clear = 'both'; for (var i = 0; i < buttonDefs.length; i++) { var button = xplorerButton(buttonDefs[i].name); button.addEventListener('click', buttonDefs[i].onClick, false); div.appendChild(button); } return div; } function xplorerHeading(text) { result = document.createElement('div'); result.style.clear = 'both'; result.setAttribute('class', 'xplorer_heading'); result.innerHTML = text; return result; } function xplorerCaption(text) { result = document.createElement('div'); result.setAttribute('class', 'xplorer_caption'); result.innerHTML = text; return result; } function xplorerButton(text) { result = document.createElement('input'); result.setAttribute('class', 'xplorer_button'); result.setAttribute('type', 'button'); result.setAttribute('name', text); result.setAttribute('value', text); return result; } function xplorerInput() { result = document.createElement('input'); result.setAttribute('class', 'xplorer_input'); return result; } function xplorerSelect() { result = document.createElement("select"); result.setAttribute('class', 'xplorer_select'); return result; } function xplorerCheckbox() { result = document.createElement("input"); result.setAttribute('class', 'xplorer_checkbox'); result.setAttribute('type', 'checkbox'); return result; } function xplorerLabel(text) { result = document.createElement("label"); result.setAttribute('class', 'xplorer_label'); result.textContent = text; return result; } function htmlElement(element, childElement){ result = document.createElement(element); result.setAttribute('class', 'xplorer_' + element); if(childElement) { if(typeof childElement == "string") { result.innerHTML = childElement; } else { result.appendChild(childElement); } } return result; } function htmlBr(childElement){ return htmlElement(HTML_ELEMENT.br, childElement); } function htmlDiv(childElement){ return htmlElement(HTML_ELEMENT.div, childElement); } function htmlH3(childElement){ return htmlElement(HTML_ELEMENT.h4, childElement); } function htmlH4(childElement){ return htmlElement(HTML_ELEMENT.h4, childElement); } function htmlH5(childElement){ return htmlElement(HTML_ELEMENT.h5, childElement); } function htmlTableBody(childElement){ return htmlElement(HTML_ELEMENT.tbody, childElement); } function htmlTableRow(childElement){ return htmlElement(HTML_ELEMENT.tr, childElement); } function htmlTableHeaderCell(childElement) { return htmlElement(HTML_ELEMENT.th, childElement); } function htmlTableCell(childElement) { return htmlElement(HTML_ELEMENT.td, childElement); } function htmlImg(image, title, width, height){ result = htmlElement(HTML_ELEMENT.img); result.setAttribute('src', image); if(title) result.setAttribute('title', title); if(width) result.setAttribute('width', width); if(height) result.setAttribute('height', height); return result; } function htmlButton(title){ result = htmlElement(HTML_ELEMENT.button); if(title) { result.setAttribute('type', 'button'); result.setAttribute('name', title); result.setAttribute('value', title); } return result; } function htmlAHref(url, childElement){ result = htmlElement(HTML_ELEMENT.a, childElement); result.setAttribute('href', url); return result; } function getDomain(){ return document.domain; } function formatTime(time, compact) { if (!compact) { var d = Math.floor(time / (60*24)) var h = Math.floor((time-d*60*24) / 60); var m = Math.floor(time - 60*h - 60*24*d); // minutes are always present, days and hours omitted if zero return (d > 0? d+"d ":"")+(h > 0? h+"h ":"")+m+"m"; } else { // compact format // if under a day -> show hours if (time < (24*60)) {return Math.round(time/60)+'h';} // show days else {return Math.round(time/60/24)+'d';} } } function $(id){ return document.getElementById(id); } function getHrefParam(href, param) { param = param.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]"); var regexStr = "[\\?&]"+param+"=([^&#]*)"; var regex = new RegExp( regexStr ); var results = regex.exec(href); if( results == null ) return ""; else return results[1]; } function getRequestParam(param) { return getHrefParam(window.location.href, param); } function ikariamGetServer() { var domain = getDomain(); return domain.substring(domain.indexOf('.') + 1, domain.length); } function ikariamGetWorld() { var domain = getDomain(); return domain.substring(1, domain.indexOf('.')); } function ikariamGetCurrentView(){ var result = getRequestParam('view'); if(!result) { result = getRequestParam('action'); } return result; } function ikariamIsCurrentView(name){ var result = name.localeCompare(ikariamGetCurrentView()) return (result == 0); } function ikariamIsAllyListView() { return (ikariamIsCurrentView('diplomacyAdvisorAlly') && (getRequestParam('listAllyMembers') == 1)); } function ikariamIsIslandView() { return ($('island') != null); } function ikariamIsMilitaryMovementsView() { return ($('fleetMovements') != null); } function ikariamIsWorldMapView() { return ($('worldmap_iso') != null); } function ikariamScoreToNum(score) { return parseInt(trim(score.replace (/,/g, ""))); } function ikariamParseCoordinatesFromString(str, coords) { coords.x = parseInt(str.substring(str.indexOf('[')+1, str.indexOf(':'))); coords.y = parseInt(str.substring(str.indexOf(':')+1, str.indexOf(']'))); } ikariamCalculateDistance = function(coordsA, coordsB) { return Math.sqrt(Math.pow(coordsA.x-coordsB.x,2)+Math.pow(coordsA.y-coordsB.y,2)); } // travel time for transport ships ikariamCalculateTravelTime = function(coordsA, coordsB) { var result = (1200/60) * ikariamCalculateDistance(coordsA, coordsB); if (result == 0) return 10; else return result; } ikariamTravelTimeAsString = function(coordsA, coordsB, compact) { return formatTime(ikariamCalculateTravelTime(coordsA, coordsB), compact); } /* * Returns an array containing a list of own cities * Reads the information from the city selection drop down * so can be called from any view */ function ikariamGetOwnCities(){ var result = []; try { var cityElements = unsafeWindow.dataSetForView.relatedCityData; } catch(e) { syslog('Error retrieving own cities: "' + e.description + '"', 1); return result; } for (key in cityElements) { if ((key == 'additionalInfo') || (key == 'selectedCity')) continue; var city = new mdbCity(); city.island = new mdbIsland(); city.id = parseInt(cityElements[key].id); city.name = cityElements[key].name; city.luxuryResource = parseInt(cityElements[key].trafeGood); city.selected = (key == cityElements.selectedCity); ikariamParseCoordinatesFromString(cityElements[key].coords, city.island.coords); city.relationship = cityElements[key].relationship; result.push(city); } return result; } function ikariamAllyListViewGetAllianceId() { return parseInt(getHrefParam($('allyinfo').getElementsByClassName('icon_msg')[0].getAttribute('href'), 'allyId')); } function ikariamAllyListViewGetAllianceInfo(alliance) { alliance.name = $('allyinfo').getElementsByTagName('td')[0].title; alliance.longName = $('allyinfo').getElementsByTagName('td')[1].title; alliance.lastUpdate = new Date().getTime(); } function ikariamAllyListViewGetPlayerInfos() { var memberList = $('memberList'); var playerInfsTmp1 = Array.prototype.slice.call(memberList.getElementsByClassName('default')); var playerInfsTmp2 = Array.prototype.slice.call(memberList.getElementsByClassName('alt')); return playerInfsTmp1.concat(playerInfsTmp2); } function ikariamAllyListViewGetPlayerId(playerInfo) { var sendMessageAction = playerInfo.getElementsByClassName('message')[0]; if(sendMessageAction) { return parseInt(getHrefParam(playerInfo.getElementsByClassName('message')[0].getAttribute('href'), 'receiverId')); } // own information stored under id = 0 since real id is not available in this view else { return 0; } } function ikariamAllyListViewGetPlayerInfo(playerInfo, player) { // player name player.name = playerInfo.childNodes[3].textContent; // player total score player.score = ikariamScoreToNum(playerInfo.childNodes[9].textContent); // player rank player.rank = playerInfo.childNodes[7].textContent; // online status -> sets both player.status and player.onlineStatus var lastOnlineText = playerInfo.childNodes[1].getAttribute('title'); player.lastOnline = lastOnlineText.substring(lastOnlineText.indexOf(':')+2, lastOnlineText.length); player.onlineStatus = playerInfo.childNodes[1].getAttribute('class'); switch(player.onlineStatus) { case 'online': case 'offline': player.status = 'active'; break; case 'inactive': player.status = 'inactive'; break; case 'vacation': player.status = 'vacation'; break; } } function ikariamAllyListViewGetCityInfos(playerInfo) { return playerInfo.getElementsByClassName('city'); } function ikariamAllyListViewGetCityId(cityInfo) { var href = cityInfo.getAttribute('href'); return parseInt(getHrefParam(href, 'selectCity')); } function ikariamAllyListViewGetCityInfo(cityInfo, city) { var cityText = cityInfo.textContent; city.name = cityText.substring(0, cityText.indexOf('[')-1); } function ikariamAllyListViewGetIslandId(cityInfo) { var href = cityInfo.getAttribute('href'); return parseInt(getHrefParam(href, 'id')); } function ikariamAllyListViewGetIslandInfo(cityInfo, island) { ikariamParseCoordinatesFromString(cityInfo.textContent, island.coords) island.lastUpdate = new Date().getTime(); island.setProcessLevel(2); } function ikariamIslandViewGetIslandId() { return parseInt(unsafeWindow.ikariam.backgroundView.screen.data.id); } function ikariamIslandViewGetIslandInfo(island) { var data = unsafeWindow.ikariam.backgroundView.screen.data; island.name = data.name; island.coords.x = parseInt(data.xCoord); island.coords.y = parseInt(data.yCoord); island.sawmillLevel = parseInt(data.resourceLevel); island.luxury = parseInt(data.tradegood); island.luxuryLevel = parseInt(data.tradegoodLevel); island.wonder = parseInt(data.wonder); island.wonderLevel = parseInt(data.wonderLevel); island.lastUpdate = new Date().getTime(); island.setProcessLevel(3); } function ikariamIslandViewGetCityInfos() { return unsafeWindow.ikariam.backgroundView.screen.data.cities; } function ikariamIslandViewGetCityId(cityInfo) { return parseInt(cityInfo.id); } function ikariamIslandViewGetCityInfo(cityInfo, city) { city.name = cityInfo.name; // city townhall size city.townHallSize = parseInt(cityInfo.level); city.lastUpdate = new Date().getTime(); } function ikariamIslandViewGetAllianceId(cityInfo) { return parseInt(cityInfo.ownerAllyId); } function ikariamIslandViewGetAllianceInfo(cityInfo, alliance) { if(cityInfo.ownerAllyId == 0) alliance.name = '-' else alliance.name = cityInfo.ownerAllyTag; alliance.lastUpdate = new Date().getTime(); } function ikariamIslandViewGetPlayerId(cityInfo) { return parseInt(cityInfo.ownerId); } function ikariamIslandViewGetPlayerInfo(cityInfo, avatarScores, player) { player.name = cityInfo.ownerName; player.status = cityInfo.state; player.buildersScore = ikariamScoreToNum(avatarScores[player.id].building_score_main)/100; player.scientistScore = ikariamScoreToNum(avatarScores[player.id].research_score_main)/100; player.generals = ikariamScoreToNum(avatarScores[player.id].army_score_main)/100; player.gold = ikariamScoreToNum(avatarScores[player.id].trader_score_secondary); // this is now missing the number of citizens, could not find it anywhere player.score = player.buildersScore + player.scientistScore + player.generals; player.lastUpdate = new Date().getTime(); } function ikariamMilitaryMovementsViewGetMovementInfos() { return $('fleetMovements').getElementsByClassName('locationEvents')[0].getElementsByTagName('tr'); } function ikariamMilitaryMovementsViewGetMovementId(movementInfo) { return parseInt(movementInfo.getElementsByTagName('td')[1].id.substring(8)); } function ikariamAllyListViewGetPlayerInfos() { var memberList = $('memberList'); var playerInfsTmp1 = Array.prototype.slice.call(memberList.getElementsByClassName('default')); var playerInfsTmp2 = Array.prototype.slice.call(memberList.getElementsByClassName('alt')); return playerInfsTmp1.concat(playerInfsTmp2); } function ikariamWorldMapViewGetIslandInfo(islandInfo, island) { island.name = islandInfo[1]; island.luxury = parseInt(islandInfo[2]); island.wonder = parseInt(islandInfo[3]); island.islandType = parseInt(islandInfo[5]); island.cityCount = parseInt(islandInfo[7]); // change 5.7.2015, do not modify lastUpdate when in worldmapview // island.lastUpdate = new Date().getTime(); island.setProcessLevel(1); } function getArrayItemByID(array, id) { for (var i = 0; i < array.length; i++) { if(array[i].id == id) return array[i]; } return null; } function getArrayItemByName(array, name) { for (var i = 0; i < array.length; i++) { if(array[i].name == name) return array[i]; } return null; } function getArrayItemByCoordinates(array, x, y) { for (var i = 0; i < array.length; i++) { if((array[i].coords.x == x) && (array[i].coords.y == y)) return array[i]; } return null; } function xplorerStoreMemberCities(memberCities) { var key = getDomain() + '.xplorerMemberCities'; GM_setValue(key, uneval(memberCities)); } function xplorerLoadMemberCities() { var key = getDomain() + '.xplorerMemberCities'; return (eval(GM_getValue(key, ''))); } //testing data types accurately in JavaScript (opposed to "typeof") //from http://bonsaiden.github.com/JavaScript-Garden/ function is(type, obj) { var clas = Object.prototype.toString.call(obj).slice(8, -1); return obj !== undefined && obj !== null && clas === type; } function compareById(a, b) { if(is("Number", a) && is("Number", b)) { return a - b; } else { if(is("Object", a) && is("Number", b)) { return a.id - b; } else { return a.id - b.id; } } } function compareByName(a, b) { if(is("String", a) && is("String", b)) { return a.localeCompare(b); } else { if(is("Object", a) && is("String", b)) { return a.name.localeCompare(b); } else { return a.name.localeCompare(b.name); } } } function stringCompare(a, b, index) { if(is("String", a) && is("String", b)) { return a.localeCompare(b); } else { if(is("Object", a) && is("String", b)) { return a[index].localeCompare(b); } else { return a[index].localeCompare(b[index]); } } } /**************************************************** sortedList ****************************************************/ function sortedList(compareFunction, indexProperty) { this.list = []; this.compareFunction = compareFunction; this.indexProperty = indexProperty; } sortedList.prototype.add = function(item) { var position = this.indexOf(item[this.indexProperty], true); this.list.splice(position, 0, item); } sortedList.prototype.toJSON = function() { var result = []; for (var i = 0; i < this.list.length; i++) { result.push(this.list[i].toJSON()); } return result; } sortedList.prototype.indexOf = function(value, findNearest, compareFunction) { var compFunc; if(compareFunction) { compFunc = compareFunction;} else compFunc = this.compareFunction; var low = 0; var high = this.list.length - 1; var i, comparison; while (low <= high) { i = Math.floor((low + high) / 2); comparison = compFunc(this.list[i], value, this.indexProperty); if (comparison < 0) { low = i + 1; continue } if (comparison > 0) { high = i - 1; continue; } return i; } // return nearest item (used internally when adding) if requested if (findNearest) return low; // otherwise no match return -1; } sortedList.prototype.find = function(value, findNearest, compareFunction) { return this.list[this.indexOf(value, findNearest, compareFunction)]; } sortedList.prototype.filterString = function(value, valueAttribute, filterMatchAttribute, filterIndex, caseSensitive, subString) { var compValue = ''; if(!caseSensitive) compValue = value.toLowerCase(); else compValue = value; var compValues = compValue.split(" "); // the items contained in the list must have an attribute named with the value of valueAttribute // and they must have an array attribute named with the value of filterMatchAttribute for (var i = 0; i < this.list.length; i++) { var found = false; var itemValue = this.list[i][valueAttribute]; if(!caseSensitive) itemValue = itemValue.toLowerCase(); for (var j = 0; j < compValues.length; j++) { if((j > 0) && (compValues[j] == '')) continue; if(!subString) found = (itemValue == compValues[j]); else found = (itemValue.indexOf(compValues[j]) != -1); if (found) break; } this.list[i][filterMatchAttribute][filterIndex] = found; } } /**************************************************** mdbCoordinates ****************************************************/ function mdbCoordinates() { this.x = 0; this.y = 0; } mdbCoordinates.prototype.asString = function() { return '[' + this.x + ':' + this.y + ']'; } mdbCoordinates.prototype.isInRange = function(centerX, centerY, range) { return ((this.x >= (centerX-range)) && (this.x <= (centerX+range)) && (this.y >= (centerY-range)) && (this.y <= (centerY+range))); } /**************************************************** mdbIsland ****************************************************/ function mdbIsland() { this.id = ''; this.name = ''; this.luxury = 0; this.coords = new mdbCoordinates(); this.lastUpdate = 0; this.wonder = 0; this.wonderLevel = 0; this.sawmillLevel = 0; this.luxuryLevel = 0; this.cityCount = 0; this.processLevel = 0; // 1=world map view, 2=ally list view, 3=island view this.cities = []; this.islandBox = null; this.filterMatch = [true]; } mdbIsland.prototype.setProcessLevel = function(processLevel) { if((processLevel > this.processLevel) || isNaN(this.processLevel)) this.processLevel = processLevel; } mdbIsland.prototype.toJSON = function() { var result = []; result.push(this.id, this.name, this.luxury, this.coords.x, this.coords.y, this.lastUpdate, this.wonder, this.wonderLevel, this.sawmillLevel, this.luxuryLevel, this.cityCount, this.processLevel); return result; } mdbIsland.prototype.fromJSON = function(json) { this.id = parseInt(json[0]); this.name = json[1]; this.luxury = json[2]; this.coords.x = parseInt(json[3]); this.coords.y = parseInt(json[4]); this.lastUpdate = parseInt(json[5]); this.wonder = parseInt(json[6]); this.wonderLevel = parseInt(json[7]); this.sawmillLevel = parseInt(json[8]); this.luxuryLevel = parseInt(json[9]); this.cityCount = parseInt(json[10]); this.processLevel = parseInt(json[11]); } mdbIsland.prototype.filterMatches = function() { for (var i = 0; i < this.filterMatch.length; i++) { if (this.filterMatch[i]) return true; } return false; } mdbIsland.prototype.clearFilterMatch = function() { this.filterMatch = []; } // "Island";X-coordinate;Y-coordinate;"Luxury" mdbIsland.prototype.toCSVString = function() { var result = '"' + this.name + '";'; result += this.coords.x + ';'; result += this.coords.y + ';'; result += '"' + this.luxury + '";'; return result; } mdbIsland.prototype.containsSelectedCity = function() { var result = false; for (var i = 0; i < this.cities.length; i++) { if(this.cities[i].selected) { result = true; break; } } return result; } mdbIsland.prototype.daysSinceLastUpdate = function() { return Math.floor((new Date().getTime() - this.lastUpdate)/(1000*60*60*24)); } mdbIsland.prototype.citiesAsString = function() { var result = ''; for (var i = 0; i < this.cities.length; i++) { result += this.cities[i].name; if(i < this.cities.length - 1) result += ', '; } return result; } mdbIsland.prototype.getRelationship = function() { var result = []; for (var i = 0; i < this.cities.length; i++) { var relationship = this.cities[i].relationship; if((relationship != '') && (result.indexOf(relationship) == -1)) result.push(relationship); } result.sort(); return result; } mdbIsland.prototype.filter = function() { if(this.islandBox == null) return; // check filtering for the whole island var islandMatches = !filtersApplied; for (var i = 0; i < this.cities.length; i++) { var city = this.cities[i]; if(city.filterMatches() && city.player.filterMatches() && city.player.alliance.filterMatches()) { islandMatches = true; break; } } // hide or show islandBox if(islandMatches) this.islandBox.style.visibility = 'visible'; else this.islandBox.style.visibility = 'hidden'; } mdbIsland.prototype.draw = function(alliances, parent, reportType, highlightInactive, highlightVacation) { // do not draw empty islands at all if(this.cityCount == 0) return; var containsInactive = false; var containsVacation = false; var valueScale = islandScale; var size = valueScale * mapScale; // to put larger boxes on the bottom... var zindex = (5000 - size); var left = mapXOffset + (this.coords.x*mapScaleRatio*mapScale/10)-Math.round(size/2); var top = mapYOffset + (this.coords.y*mapScaleRatio*mapScale/10)-Math.round(size/2); if (left < 0) left = 0; if (top < 0) top = 0; // color by lastUpdate /* var daysSinceLastUpdate = this.daysSinceLastUpdate(); var color = 'Gray'; if (daysSinceLastUpdate < 7) color = 'Green'; else if (daysSinceLastUpdate < 30) color = "Orange"; else color = "Red"; if(this.processLevel != 3) color = 'Gray'; */ // color by relationship var color = 'background-color: gray'; var relationships = this.getRelationship().join(); if(relationships != '') syslog(relationships); switch (relationships) { case 'ownCity': color = 'background-color: blue'; break; case 'deployedCities': color = 'background-color: green'; break; case 'occupiedCities': color = 'background-color: red'; break; case 'deployedCities,ownCity': color = 'background: linear-gradient(to right, blue 50%, green 50%)'; break; case 'occupiedCities,ownCity': color = 'background: linear-gradient(to right, blue 50%, red 50%)'; break; case 'deployedCities,occupiedCities,ownCity': color = 'background: linear-gradient(to right, blue 34%, green 33%, red 33%)'; break; case 'deployedCities,occupiedCities': color = 'background: linear-gradient(to right, green 50%, red 50%)'; break; } if(this.processLevel != 3) color = 'background-color: LightGray'; this.islandBox = htmlDiv(); this.islandBox.setAttribute('class', 'mdbIsland'); this.islandBox.setAttribute('id', this.id); this.islandBox.setAttribute('x', this.coords.x); this.islandBox.setAttribute('y', this.coords.y); this.islandBox.setAttribute('title', this.name + ' ' + this.coords.asString()); this.islandBox.setAttribute('style', 'z-index:'+zindex+';opacity:.60; left:' + left + 'px; top:' + top + 'px; height:' + size + 'px; width:' + size + 'px;' + color); // #### Gradient example //this.islandBox.setAttribute('style', 'z-index:'+zindex+';opacity:.60; left:' + left + 'px; top:' + top + 'px; height:' + size + 'px; width:' + size + 'px; background: linear-gradient(to right, red 50%, green 50%)'); /* // highligh inactive if ((highlightInactive && containsInactive) || (highlightVacation && containsVacation)) { this.islandBox.style.border = '2px solid yellow'; } */ this.islandBox.addEventListener('mouseover', onmdbIslandMouseOver, false); this.islandBox.addEventListener('click', onmdbIslandClick, false); // http://s2.nn.ikariam.com/index.php?currentIslandId=908&view=island&xcoord=33&ycoord=43&submit.x=0&submit.y=0 this.islandBox.setAttribute('href', '?currentIslandId=' + this.id + '&view=island&xcoord=' + this.coords.x + '&ycoord=' + this.coords.y + '&submit.x=0&submit.y=0'); parent.appendChild(this.islandBox); } function onmdbIslandMouseOver() { consoleTime('xplorer.onmdbIslandMouseOver'); updatePreview(islands.find(parseInt(this.getAttribute('id')))); consoleTimeEnd('xplorer.onmdbIslandMouseOver'); } function onmdbIslandClick(e) { // navigate the main (calling) browser window to chosen city's island view window.location = this.getAttribute('href'); } mdbIsland.prototype.preview = function(parent) { // Table body var tblBody = htmlTableBody(); // Header row var tblHeader = htmlTableRow(); tblHeader.appendChild(htmlTableHeaderCell('Player')); tblHeader.appendChild(htmlTableHeaderCell('Status')); tblHeader.appendChild(htmlTableHeaderCell('Alliance')); tblHeader.appendChild(htmlTableHeaderCell('Generals')); tblHeader.appendChild(htmlTableHeaderCell('Score')); tblHeader.appendChild(htmlTableHeaderCell('Gold')); tblHeader.appendChild(htmlTableHeaderCell('City')); tblHeader.appendChild(htmlTableHeaderCell('TH')); tblHeader.appendChild(htmlTableHeaderCell('Luxury')); //tblHeader.appendChild(htmlTableHeaderCell('fCity')); //tblHeader.appendChild(htmlTableHeaderCell('fPlayer')); //tblHeader.appendChild(htmlTableHeaderCell('fAlliance')); tblBody.appendChild(tblHeader); for (var i = 0; i < this.cities.length; i++) { var tr = htmlTableRow(); var city = this.cities[i]; if(!city.filterMatches() || !city.player.filterMatches() || !city.player.alliance.filterMatches()) continue; tr.appendChild(htmlTableCell(city.player.name)); tr.appendChild(htmlTableCell(city.player.status)); tr.appendChild(htmlTableCell(city.player.alliance.name)); tr.appendChild(htmlTableCell(intToString(city.player.generals))); tr.appendChild(htmlTableCell(intToString(city.player.score))); tr.appendChild(htmlTableCell(intToString(city.player.gold))); // eg. http://s1.nn.ikariam.com/index.php?view=island&cityId=90272 var cityLink = htmlAHref('?view=island&cityId=' + city.id, this.cities[i].name); cityLink.addEventListener('click', onCityLinkClick, false); tr.appendChild(htmlTableCell(cityLink)); tr.appendChild(htmlTableCell(intToString(city.townHallSize))); tr.appendChild(htmlTableCell(intToString(this.luxury))); /* tr.appendChild(htmlTableCell(city.filterMatches().toString())); tr.appendChild(htmlTableCell(city.player.filterMatches().toString())); tr.appendChild(htmlTableCell(city.player.alliance.filterMatches().toString())); */ tblBody.appendChild(tr); } parent.appendChild(tblBody); } function onCityLinkClick(e) { // navigate the main (calling) browser window to chosen city's island view window.location = this.href; // prevent loading the page to the map window e.preventDefault(); } mdbIsland.prototype.getPreviewHeading = function() { return this.name + ' ' + this.coords.asString() + ' ' + ikariamTravelTimeAsString(this.coords, selectedOwnCity.island.coords, false) + ' (' + this.daysSinceLastUpdate() + ' days)'; } /**************************************************** mdbAlliance ****************************************************/ function mdbAlliance() { this.id = 0; this.name = ''; this.longName =''; this.lastUpdate = 0; this.players = []; this.filterMatch = [true]; } mdbAlliance.prototype.toJSON = function() { var result = []; result.push(this.id, this.name, this.longName, this.lastUpdate); return result; } mdbAlliance.prototype.fromJSON = function(json) { this.id = parseInt(json[0]); this.name = json[1]; this.longName = json[2]; this.lastUpdate = parseInt(json[3]); } mdbAlliance.prototype.filterMatches = function() { for (var i = 0; i < this.filterMatch.length; i++) { if (this.filterMatch[i]) return true; } return false; } mdbAlliance.prototype.clearFilterMatch = function() { this.filterMatch = []; } /**************************************************** mdbPlayer ****************************************************/ function mdbPlayer() { this.id = 0; this.name = ''; this.status =''; this.lastOnline =''; this.onlineStatus =''; this.allianceId = 0; this.alliance = null; this.score = 0; this.gold = 0; this.generals = 0; this.buildersScore = 0; this.scientistScore = 0; this.lastUpdate = 0; this.attackScore = 0; this.defenceScore = 0; this.cities = []; this.filterMatch = [true]; } mdbPlayer.prototype.toJSON = function() { var result = []; result.push(this.id, this.name, this.status, this.lastOnline, this.onlineStatus, this.allianceId, this.score, this.gold, this.generals, this.buildersScore, this.scientistScore, this.lastUpdate, this.attackScore, this.defenceScore); return result; } mdbPlayer.prototype.fromJSON = function(json) { this.id = parseInt(json[0]); this.name = json[1]; this.status = json[2]; this.lastOnline = json[3]; this.onlineStatus = json[4]; this.allianceId = parseInt(json[5]); this.score = parseInt(json[6]); this.gold = parseInt(json[7]); this.generals = parseInt(json[8]); this.buildersScore = parseInt(json[9]); this.scientistScore = parseInt(json[10]); this.lastUpdate = parseInt(json[11]); this.attackScore = parseInt(json[12]); this.defenceScore = parseInt(json[13]); } mdbPlayer.prototype.filterMatches = function() { //if (this.filterMatch == []) return true; for (var i = 0; i < this.filterMatch.length; i++) { if (this.filterMatch[i]) return true; } return false; } mdbPlayer.prototype.clearFilterMatch = function() { this.filterMatch = []; } mdbPlayer.prototype.setAlliance = function(alliance) { this.alliance = alliance; this.allianceId = alliance.id; } // "Player";"Alliance";"Status";"Score";"Generals";"Gold"; mdbPlayer.prototype.toCSVString = function() { var result = '"' + this.name + '";'; result += '"' + this.alliance + '";'; result += '"' + this.status + '";'; result += this.score + ';'; result += this.generals + ';'; result += this.gold + ';'; return result; } mdbPlayer.prototype.getCenterOfCities = function() { var result = new mdbCoordinates(); for (var i = 0; i < this.cities.length; i++) { result.x = result.x + parseInt(this.cities[i].island.coords.x); result.y = result.y + parseInt(this.cities[i].island.coords.y); } result.x = Math.round(result.x / this.cities.length); result.y = Math.round(result.y / this.cities.length); return result; } mdbPlayer.prototype.draw = function(alliances, parent, reportType, highlightInactive, highlightVacation) { var isInactive = false; var isOnVacation = false; var valueScale = 0; if(this.status == 'inactive') isInactive = true; if(this.status == 'vacation') isOnVacation = true; var playerValue = 0; switch (reportType) { case REPORT_TYPE.rtPlayers: playerValue = 1; valueScale = playerScale; break; case REPORT_TYPE.rtPlayersGenerals: playerValue = this.generals; valueScale = generalsScorePlayerScale; break; case REPORT_TYPE.rtPlayersScore: playerValue = this.score; valueScale = totalScorePlayerScale; break; case REPORT_TYPE.rtPlayersGold: playerValue = this.gold; valueScale = goldPlayerScale; break; default: syslog('mdbPlayer: Unknown report type ' + reportType); return; } if(reportType == REPORT_TYPE.rtPlayers) var size = playerValue*valueScale*mapScale else var size = Math.round(Math.sqrt(playerValue/valueScale))*mapScale; // to put larger boxed on the bottom... var zindex = (5000 - size); // use the average of city mdbCoordinates as the reporting center var coords = this.getCenterOfCities(); var left = mapXOffset + (coords.x*mapScaleRatio*mapScale/10)-Math.round(size/2); var top = mapYOffset + (coords.y*mapScaleRatio*mapScale/10)-Math.round(size/2); if (left < 0) left = 0; if (top < 0) top = 0; var color = ALLIANCE_COLOR[alliances.indexOf(this.alliance.id)]; if(!color) color = 'Gray'; var playerBox = htmlDiv(); playerBox.setAttribute('class', 'mdbPlayer'); playerBox.setAttribute('id', this.name); playerBox.setAttribute('title', this.name + ' ' + coords.asString()); playerBox.setAttribute('style', 'z-index:'+zindex+';opacity:.60; left:' + left + 'px; top:' + top + 'px; height:' + size + 'px; width:' + size + 'px; background-color:' + color); // highligh inactive if ((highlightInactive && isInactive) || (highlightVacation && isOnVacation)) { playerBox.style.border = '2px solid yellow'; } playerBox.addEventListener('mouseover', onmdbPlayerMouseOver, false); parent.appendChild(playerBox); } function onmdbPlayerMouseOver() { updatePreview(players.find(this.getAttribute('id'))); } mdbPlayer.prototype.preview = function(parent) { // Table body var tblBody = htmlTableBody(); // Header row for player info var tblHeader = htmlTableRow(); tblHeader.appendChild(htmlTableHeaderCell('Player')); tblHeader.appendChild(htmlTableHeaderCell('Status')); tblHeader.appendChild(htmlTableHeaderCell('Alliance')); tblHeader.appendChild(htmlTableHeaderCell('Generals')); tblHeader.appendChild(htmlTableHeaderCell('Score')); tblHeader.appendChild(htmlTableHeaderCell('Gold')); tblBody.appendChild(tblHeader); // Player info content var tr = htmlTableRow(); tr.appendChild(htmlTableCell(this.name)); tr.appendChild(htmlTableCell(this.status)); tr.appendChild(htmlTableCell(this.alliance)); tr.appendChild(htmlTableCell(intToString(this.generals))); tr.appendChild(htmlTableCell(intToString(this.score))); tr.appendChild(htmlTableCell(intToString(this.gold))); tblBody.appendChild(tr); // Header row for city information var tblHeader = htmlTableRow(); tblHeader.appendChild(htmlTableHeaderCell('City')); tblHeader.appendChild(htmlTableHeaderCell('TH')); tblHeader.appendChild(htmlTableHeaderCell('Island')); tblHeader.appendChild(htmlTableHeaderCell('Travel')); tblBody.appendChild(tblHeader); // City info content for (var i = 0; i < this.cities.length; i++) { var city = this.cities[i]; var tr = htmlTableRow(); var cityLink = htmlAHref('?view=island&cityId=' + city.id, city.name); cityLink.addEventListener('click', onCityLinkClick, false); tr.appendChild(htmlTableCell(cityLink)); tr.appendChild(htmlTableCell(intToString(city.townHallSize))); tr.appendChild(htmlTableCell(city.island.name + ' ' + city.island.coords.asString())); var travelTime = ikariamTravelTimeAsString(city.island.coords, selectedOwnCity.island.coords, false); tr.appendChild(htmlTableCell(travelTime)); tblBody.appendChild(tr); } parent.appendChild(tblBody); } mdbPlayer.prototype.getPreviewHeading = function() { return this.name + ' ' + this.getCenterOfCities().asString() + ' ' + ikariamTravelTimeAsString(this.getCenterOfCities(), selectedOwnCity.island.coords, false); } // Compare function for player sorting function mdbPlayerCompareByGenerals(a,b) { return (b.generals - a.generals); } // Compare function for city sorting (city name) function mdbCityCompareByName(a,b) { return a.name.localeCompare(b); } // Compare function for city sorting (player name) function mdbCityCompareByPlayerName(a,b) { return a.player.name.localeCompare(b.player.name); } // Compare function for city sorting (player generals) function mdbCityCompareByPlayerGenerals(a,b) { return (b.player.generals - a.player.generals); } /**************************************************** mdbCity ****************************************************/ function mdbCity() { this.id = ''; this.name = ''; this.townHallSize = 0; this.playerId = 0; this.player = null; this.islandId = 0; this.island = null; this.selected = false; this.lastUpdate = 0; this.wallLevel = 0; this.warehouseLevel = 0; this.relationship = ''; this.filterMatch = [true]; } mdbCity.prototype.toJSON = function() { var result = []; result.push(this.id, this.name, this.townHallSize, this.playerId, this.islandId, this.lastUpdate, this.wallLevel, this.warehouseLevel); return result; } mdbCity.prototype.fromJSON = function(json) { this.id = parseInt(json[0]); this.name = json[1]; this.townHallSize = parseInt(json[2]); this.playerId = parseInt(json[3]); this.islandId = parseInt(json[4]); this.lastUpdate = parseInt(json[5]); this.wallLevel = parseInt(json[6]); this.warehouseLevel = parseInt(json[7]); } mdbCity.prototype.filterMatches = function() { for (var i = 0; i < this.filterMatch.length; i++) { if (this.filterMatch[i]) { return true; } } return false; } mdbCity.prototype.clearFilterMatch = function() { this.filterMatch = []; } mdbCity.prototype.setPlayer = function(player) { this.player = player; this.playerId = player.id; } mdbCity.prototype.setIsland = function(island) { this.island = island; this.islandId = island.id; } mdbCity.prototype.toThetaAtiensString = function() { // format is "// TARGET=alliance,player,city,x-coordinate,y-coordinate,enemy" var result = '// TARGET='; result = result + this.player.alliance.name + ','; result = result + this.player.name + ','; result = result + this.name + ','; result = result + this.island.coords.x + ','; result = result + this.island.coords.y + ','; result = result + 'enemy'; return result; } // "Name";TownHallSize;IslandCSVString;PlayerCSVString; mdbCity.prototype.toCSVString = function() { var result = '"' + this.name + '";'; result += this.townHallSize + ';'; result += this.island.toCSVString(); result += this.player.toCSVString(); return result; } /**************************************************** mapDB ****************************************************/ function mapDB() { this.version = mapDBVersion; this.keyRoot = getDomain() + '.' + mapDBKey + '.' + this.version; this.alliances = new sortedList(compareById, 'id'); this.players = new sortedList(compareById, 'id'); this.islands = new sortedList(compareById, 'id'); this.cities = new sortedList(compareById, 'id'); } mapDB.prototype.save = function() { syslog('mapDB.save started', 3); GM_setValue(this.keyRoot + '.alliances', uneval(this.alliances.toJSON())); GM_setValue(this.keyRoot + '.players', uneval(this.players.toJSON())); GM_setValue(this.keyRoot + '.islands', uneval(this.islands.toJSON())); GM_setValue(this.keyRoot + '.cities', uneval(this.cities.toJSON())); syslog('mapDB.save finished', 3); } mapDB.prototype.load = function() { syslog('mapDB.load started', 3); this.alliances.list = []; this.players.list = []; this.islands.list = []; this.cities.list = []; var alliances = eval(GM_getValue(this.keyRoot + '.alliances', '')); if(alliances) { for (i = 0; i < alliances.length; i++ ) { var alliance = new mdbAlliance(); alliance.fromJSON(alliances[i]); this.alliances.list.push(alliance); // } } var players = eval(GM_getValue(this.keyRoot + '.players', '')); if (players) { for (i = 0; i < players.length; i++ ) { var player = new mdbPlayer(); player.fromJSON(players[i]); this.players.list.push(player); player.setAlliance(this.alliances.find(player.allianceId)); player.alliance.players.push(player); } } var islands = eval(GM_getValue(this.keyRoot + '.islands', '')); if (islands) { for (i = 0; i < islands.length; i++ ) { var island = new mdbIsland(); island.fromJSON(islands[i]); this.islands.list.push(island); } } var cities = eval(GM_getValue(this.keyRoot + '.cities', '')); if (cities) { for (i = 0; i < cities.length; i++ ) { var city = new mdbCity(); city.fromJSON(cities[i]); this.cities.list.push(city); city.setPlayer(this.players.find(city.playerId)); city.player.cities.push(city); city.setIsland(this.islands.find(city.islandId)); city.island.cities.push(city); } } syslog('mapDB.load finished', 3); } mapDB.prototype.addAlliance = function(allianceId) { var alliance = new mdbAlliance(); alliance.id = allianceId; this.alliances.add(alliance); return alliance; } mapDB.prototype.addPlayer = function(playerId, alliance) { var player = new mdbPlayer(); player.id = playerId; player.setAlliance(alliance); this.players.add(player); alliance.players.push(player); return player; } mapDB.prototype.addIsland = function(islandId) { var island = new mdbIsland(); island.id = islandId; this.islands.add(island); return island; } mapDB.prototype.addCity = function(cityId, player, island) { var city = new mdbCity(); city.id = cityId; city.setPlayer(player); city.setIsland(island); this.cities.add(city); island.cities.push(city); player.cities.push(city); return city; } // Added 5.7.2015 mapDB.prototype.moveCity = function(city, newIsland) { syslog('moveCity started'); // find the old island and remove city from it var oldIsland = this.islands.find(city.islandId); oldIsland.cities.removeById(city.id); city.setIsland(newIsland); newIsland.cities.push(city); syslog('moveCity finished'); return true; } // Added 7.7.2015 mapDB.prototype.movePlayer = function(player, newAlliance) { syslog('movePayer started'); // find the old alliance and remove player from it var oldAlliance = this.alliances.find(player.allianceId); oldAlliance.players.removeById(player.id); player.setAlliance(newAlliance); newAlliance.players.push(player); syslog('movePlayer finished'); return true; } /**************************************************** xplorer ****************************************************/ function xplorer() { this.db = new mapDB(); xplorerDB = this.db; } xplorer.prototype.init = function() { consoleTime('xplorer.init'); syslog('xplorer.init', 2); // add icon var button = htmlImg(IMAGES.xplorer, 64,64); button.setAttribute('style', 'position: absolute; top: 55px; left: 640px; cursor: pointer'); button.setAttribute('title', 'Ikariam Xplorer'); button.addEventListener('click', xplorerOnClickHandler, false); var header = document.getElementById('GF_toolbar'); header.appendChild(button); syslog('xplorer.init finished', 2); consoleTimeEnd('xplorer.init'); } xplorer.prototype.processViews = function() { consoleTime('xplorer.processViews'); syslog('xplorer.processViews', 2); /* if (ikariamIsAllyListView()) { consoleTime('xplorer.ProcessAllyList'); processAllyList(); consoleTimeEnd('xplorer.ProcessAllyList'); } */ if (ikariamIsIslandView()) { consoleTime('xplorer.processIslandView'); setTimeout(function() {processIslandView();}, 0); consoleTimeEnd('xplorer.processIslandView'); } /* if (ikariamIsMilitaryMovementsView()) { consoleTime('xplorer.processMilitaryMovementsView'); processMilitaryMovementsView(); consoleTimeEnd('xplorer.processMilitaryMovementsView'); } */ if (ikariamIsWorldMapView()) { consoleTime('xplorer.processWorldMapView'); initWorldMapView(); setTimeout(function() {processWorldMapView();}, 0); consoleTimeEnd('xplorer.processWorldMapView'); } syslog('xplorer.processViews finished', 2); consoleTimeEnd('xplorer.processViews'); } function liveFilter() { consoleTime('xplorer.liveFilter'); // check if any filter is applied // #### add all the filter inputs/selects filtersApplied = ((allianceInput.value != '') || (playerInput.value != '') || (cityInput.value != '')); //filter map filterMap() // update legend updateLegend(alliances); // update status var searchStatus = 'Filtering finished at ' + getTimestamp(); updateStatus(alliances, players, islands, cities, searchStatus); consoleTimeEnd('xplorer.liveFilter'); } function filterMap() { for (var i = 0; i < islands.list.length; i++) { islands.list[i].filter(); } } function drawMap() { syslog('drawMap started', 3); // first clear the old elements from the map removeElementsByClassname(windowRef.document, 'mdbIsland', mapContainer); removeElementsByClassname(windowRef.document, 'mdbPlayer', mapContainer); removeElementsByClassname(windowRef.document, 'ownmdbIsland', mapContainer); // then draw all the islands for (var i = 0; i < islands.list.length; i++) { islands.list[i].draw(alliances, mapContainer, null, highlightInactiveCheckbox.checked, highlightVacationCheckbox.checked); } // and finally apply any potential filters filterMap(); /* all this is disabled for now // draw own islands drawOwnIslands(mapContainer); // draw the data to the map var reportType = REPORT_TYPE_INDEX[parseInt(reportSelect.options[reportSelect.selectedIndex].value)]; switch (reportType) { case REPORT_TYPE.rtIslands: case REPORT_TYPE.rtIslandsGenerals: case REPORT_TYPE.rtIslandsScore: case REPORT_TYPE.rtIslandsGold: for (var i = 0; i < islands.list.length; i++) { islands.list[i].draw(alliances, mapContainer, reportType, highlightInactiveCheckbox.checked, highlightVacationCheckbox.checked); } break; // TODO player based views need to be updated case REPORT_TYPE.rtPlayers: case REPORT_TYPE.rtPlayersGenerals: case REPORT_TYPE.rtPlayersScore: case REPORT_TYPE.rtPlayersGold: for (var i = 0; i < players.list.length; i++) { players.list[i].draw(alliances, mapContainer, reportType, highlightInactiveCheckbox.checked, highlightVacationCheckbox.checked); } break; default: syslog('drawMap: Unknown report type ' + reportType); break; } */ syslog('drawMap finished', 3); } // #### do we need this any more? Own islands should be highlighted when drawing normal islands function drawOwnIslands(parent) { /* for (var i = 0; i < ownIslands.length; i++) { var island = ownIslands[i]; var size = (islandScale-1)*mapScale // own islands on the bottom var zindex = 5000; // use the average of city mdbCoordinates as the reporting center var coords = island.coords; var left = mapXOffset + (coords.x*mapScaleRatio*mapScale/10)-Math.round(size/2); var top = mapYOffset + (coords.y*mapScaleRatio*mapScale/10)-Math.round(size/2); if (left < 0) left = 0; if (top < 0) top = 0; var color = 'black'; var ownIslandBox = htmlDiv(); ownIslandBox.setAttribute('class', 'ownmdbIsland'); ownIslandBox.setAttribute('id', island.name); ownIslandBox.setAttribute('title', island.citiesAsString() + ' ' + island.coords.asString()); ownIslandBox.setAttribute('style', 'z-index:'+zindex+';opacity:.60; left:' + left + 'px; top:' + top + 'px; height:' + size + 'px; width:' + size + 'px; background-color:' + color); // highligh selected one if (island.containsSelectedCity()) { ownIslandBox.style.border = '2px solid red'; } parent.appendChild(ownIslandBox); } */ } xplorerOnClickHandler = function() { displayMapWindow(); } function updatePreview(item) { removeAllChildElements(previewContainer); previewContainer.appendChild(xplorerHeading('Preview - ' + item.getPreviewHeading())); item.preview(previewContainer); } function updateLegend(alliances) { removeAllChildElements(legendContainer); var tblBody = htmlTableBody(); var tblHeader = htmlTableRow(); for (var i = 0; i < alliances.list.length; i++) { var th = htmlTableHeaderCell(alliances.list[i].name); th.setAttribute('style', 'opacity:0.8;background:none;background-color:'+ ALLIANCE_COLOR[i] + ';color:' + ALLIANCE_TEXT_COLOR[i]); tblHeader.appendChild(th); } tblBody.appendChild(tblHeader); legendContainer.appendChild(tblBody); } function updateStatus(alliances, players, islands, cities, searchStatus) { removeAllChildElements(statusContainer); var tblBody = htmlTableBody(); var tblHeader = htmlTableRow(); tblHeader.appendChild(htmlTableHeaderCell('Server/world: ' + ikariamGetServer() + '/' + ikariamGetWorld())); tblHeader.appendChild(htmlTableHeaderCell('Alliances: ' + alliances.list.length)); tblHeader.appendChild(htmlTableHeaderCell('Players: ' + players.list.length)); tblHeader.appendChild(htmlTableHeaderCell('Islands: ' + islands.list.length)); tblHeader.appendChild(htmlTableHeaderCell('Cities: ' + cities.list.length)); tblHeader.appendChild(htmlTableHeaderCell('Zoom: ' + mapScale)); tblHeader.appendChild(htmlTableHeaderCell('Status: ' + searchStatus)); tblBody.appendChild(tblHeader); statusContainer.appendChild(tblBody); } function createSearchContainer(parent) { var result = htmlDiv(); result.setAttribute('class', 'searchContainer'); result.setAttribute('style', 'display:none'); parent.appendChild(result); // Filter result.appendChild(xplorerHeading('Filter')); allianceInput = xplorerSearchInputDiv(result, 'Alliance', '90px', '', onAllianceInputKeyUp); playerInput = xplorerSearchInputDiv(result, 'Player', '90px', '', onPlayerInputKeyUp); cityInput = xplorerSearchInputDiv(result, 'City', '90px', '', onCityInputKeyUp); /* playerStatusSelect = xplorerSearchSelectDiv(result, 'Status', PLAYER_STATUS_SELECT_INDEX, onSelectChange); var distanceValues = []; for(i=1; i < 100; i++ ) distanceValues.push(i); distanceSelect = xplorerSearchSelectDiv(result, 'Distance', distanceValues, onSelectChange); luxuryResourceSelect = xplorerSearchSelectDiv(result, 'Luxury', LUXURY_RESOURCE_SELECT_INDEX, onSelectChange); */ // Town hall size drop down (distanceSelect as global var) /* var townHallLevelDiv = xplorerSearchDiv(); townHallLevelDiv.appendChild(xplorerCaption('Townhall size')); townHallLevelLowSelect = xplorerSelect(); townHallLevelLowSelect.appendChild(new Option('Any',0)); for(i=1; i < 41; i++ ) { townHallLevelLowSelect.appendChild(new Option(i,i)); } townHallLevelDiv.appendChild(townHallLevelLowSelect); townHallLevelHighSelect = xplorerSelect(); townHallLevelHighSelect.appendChild(new Option('Any',0)); for(i=1; i < 41; i++ ) { townHallLevelHighSelect.appendChild(new Option(i,i)); } townHallLevelDiv.appendChild(townHallLevelHighSelect); result.appendChild(townHallLevelDiv); // Military score input min-max (input fields are stored in a global variable) var militaryScoreDiv = xplorerSearchDiv(); militaryScoreDiv.appendChild(xplorerCaption('Military score')); militaryScoreLowInput = xplorerInput(); militaryScoreLowInput.style.width = '40px'; militaryScoreDiv.appendChild(militaryScoreLowInput); militaryScoreHighInput = xplorerInput(); militaryScoreHighInput.style.width = '40px'; militaryScoreDiv.appendChild(militaryScoreHighInput); result.appendChild(militaryScoreDiv); */ // #### buttons hidden for now (no use) /* var searchButtonDefs = [{name: 'Search', onClick: onSearchClick}, {name:'Clear map', onClick: onClearMapClick}, {name: 'Export', onClick: onExportClick}]; result.appendChild(xplorerButtonsDiv(searchButtonDefs)); */ // Map settings result.appendChild(xplorerHeading('Map settings')); // Zoom buttons result.appendChild(xplorerLabel('Zoom')); var zoomInButton = xplorerButton('+'); zoomInButton.addEventListener('click', onZoomInClick, false); result.appendChild(zoomInButton); var zoomOutButton = xplorerButton('-'); zoomOutButton.addEventListener('click', onZoomOutClick, false); result.appendChild(zoomOutButton); // #### hidden for now // Report drop down (stored as a global variable) /* reportSelect = xplorerSelect(); for(i=0; i < REPORT_TYPE_INDEX.length; i++ ) { reportSelect.appendChild(new Option(REPORT_TYPE_INDEX[i],i)); } reportSelect.addEventListener('change', onReportSelectChange, false); result.appendChild(reportSelect); result.appendChild(htmlBr()); */ // Highlight inactive/vacation checkboxes result.appendChild(xplorerLabel('Highlight: Inactive')); highlightInactiveCheckbox = xplorerCheckbox(); highlightInactiveCheckbox.checked = false; highlightInactiveCheckbox.addEventListener('change', onHighlightCheckboxChange, false); result.appendChild(highlightInactiveCheckbox); result.appendChild(xplorerLabel('Vacation')); highlightVacationCheckbox = xplorerCheckbox(); highlightVacationCheckbox.checked = false; highlightVacationCheckbox.addEventListener('change', onHighlightCheckboxChange, false); result.appendChild(highlightVacationCheckbox); // Scan result.appendChild(xplorerHeading('Scan')); scanCenterXInput = xplorerSearchInputDiv(result, 'Center-x', '50px', ''); scanCenterYInput = xplorerSearchInputDiv(result, 'Center-y', '50px', ''); scanRangeInput = xplorerSearchInputDiv(result, 'Range', '45px', '5'); scanDelayMinInput = xplorerSearchInputDiv(result, 'Delay-min', '60px', '5000'); scanDelayMaxInput = xplorerSearchInputDiv(result, 'Delay-max', '60px', '8000'); rescanWaitTimeInput = xplorerSearchInputDiv(result, 'Rescan wait (days)', '120px', '7'); var scanButtonDefs = [{name: 'Scan', onClick: onScanClick}, {name:'WorldScan', onClick: onWorldScanClick}]; result.appendChild(xplorerButtonsDiv(scanButtonDefs)); return result; } function onNewClick() { syslog('onNewClick',1); } function onDeleteClick() { syslog('onDeleteClick',1); } // ?view=worldmap_iso&islandX=43&islandY=42 function onWorldScanClick() { if (!windowRef.confirm('This will view/scan world map view at four points. Continue?')) return; // four fixed points which cover the whole world map (8 second delay between) browseToWithDelay('?view=worldmap_iso&islandX=25&islandY=25', 0, ''); browseToWithDelay('?view=worldmap_iso&islandX=75&islandY=25', 8000, ''); browseToWithDelay('?view=worldmap_iso&islandX=25&islandY=75', 16000, ''); browseToWithDelay('?view=worldmap_iso&islandX=75&islandY=75', 24000, ''); } function onScanClick() { var scanCenterX = parseInt(scanCenterXInput.value); var scanCenterY = parseInt(scanCenterYInput.value); var scanRange = parseInt(scanRangeInput.value); var minDelay = parseInt(scanDelayMinInput.value); var maxDelay = parseInt(scanDelayMaxInput.value); var rescanWaitTime = parseInt(rescanWaitTimeInput.value); var baseDelay = 0; var delay = 0; var expIslands = []; // first go through all islands to find the ones which are in range // and have not been scanned for over 7 days for (var i = 0; i < islands.list.length; i++) { var island = islands.list[i]; if (island.coords.isInRange(scanCenterX, scanCenterY, scanRange)) { syslog('Is in range, x=' + island.coords.x + ', y=' + island.coords.y + ', id=' + island.id + ', updated=' + island.daysSinceLastUpdate() + ', citycount=' + island.cityCount); // Must have cities and either over 7 days since last update or island view not visited at all if((island.cityCount > 0) && ((island.daysSinceLastUpdate() > rescanWaitTime) || (island.processLevel != 3))) { expIslands.push(island); } } } // ask confirmation before proceeding var duration = Math.round(((minDelay + maxDelay)/2/1000/60)*expIslands.length); syslog((minDelay + maxDelay)/2); if (!windowRef.confirm('Found ' + expIslands.length + ' islands to be scanned. Scanning will take ' + duration + ' minutes. Continue?')) return; // launch scanning for (var i = 0; i < expIslands.length; i++) { var island = expIslands[i]; var islandLink = htmlAHref('?view=island&islandId=' + island.id, island.name); delay = Math.random() * (maxDelay - minDelay) + minDelay; syslog(islandLink.href + ", delay=" + baseDelay); var status = ''; if (i == expIslands.length - 1) status = 'Scanning finished'; else { status = 'Scanning progress ' + (i+1) + '/' + expIslands.length + ' (' + Math.round((expIslands.length-i)/expIslands.length*duration) + ' minutes left)' } browseToWithDelay(islandLink.href, baseDelay, status); baseDelay = baseDelay + delay; } } function onSearchClick() { /* syslog('Ikariam Xplorer - Search activated',1); updateStatus(alliances, players, islands, cities, 'Search in progress...'); // TODO replace ikaCore with own data var searchParams = new ikaCoreSearchParams(); searchParams.server = ikariamGetServer(); searchParams.world = ikariamGetWorld(); searchParams.alliance = allianceInput.value; searchParams.player = playerInput.value; searchParams.city = cityInput.value; if(playerStatusSelect.selectedIndex > 0) { searchParams.status = playerStatusSelect.selectedIndex - 1; } searchParams.distance = distanceSelect.selectedIndex; searchParams.luxuryResource = luxuryResourceSelect.selectedIndex; if(townHallLevelLowSelect.selectedIndex > 0) searchParams.townHallLevelLow = townHallLevelLowSelect.selectedIndex; if(townHallLevelHighSelect.selectedIndex > 0) searchParams.townHallLevelHigh = townHallLevelHighSelect.selectedIndex; var milLow = parseInt(militaryScoreLowInput.value); if(!isNaN(milLow)) searchParams.militaryScoreLow = milLow; var milHigh = parseInt(militaryScoreHighInput.value); if(!isNaN(milHigh)) searchParams.militaryScoreHigh = milHigh; searchIkaCore(searchParams, SearchResultHandler); syslog('Ikariam Xplorer - Search finished',1); */ } function onClearMapClick() { syslog('Ikariam War Room - Clear Map activated',1); /* cities = []; players = []; alliances = []; islands = []; drawMap(); updateLegend(alliances); updateStatus(alliances, players, islands, cities, 'Map cleared'); // TODO replace with filter clear */ syslog('Ikariam War Room - Clear Map finished',1); } function onExportClick() { syslog('Ikariam War Room - Export activated',1); explore(); //displayExportWindow(cities, alliances, players); updateStatus(alliances, players, islands, cities, 'Export finished'); syslog('Ikariam War Room - Export finished',1); } function onZoomInClick() { syslog('onZoomInClick'); mapScale += 1; onZoomChange(); } function onZoomOutClick() { syslog('onZoomOutClick'); mapScale -= 1; if(mapScale < 1) mapScale = 1; onZoomChange(); } function onZoomChange() { // calculate the current center position as factor var xFactor = (mapContainer.scrollLeft + mapContainer.clientWidth/2) / mapContainer.scrollWidth; var yFactor = (mapContainer.scrollTop + mapContainer.clientHeight/2) / mapContainer.scrollHeight; drawGrid(); drawMap(); // re-position the scrollbars to get a real zoom effect mapContainer.scrollLeft = xFactor * mapContainer.scrollWidth - mapContainer.clientWidth/2; mapContainer.scrollTop = yFactor * mapContainer.scrollHeight - mapContainer.clientHeight/2; } function onReportSelectChange() { drawMap(); } function onHighlightCheckboxChange() { drawMap(); } function createLegendContainer(parent) { var result = htmlDiv(); result.setAttribute('class', 'legendContainer'); result.setAttribute('style', 'display:none;overflow:auto'); parent.appendChild(result); return result; } function createStatusContainer(parent) { var result = htmlDiv(); result.setAttribute('class', 'statusContainer'); result.setAttribute('style', 'display:none;overflow:auto'); parent.appendChild(result); return result; } function createPreviewContainer(parent) { var result = htmlDiv(); result.setAttribute('class', 'previewContainer'); result.setAttribute('style', 'display:none;overflow:auto'); parent.appendChild(result); result.appendChild(xplorerHeading('Preview')); return result; } function createMapContainer(parent) { var result = htmlDiv(); result.setAttribute('class', 'mapContainer'); result.setAttribute('style', 'display:none;overflow:auto'); result.addEventListener('dragstart', onMapContainerDragStart, false); parent.appendChild(result); // Heading var heading = xplorerHeading('Ikariam Xplorer ' + version); // Update button updateButton = xplorerButton('Update'); updateButton.setAttribute('class', 'xplorer_Update_button'); updateButton.style.display = 'none'; updateButton.addEventListener('click', onUpdateClick, false); heading.appendChild(updateButton); result.appendChild(heading); // Canvas mapCanvas = document.createElement('canvas'); //canvas.setAttribute('width', 1000); //canvas.setAttribute('height', 1000); //canvas.setAttribute('z-index', 10000); result.appendChild(mapCanvas); return result; } function onUpdateClick(e) { syslog('War Room - version update activated', 1); // hides the update button next time the War Room is opened GM_deleteValue('xplorer.newVersion'); // update check will be performed next time the War Room is opened // (in case user cancels the installation) GM_deleteValue('xplorer.lastUpdateCheck'); location.href = scriptURL; } function onGridSurroundMouseDown(e) { if(!e) return; var currentX = mapContainer.scrollLeft + e.clientX; var currentY = mapContainer.scrollTop + e.clientY; dragPrevX = currentX; dragPrevY = currentY; return false; } function onGridSurroundMouseUp(e) { if(!e) return; var currentX = mapContainer.scrollLeft + e.clientX; var currentY = mapContainer.scrollTop + e.clientY; mapContainer.scrollLeft = mapContainer.scrollLeft + (dragPrevX-currentX); mapContainer.scrollTop = mapContainer.scrollTop + (dragPrevY-currentY); return false; } // Zoom with mousewheel (center on mouse cursor location) function onGridSurroundMouseScroll(e) { var delta = 0; if (e.detail) { delta = -e.detail/3; } // delta is positive on scroll up and vice versa if (delta > 0) mapScale += 1; else if (delta < 0) mapScale -= 1; if(mapScale < 1) mapScale = 1; // zoom on mouse cursor location (make it the new center) var xFactor = (mapContainer.scrollLeft + e.clientX) / mapContainer.scrollWidth; var yFactor = (mapContainer.scrollTop + e.clientY) / mapContainer.scrollHeight; drawGrid(); drawMap(); // re-position the scrollbars to get a real zoom effect mapContainer.scrollLeft = xFactor * mapContainer.scrollWidth - mapContainer.clientWidth/2; mapContainer.scrollTop = yFactor * mapContainer.scrollHeight - mapContainer.clientHeight/2; e.preventDefault(); return false; } function onMapContainerDragStart(e) { e.preventDefault(); return false; } function drawGrid () { // first remove previous grid elements removeElementsByClassname(windowRef.document, 'gridElem', mapContainer); removeElementsByClassname(windowRef.document, 'gridSurroundingBox', mapContainer); removeElementsByClassname(windowRef.document, 'hTick', mapContainer); removeElementsByClassname(windowRef.document, 'vTick', mapContainer); // vertical grid lines for (var i = 0; i < 5; i++) { var gridVert = htmlDiv(); var top = mapYOffset; var left = mapXOffset + (i*mapScale*mapScaleRatio)*2; var width = mapScale*mapScaleRatio-1; var height = mapScale*mapScaleRatio*10-1; gridVert.setAttribute('class', 'gridElem'); gridVert.setAttribute('style', 'z-index:5;width:'+width+'px; height:'+height+'px; top:'+top+'px; left:'+left+'px'); //gridVert.addEventListener('selectstart', onMapContainerSelectStart, false); mapContainer.appendChild(gridVert); } // horizontal grid lines for (var i = 0; i < 5; i++) { var gridHoriz = htmlDiv(); var top = mapYOffset + (i*mapScale*mapScaleRatio)*2; var left = mapXOffset; var width = mapScale*mapScaleRatio*10-1; var height = mapScale*mapScaleRatio-1; gridHoriz.setAttribute('class', 'gridElem'); gridHoriz.setAttribute('style', 'z-index:5;width:'+width+'px; height:'+height+'px; top:'+top+'px; left:'+left+'px'); //gridHoriz.addEventListener('selectstart', onMapContainerSelectStart, false); mapContainer.appendChild(gridHoriz); } // Surrounding box var gridSurr = htmlDiv(); var top = mapYOffset; var left = mapXOffset; var width = mapScale*mapScaleRatio*10-2; var height = mapScale*mapScaleRatio*10-2; gridSurr.setAttribute('class', 'gridSurroundingBox'); gridSurr.setAttribute('style', 'cursor:all-scroll;z-index:10;width:'+width+'px; height:'+height+'px; top:'+top+'px; left:'+left+'px'); gridSurr.addEventListener('mousedown', onGridSurroundMouseDown, false); gridSurr.addEventListener('mouseup', onGridSurroundMouseUp, false); gridSurr.addEventListener('DOMMouseScroll', onGridSurroundMouseScroll, false); mapContainer.appendChild(gridSurr); // h-ticks for (var i = 1; i < 11; i++) { var hTick = htmlDiv(); var height = 15; var top = mapYOffset-height-3; var left = mapXOffset + i*mapScale*mapScaleRatio-(mapScale*mapScaleRatio/2); var width = mapScale*mapScaleRatio-1; hTick.setAttribute('class', 'hTick'); hTick.textContent = i*10; hTick.setAttribute('style', 'z-index:5;width:'+width+'px; height:'+height+'px; top:'+top+'px; left:'+left+'px'); //hTick.addEventListener('selectstart', onMapContainerSelectStart, false); mapContainer.appendChild(hTick); } // v-ticks for (var i = 1; i < 11; i++) { var vTick = htmlDiv(); var height = 15; var top = mapYOffset + i*mapScale*mapScaleRatio-height/2; var left = mapXOffset + mapScale*mapScaleRatio*10+5; var width = 15; vTick.setAttribute('class', 'vTick'); vTick.textContent = i*10; vTick.setAttribute('style', 'z-index:5;width:'+width+'px; height:'+height+'px; top:'+top+'px; left:'+left+'px'); //vTick.addEventListener('selectstart', onMapContainerSelectStart, false); mapContainer.appendChild(vTick); } } function createIkaCoreAddContainer(parent) { var ikaCoreAddFrame = windowRef.document.createElement('iframe'); ikaCoreAddFrame.setAttribute('id', 'ikaCoreAddContainer'); ikaCoreAddFrame.setAttribute('scrolling', 'NO'); //ikaCoreAddFrame.setAttribute('src', 'http://www.ika-core.org/ikariam.html?u=25'); ikaCoreAddFrame.setAttribute('disabled', 'true'); parent.appendChild(ikaCoreAddFrame); return ikaCoreAddFrame; } function refreshSizesAndPositions() { syslog('refreshSizesAndPositions started', 3); // calculate new map scale ratio xRatio = defaultMapScaleRatio * windowRef.outerWidth/defaultWindowWidth; yRatio = defaultMapScaleRatio * windowRef.outerHeight/defaultWindowHeight; mapScaleRatio = Math.min(xRatio, yRatio); // reposition and resize mapContainer mapContainer.style.top = 10 + 'px'; mapContainer.style.left = 10 + 'px'; mapContainer.style.width = mapScaleRatio*10 + mapXOffset*3 + 'px'; mapContainer.style.height = mapContainer.style.width; mapContainer.style.display = 'block'; // resize map canvas mapCanvas.style.position = 'absolute'; mapCanvas.style.top = mapYOffset +'px'; mapCanvas.style.left = mapXOffset + 'px'; mapCanvas.width = mapScale*mapScaleRatio*10; mapCanvas.height = mapScale*mapScaleRatio*10; // #### testing var ctx = mapCanvas.getContext("2d"); ctx.beginPath(); ctx.moveTo(0, 0); ctx.lineTo(mapCanvas.width, 0); ctx.lineTo(mapCanvas.width, mapCanvas.height); ctx.lineTo(0, mapCanvas.height); ctx.lineTo(0, 0); ctx.stroke(); // reposition and resize previewContainer previewContainer.style.top = mapContainer.offsetTop + 'px'; previewContainer.style.height = mapContainer.offsetHeight*0.5 + 'px'; previewContainer.style.left = mapContainer.offsetLeft + mapContainer.offsetWidth + 5 + 'px'; previewContainer.style.width = windowRef.outerWidth - mapContainer.offsetLeft - mapContainer.offsetWidth - 35 + 'px'; previewContainer.style.display = 'block'; // reposition and resize searchContainer searchContainer.style.top = previewContainer.offsetTop + previewContainer.offsetHeight + 0 + 'px'; searchContainer.style.height = mapContainer.offsetHeight*0.5 - 7 + 'px'; searchContainer.style.left = previewContainer.offsetLeft + 'px'; searchContainer.style.width = previewContainer.style.width; searchContainer.style.display = 'block'; // reposition and resize legendContainer legendContainer.style.top = mapContainer.offsetTop + mapContainer.offsetHeight + 0 + 'px'; //legendContainer.style.height = '20px'; legendContainer.style.left = mapContainer.offsetLeft + 'px'; legendContainer.style.width = mapContainer.offsetWidth + searchContainer.offsetWidth + 2 + 'px'; legendContainer.style.display = 'block'; // reposition and resize statusContainer statusContainer.style.top = legendContainer.offsetTop + legendContainer.offsetHeight + 0 + 'px'; //statusContainer.style.height = '20px'; statusContainer.style.left = mapContainer.offsetLeft + 'px'; statusContainer.style.width = legendContainer.style.width; statusContainer.style.display = 'block'; // reposition (and resize) ikaCoreAddContainer //ikaCoreAddContainer.style.top = statusContainer.offsetTop + statusContainer.offsetHeight + 5 + 'px'; //ikaCoreAddContainer.style.display = 'block'; // re-draw grid and map items drawGrid(); drawMap(); syslog('refreshSizesAndPositions finished', 3); } function onWindowResize() { if(windowResizeTimeOut != null) clearTimeout(windowResizeTimeOut); windowResizeTimeOut = setTimeout(refreshSizesAndPositions, 300); } function onWindowKeypress(e) { switch (e.keyCode) { case 13: onSearchClick(); break; default: return; } } function onAllianceInputKeyUp(e) { consoleTime('xplorer.onAllianceInputKeyUp'); if (allianceInput.value != allianceInput.lastValue) { alliances.filterString(allianceInput.value, 'name', 'filterMatch', filterIndex, false, true); allianceInput.lastValue = allianceInput.value; liveFilter(); } consoleTimeEnd('xplorer.onAllianceInputKeyUp'); } function onPlayerInputKeyUp(e) { consoleTime('xplorer.onPlayerInputKeyUp'); if (playerInput.value != playerInput.lastValue) { players.filterString(playerInput.value, 'name', 'filterMatch', filterIndex, false, true); playerInput.lastValue = playerInput.value; liveFilter(); } consoleTimeEnd('xplorer.onPlayerInputKeyUp'); } function onCityInputKeyUp(e) { consoleTime('xplorer.onCityInputKeyUp'); if (cityInput.value != cityInput.lastValue) { cities.filterString(cityInput.value, 'name', 'filterMatch', filterIndex, false, true); cityInput.lastValue = cityInput.value; liveFilter(); } consoleTimeEnd('xplorer.onCityInputKeyUp'); } function onSelectChange(e) { // #### TODO this must be broken to several event handlers for each item to be performance optimised // also now supports only player status which seems to be broken too var playerStatus = PLAYER_STATUS_SELECT_INDEX[playerStatusSelect.selectedIndex] // case-sensitive since otherwise Active would match also Inactive if (playerStatus == 'Any') playerStatus = ''; players.filterString(playerStatus, 'status', 'filterMatch', filterIndex, false, false); liveFilter(); } function checkVersion() { // get the stored last update check time var lastUpdateCheck = GM_getValue('xplorer.lastUpdateCheck', 0); var now = parseInt(new Date().getTime()); // calculate time elapsed since last update check var performCheck = ((now - parseInt(lastUpdateCheck)) > updateCheckInterval); // perform update check if necessary if (performCheck) { syslog('War Room performing update check', 1); // get the script source try { GM_xmlhttpRequest({ method: "GET", url: scriptMetaURL, onload: function(xhr) { checkVersionResponseHandler(xhr.responseText); } }); GM_setValue('xplorer.lastUpdateCheck', '' + now); } catch(err) { syslog('checkVersion, GM_xmlhttpRequest failed: ' + err.description, 1); } } else { // also check if an update was found earlier on var newVersion = GM_getValue('xplorer.newVersion', ''); if(newVersion != '') { updateButton.value = 'Update to ' + newVersion; updateButton.style.display = 'inline-block'; } } } function checkVersionResponseHandler(responseText) { var lines = responseText.split('\n'); var latestVersion = null; for(i=0; i < lines.length; i++ ) { if(lines[i].indexOf(versionTag) != -1) { // extract the version info from line (excluding any whitespace) latestVersion = lines[i].substr(versionTag.length).replace(/^\s*|\s*$/g,''); } } if(!latestVersion) { syslog('War Room - version information not found in the latest script source', 1); return; } if (version != latestVersion) { syslog('War Room, new version available (current: ' + version + ' new: ' + latestVersion + ')', 1); updateButton.value = 'Update to ' + latestVersion; updateButton.style.display = 'inline-block'; GM_setValue('xplorer.newVersion', latestVersion); } } function browseToWithDelay(href, delay, status) { windowRef.setTimeout(function() { syslog('href=' + href + ', delay=' + delay); window.location = href; updateStatus(alliances, players, islands, cities, status); }, delay); } function displayExportWindow (cities, alliances, players) { // TODO modify to expect a sortedList instead of an array of items var windowName = 'War Room Export'; var windowWidth = 900; var windowHeight = 800; var windowOptions = 'width='+windowWidth+',height='+windowHeight+',status=no,toolbar=0,copyhistory=no,'; windowOptions += 'location=no,scrollbars=yes,menubar=no,directories=no'; var windowRef = window.open('', windowName, windowOptions); windowRef.document.write('<html><head><title>Ikariam War Room Export (by bt_viper)</title>'); windowRef.document.write(xplorerCSS()); windowRef.document.write('</head><body></body></html>'); windowRef.document.close(); // Theta Atiens text area var thetaCaption = windowRef.document.createElement('h3'); thetaCaption.textContent = "Theta Atien's Alliance Map - Embassy Input format"; var thetaTextArea = windowRef.document.createElement('textarea'); thetaTextArea.setAttribute('rows','10'); thetaTextArea.setAttribute('cols','100'); var thetaText = ''; for (var i = 0; i < cities.length; i++) { thetaText += cities[i].toThetaAtiensString(); if(i < cities.length-1) thetaText += '\n'; } thetaTextArea.textContent = thetaText; // Players in CSV format var playersCaption = windowRef.document.createElement('h3'); playersCaption.textContent = "Player data in CSV format (ready for Excel import)"; var playersTextArea = windowRef.document.createElement('textarea'); playersTextArea.setAttribute('rows','10'); playersTextArea.setAttribute('cols','100'); var playersText = '"Player name";"Alliance";"Status";"Score";"Generals";"Gold";\n'; for (var i = 0; i < players.length; i++) { playersText += players[i].toCSVString(); if(i < players.length-1) playersText += '\n'; } playersTextArea.textContent = playersText; // Cities in CSV format var citiesCaption = windowRef.document.createElement('h3'); citiesCaption.textContent = "City data in CSV format (ready for Excel import)"; var citiesTextArea = windowRef.document.createElement('textarea'); citiesTextArea.setAttribute('rows','10'); citiesTextArea.setAttribute('cols','100'); var citiesText = '"City";"TownHallSize";"Island";"X-coordinate";"Y-coordinate";"Luxury";"Player";"Alliance";"Status";"Score";"Generals";"Gold";\n'; for (var i = 0; i < cities.length; i++) { citiesText += cities[i].toCSVString(); if(i < cities.length-1) { citiesText += '\n'; } } citiesTextArea.textContent = citiesText; var body = windowRef.document.body; body.appendChild(thetaCaption); body.appendChild(thetaTextArea); body.appendChild(playersCaption); body.appendChild(playersTextArea); body.appendChild(citiesCaption); body.appendChild(citiesTextArea); windowRef.document.close(); } // this is run is page script context function fireNewMapWindow () { var windowName = 'xplorer'; var newWindow = window.open ('about:blank', '_blank', "height=800,width=1250"); newWindow.addEventListener ( "load", function () { onDisplayMapWindow (newWindow) }, false ); } function addJS_Node (text, s_URL, funcToRun, runOnLoad) { var D = document; var scriptNode = D.createElement ('script'); if (runOnLoad) { scriptNode.addEventListener ("load", runOnLoad, false); } scriptNode.type = "text/javascript"; if (text) scriptNode.textContent = text; if (s_URL) scriptNode.src = s_URL; if (funcToRun) scriptNode.textContent = '(' + funcToRun.toString() + ')()'; var targ = D.getElementsByTagName ('head')[0] || D.body || D.documentElement; targ.appendChild (scriptNode); } function displayMapWindow() { // first export onDisplayMapWindow function to the page script domain exportFunction(onDisplayMapWindow, unsafeWindow, {defineAs: "onDisplayMapWindow"}); // then trigger the new window creation addJS_Node (null, null, fireNewMapWindow); } function onDisplayMapWindow (newWindow) { syslog('displayMapWindow started', 3); consoleTime('xplorer.displayMapWindow'); windowRef = newWindow; doc = windowRef.document; doc.write('<html><head><title>Ikariam Xplorer</title>'); doc.write(xplorerCSS()); doc.write('</head><body></body></html>'); doc.close(); // create the containers searchContainer = createSearchContainer(windowRef.document.body); previewContainer = createPreviewContainer(windowRef.document.body); mapContainer = createMapContainer(windowRef.document.body); legendContainer = createLegendContainer(windowRef.document.body); statusContainer = createStatusContainer(windowRef.document.body); // add a listener for browser window resize windowRef.addEventListener('resize', onWindowResize, false); // add a listener for key presses windowRef.addEventListener('keypress', onWindowKeypress, false); // load the data xplorerDB.load(); alliances = xplorerDB.alliances; players = xplorerDB.players; islands = xplorerDB.islands; cities = xplorerDB.cities; // get own cities and update city relationships var ownCities = ikariamGetOwnCities(); for (var i = 0; i < ownCities.length; i++) { var ownCity = ownCities[i]; var city = getArrayItemByID(cities.list, ownCity.id); if(city) { city.relationship = ownCity.relationship; if(ownCity.selected) { city.selected = true; selectedOwnCity = city; } } } // set the correct sizes and positions to the elements refreshSizesAndPositions(); // update legend updateLegend(alliances); // update status updateStatus(alliances, players, islands, cities, ''); // perform version update check // checkVersion(); consoleTimeEnd('xplorer.displayMapWindow'); syslog('displayMapWindow finished', 3); } function xplorerCSS() { var result = ' \ <style type="text/css"> \ table { border-collapse: collapse; } \ \ .xplorer_searchDiv { \ float: left; \ margin: 1px; \ //clear: right; \ } \ \ .xplorer_heading { \ color: #d9eef7; \ background: -moz-linear-gradient(top, #00adee, #0078a5); \ outline: none; \ text-align: center; \ text-decoration: none; \ text-shadow: 0 1px 1px rgba(0,0,0,.3); \ font: 16px/100% Arial, Helvetica, sans-serif; \ font-weight:bold; \ height: 20px; \ padding: .3em .5em .3em; \ margin: 0px; \ -moz-border-radius: 7px 7px 0 0; \ } \ \ .xplorer_caption, .xplorer_label { \ color: black; \ background-color: white; \ text-align: left; \ text-shadow: 0 1px 1px rgba(0,0,0,.3); \ font: 14px/100% Arial, Helvetica, sans-serif; \ padding: 3px; \ margin: 0px; \ } \ \ .xplorer_button { \ color: #e9e9e9; \ border: solid 1px #555; \ background: -moz-linear-gradient(top, #888, #575757); \ display: inline-block; \ outline: none; \ cursor: pointer; \ text-align: center; \ text-decoration: none; \ font: 14px/100% Arial, Helvetica, sans-serif; \ font-weight:bold; \ padding: .3em 1em .3em; \ margin: 5px; \ text-shadow: 0 1px 1px rgba(0,0,0,.3); \ -moz-border-radius: .5em; \ -moz-box-shadow: 0 2px 4px rgba(0,0,0,.4); \ } \ .xplorer_button:hover { \ text-decoration: none; \ background: -moz-linear-gradient(top, #757575, #4b4b4b);\ } \ .xplorer_button:active { \ color: #afafaf; \ background: -moz-linear-gradient(top, #575757, #888); \ position: relative; \ top: 1px; \ } \ \ .xplorer_Update_button { \ color: #e8f0de; \ border: solid 1px #538312; \ background: -moz-linear-gradient(top, #7db72f, #4e7d0e); \ display: inline-block; \ outline: none; \ cursor: pointer; \ vertical-align: middle; \ text-align: center; \ text-decoration: none; \ font: 12px/100% Arial, Helvetica, sans-serif; \ font-weight:bold; \ //padding: .3em 1em .3em; \ margin: 0px 0px 0px 20px; \ text-shadow: 0 1px 1px rgba(0,0,0,.3); \ -moz-border-radius: .5em; \ -moz-box-shadow: 0 2px 4px rgba(0,0,0,.4); \ } \ .xplorer_Update_button:hover { \ text-decoration: none; \ background: -moz-linear-gradient(top, #6b9d28, #436b0c); \ } \ .xplorer_Update_button:active { \ color: #a9c08c; \ background: -moz-linear-gradient(top, #4e7d0e, #7db72f); \ position: relative; \ top: 1px; \ } \ \ .xplorer_input { \ background-color: white; \ color: black; \ padding: 2px; \ margin: 3px; \ font: 12px/100% Arial, Helvetica, sans-serif; \ //font: 12px/100% Cambria, Arial; \ font-weight:normal; \ text-shadow: 0 1px 1px rgba(0,0,0,.3); \ -moz-border-radius: 2px; \ -moz-box-shadow: 0 1px 2px rgba(0,0,0,.4); \ } \ \ .xplorer_select, .xplorer_checkbox { \ background-color: white; \ color: black; \ padding: 3px; \ margin: 5px; \ font: 12px/100% Arial, Helvetica, sans-serif; \ font-weight:normal; \ text-shadow: 0 1px 1px rgba(0,0,0,.3); \ -moz-border-radius: 4px; \ -moz-box-shadow: 0 2px 4px rgba(0,0,0,.4); \ } \ \ .xplorer_th { \ color: #e9e9e9; \ //background-color: lightgrey; \ background: -moz-linear-gradient(top, #888, #575757); \ //color: black; \ height: 15px; \ padding: 2px; \ margin: 1px; \ font: 12px/100% Arial, Helvetica, sans-serif; \ font-weight:normal; \ text-shadow: 0 1px 1px rgba(0,0,0,.3); \ } \ .xplorer_td { \ background-color: white; \ color: black; \ padding: 3px; \ margin: 1px; \ font: 12px/100% Arial, Helvetica, sans-serif; \ font-weight:normal; \ text-shadow: 0 1px 1px rgba(0,0,0,.3); \ } \ \ .mdbPlayer { \ position: absolute; \ width: 5px; \ height: 5px; \ border: 1px solid black; \ } \ .mdbIsland, .ownmdbIsland { \ position: absolute; \ border: 1px solid LightGray; \ } \ .searchContainer, .previewContainer { \ position: absolute; \ padding: 0px; \ margin: 0px; \ border: 2px solid grey; \ -moz-border-radius: 6px; \ -moz-box-shadow: 0 2px 4px rgba(0,0,0,.4); \ } \ .statusContainer, .legendContainer { \ color: #e9e9e9; \ border: solid 1px #555; \ background: -moz-linear-gradient(top, #888, #575757); \ //background-color: lightgrey; \ font: 10px/100% Arial, Helvetica, sans-serif; \ font-weight:normal; \ text-shadow: 0 1px 1px rgba(0,0,0,.3); \ position: absolute; \ height: 15px; \ padding: 0px; \ margin: 0px; \ border: 1px solid grey; \ -moz-border-radius: 4px; \ -moz-box-shadow: 0 2px 4px rgba(0,0,0,.4); \ } \ \ .mapContainer { \ position: absolute; \ padding: 0px; \ margin: 0px; \ border: 3px solid grey; \ -moz-border-radius: 10px; \ -moz-box-shadow: 0 2px 4px rgba(0,0,0,.4); \ } \ \ .gridSurroundingBox { \ position: absolute; \ padding: 0px; \ margin: 0px; \ border: 2px solid grey; \ } \ \ .gridElem { \ position: absolute; \ padding:0px; \ margin:0px; \ border: 1px dashed gray; \ } \ \ .hTick { \ position: absolute; \ padding:0px; \ margin:0px; \ font-size: 15px; \ font-weight:bold; \ text-shadow: 0 1px 1px rgba(0,0,0,.3); \ text-align: center; \ border: none; \ } \ .vTick { \ position: absolute; \ padding:0px; \ margin:0px; \ font-size: 15px; \ font-weight:bold; \ text-shadow: 0 1px 1px rgba(0,0,0,.3); \ text-align: left; \ border: none; \ } \ </style> \ '; return result; } function processIslandView() { syslog('processIslandView started', 1); // load the existing content to the database xplorerDB.load(); // get a reference to an existing island or create a new one var islandId = ikariamIslandViewGetIslandId(); var island = xplorerDB.islands.find(islandId); if (!island) island = xplorerDB.addIsland(islandId); ikariamIslandViewGetIslandInfo(island); // get a reference to avatar(=player) scores var avatarScores = unsafeWindow.ikariam.backgroundView.screen.data.avatarScores; // get a list of city infos var cityInfs = ikariamIslandViewGetCityInfos(); island.cityCount = 0; for (i = 0; i < cityInfs.length; i++ ) { var cityInfo = cityInfs[i]; // city id (skip empty building places) var cityId = ikariamIslandViewGetCityId(cityInfo); if (cityId == -1) continue; island.cityCount = island.cityCount + 1; // get a reference to an existing alliance or create a new one var allianceId = ikariamIslandViewGetAllianceId(cityInfo); var alliance = xplorerDB.alliances.find(allianceId); if (!alliance) alliance = xplorerDB.addAlliance(allianceId); ikariamIslandViewGetAllianceInfo(cityInfo, alliance); // get a reference to an existing player or create a new one var playerId = ikariamIslandViewGetPlayerId(cityInfo); var player = xplorerDB.players.find(playerId); if (!player) player = xplorerDB.addPlayer(playerId, alliance); ikariamIslandViewGetPlayerInfo(cityInfo, avatarScores, player); // Added 7.7.2015 if(player.allianceId != alliance.id) xplorerDB.movePlayer(player, alliance); // get a reference to an existing city or create a new one var city = xplorerDB.cities.find(cityId); if (!city) city = xplorerDB.addCity(cityId, player, island); ikariamIslandViewGetCityInfo(cityInfo, city); // Added 5.7.2015 // check if city has been moved from an island to another if(city.islandId != island.id) xplorerDB.moveCity(city, island); } // store permanently to GM cache xplorerDB.save(); syslog('processIslandView finished', 1); } function processAllyList() { syslog('Process Ally list started', 1); // load the existing content to the database this.db.load(); // get a reference to an existing alliance or create a new one var allianceId = ikariamAllyListViewGetAllianceId(); var alliance = this.db.alliances.find(allianceId); if (!alliance) alliance = this.db.addAlliance(allianceId); ikariamAllyListViewGetAllianceInfo(alliance); // get the member entries (=players) var playerInfos = ikariamAllyListViewGetPlayerInfos(); for (i = 0; i < playerInfos.length; i++ ) { var playerInfo = playerInfos[i]; // get a reference to an existing player or create a new one var playerId = ikariamAllyListViewGetPlayerId(playerInfo); var player = this.db.players.find(playerId); if (!player) player = this.db.addPlayer(playerId, alliance); ikariamAllyListViewGetPlayerInfo(playerInfo, player); // player's city information var cityInfos = ikariamAllyListViewGetCityInfos(playerInfo); for(j=0; j < cityInfos.length; j++ ) { var cityInfo = cityInfos[j]; // get a reference to an existing island or create a new one var islandId = ikariamAllyListViewGetIslandId(cityInfo); var island = this.db.islands.find(islandId); if (!island) island = this.db.addIsland(islandId); ikariamAllyListViewGetIslandInfo(cityInfo, island); // get a reference to an existing city or create a new one var cityId = ikariamAllyListViewGetCityId(cityInfo); var city = this.db.cities.find(cityId); if (!city) city = this.db.addCity(cityId, player, island); ikariamAllyListViewGetCityInfo(cityInfo, city); } } // store permanently to GM cache this.db.save(); syslog('Process Ally list finished', 1); } function processMilitaryMovementsView() { // get the military movements var movementInfos = ikariamMilitaryMovementsViewGetMovementInfos(); for (i = 1; i < movementInfos.length; i++ ) { // first item heading row var movementInfo = movementInfos[i]; // #### consoleDir(movementInfo); // get a reference to an existing movement or create a new one var movementId = ikariamMilitaryMovementsViewGetMovementId(movementInfo); // #### syslog(movementId,1); } } function worldMapViewOnLoad(JSONResponse) { worldMapViewOriginalHandleMapData(JSONResponse); // GM prevents from directly calling GM_* function from unsafeWindow callbacks setTimeout(function() {processWorldMapView();}, 0); } function initWorldMapView() { syslog('InitWorldMapView started', 1); // hook into world map view's map data handler worldMapViewOriginalHandleMapData = unsafeWindow.worldmap.handleMapData; unsafeWindow.worldmap.handleMapData = worldMapViewOnLoad; syslog('InitWorldMapView finished', 1); } function processWorldMapView() { syslog('processWorldMapView started', 1); xplorerDB.load(); var islands = unsafeWindow.ikariam.backgroundView.screen.islands; var islandCount = 0; // #### DEBUG syslog('islands.length=' + islands.length); var minX=100; var minY=100; var maxX=0; var maxY=0; for (i = 1; i < islands.length; i++ ) { if(!islands[i]) continue; for (j = 1; j < islands[i].length; j++ ) { if((!islands[i][j]) || (!islands[i][j][0]) || (islands[i][j] == 'ocean')) continue; var islandId = parseInt(islands[i][j][0]); var island = xplorerDB.islands.find(islandId); if (!island) island = xplorerDB.addIsland(islandId); ikariamWorldMapViewGetIslandInfo(islands[i][j], island); island.coords.x = i; island.coords.y = j; islandCount++; // #### DEBUG if(i<minX) minX=i; if(i>maxX) maxX=i; if(j<minY) minY=j; if(j>maxY) maxY=j; } } xplorerDB.save(); syslog('coords=[' + minX + ':' + minY + '] -> [' + + maxX + ':' + maxY + ']'); syslog('processWorldMapView finished (' + islandCount + ')', 1); /* wonderText = new Array(); wonderText[1] = 'Hephaistoksen paja'; wonderText[2] = 'Hadesin pyhä lehto'; wonderText[3] = 'Demeterin puutarhat'; wonderText[4] = 'Athenen temppeli'; wonderText[5] = 'Hermeksen temppeli'; wonderText[6] = 'Aresin linnake'; wonderText[7] = 'Poseidonin temppeli'; wonderText[8] = 'Kolossus'; */ } /**************************************************** Script initialisation ****************************************************/ // only init if GF_toolbar is present if (document.getElementById('GF_toolbar')) { var xp = new xplorer(); xp.init(); xp.processViews(); }