// ==UserScript==
// @name Empire Overview
// @author germano
// @description Script for Ikariam V 0.5.x, Overview tables for Ress, buildings and mititary, desktop versions in the style of Ikariam Empire Board
// @namespace Test
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_addStyle
// @grant GM_registerMenuCommand
// @grant GM_deleteValue
// @grant GM_xmlhttpRequest
// @grant GM_openInTab
// @include http://s*.ikariam.gameforge.*/index.php*
// @exclude http://board.*.ikariam.gameforge.com*
// @exclude http://*.ikariam.gameforge.*/board
//
// @require http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js
// @require http://ajax.googleapis.com/ajax/libs/jqueryui/1.9.1/jquery-ui.min.js
//
// @version 1.1661
//
// ==/UserScript==
/***********************************************************************************************************************
* Includes
********************************************************************************************************************* */
;(function($){
var jQuery = $;
if(window.navigator.vendor.match(/Google/)) {
var isChrome = true;
}
if(!isChrome) {
this.$ = this.jQuery = jQuery.noConflict(true);
}
$.extend({
exclusive : function(arr) {
return $.grep(arr, function(v, k) {
return $.inArray(v, arr) === k;
});
},
mergeValues : function(a, b, c) {
var length = arguments.length;
if(length == 1 || typeof arguments[0] !== "object" || typeof arguments[1] !== "object") {
return arguments[0];
}
var args = jQuery.makeArray(arguments);
var i = 1;
var target = args[0];
for(; i < length; i++) {
var copy = args[i];
for(var name in copy) {
if(!target.hasOwnProperty(name)) {
target[name] = copy[name];
continue;
}
if(typeof target[name] == "object" && typeof copy[name] == "object") {
target[name] = jQuery.mergeValues(target[name], copy[name])
} else if(copy.hasOwnProperty(name) && copy[name] != undefined) {
target[name] = copy[name]
}
}
}
return target
},
decodeUrlParam: function(string) {
var str = string.split('?').pop().split('&');
var obj = {};
for(var i = 0; i < str.length; i++) {
var param = str[i].split('=');
if(param.length !== 2) {
continue;
}
obj[param[0]] = decodeURIComponent(param[1].replace(/\+/g, " "))
}
return obj
}
});
var events = (function() {
var _events = {};
var retEvents = function(id) {
var callbacks, topic = id && _events[ id ];
if(!topic) {
callbacks = $.Callbacks("");
topic = {
pub : callbacks.fire,
sub : callbacks.add,
unsub: callbacks.remove
};
if(id) {
_events[ id ] = topic;
}
}
return topic;
};
retEvents.scheduleAction = function(callback, time) {
return clearTimeout.bind(undefined, setTimeout(callback, time || 0));
};
retEvents.scheduleActionAtTime = function(callback, time) {
return retEvents.scheduleAction(callback, (time - $.now() > 0 ? time - $.now() : 0))
};
retEvents.scheduleActionAtInterval = function(callback, time) {
return clearInterval.bind(undefined, setInterval(callback, time));
};
return retEvents
})();
/***********************************************************************************************************************
* Globals
**********************************************************************************************************************/
var debug = false;
var log = false;
var timing = false;
if(!unsafeWindow) unsafeWindow = window;
/***********************************************************************************************************************
* Inject button into page before the page renders the YUI menu or it will not be animated (less work)
**********************************************************************************************************************/
$('.menu_slots > .expandable:last').after('<li class="expandable slot99 empire_Menu" onclick=""><div class="empire_Menu image" style="background-image: url(skin/minimized/weltinfo.png); background-position: 0px 0px; background-size:33px auto"></div></div><div class="name"><span class="namebox">Empire Overview</span></div></li>');
/***********************************************************************************************************************
* Utility Functions
**********************************************************************************************************************/
var Utils = {
wrapInClosure : function(obj) {
return (function(x) {
return function() {
return x
}
})(obj)
},
existsIn : function(input, test) {
try {
var ret = input.indexOf(test) !== -1
} catch(e) {
return false
}
return ret;
},
estimateTravelTime: function(city1, city2) {
if(!city1 || !city2) return 0;
if(city1[0] == city2[0] && city1[1] == city2[1]) {
var time = 1200 / 60 * 0.5;
} else {
time = 1200 / 60 * (Math.sqrt(Math.pow((city2[0] - city1[0]), 2) + Math.pow((city2[1] - city1[1]), 2)));
}
return Math.floor(time * 60 * 1000);
},
addStyleSheet : function(style) {
var getHead = document.getElementsByTagName("HEAD")[0];
var cssNode = window.document.createElement('style');
var elementStyle = getHead.appendChild(cssNode);
elementStyle.innerHTML = style;
return elementStyle;
},
escapeRegExp : function(str) {
return str.replace(/[\[\]\/\{\}\(\)\-\?\$\*\+\.\\\^\|]/g, "\\$&");
},
format : function(inputString, replacements) {
var str = '' + inputString;
var keys = Object.keys(replacements);
var i = keys.length;
while(i--) {
str = str.replace(new RegExp(this.escapeRegExp('{' + keys[i] + '}'), 'g'), replacements[keys[i]])
}
return str
},
cacheFunction : function(toExecute, expiry) {
expiry = expiry || 1000;
var cachedTime = $.now;
var cachedResult = undefined;
return function() {
if(cachedTime < $.now() - expiry || cachedResult === undefined) {
cachedResult = toExecute();
cachedTime = $.now()
}
return cachedResult
}
},
getClone : function($node){
if ($node.hasClass('ui-sortable-helper') || $node.parent().find('.ui-sortable-helper').length){
return $node;}
return $($node.get(0).cloneNode(true))
},
setClone : function($node, $clone){
if ($node.hasClass('ui-sortable-helper') || $node.parent().find('.ui-sortable-helper').length){
return $node;
}
$node.get(0).parentNode.replaceChild($clone.get(0), $node.get(0));
return $node
},
replaceNode : function(node, html) {
var t = node.cloneNode(false);
t.innerHTML = html;
node.parentNode.replaceChild(t, node);
return t
},
FormatTimeLengthToStr : function(timeString, precision, spacer) {
var lang = database.settings.languageChange.value;
timeString = timeString || 0;
precision = precision || 2;
spacer = spacer || " ";
if(!isFinite(timeString)) {
return ' \u221E ';
}
if(timeString < 0) timeString *= -1;
var factors = [];
var locStr = [];
var server = ikariam.Nationality();
factors.day = 86400;
factors.hour = 3600;
factors.minute = 60;
factors.second = 1;
locStr.day = Constant.LanguageData[lang].day;
locStr.hour = database.getGlobalData.getLocalisedString('h');
locStr.minute = database.getGlobalData.getLocalisedString('m');
locStr.second = database.getGlobalData.getLocalisedString('s');
if (server == 'ir' || server == 'ae') {
locStr.hour = database.getGlobalData.getLocalisedString('س');
locStr.minute = database.getGlobalData.getLocalisedString('د');
locStr.second = database.getGlobalData.getLocalisedString('ث');
}
timeString = Math.ceil(timeString / 1000);
var retString = "";
for(var fact in factors) {
var timeInSecs = Math.floor(timeString / factors[fact]);
if(isNaN(timeInSecs)) {
return retString;
}
if(precision > 0 && (timeInSecs > 0 || retString != "")) {
timeString = timeString - timeInSecs * factors[fact];
if(retString != "") {
retString += spacer;
}
retString += timeInSecs + locStr[fact];
precision--;
}
}
return retString;
},
FormatFullTimeToDateString: function (timeString, precise) {
var lang = database.settings.languageChange.value;
precise = precise || true;
timeString = timeString || 0;
var sInDay = 86400000;
var day = '';
var compDate = new Date(timeString);
if(precise) {
switch(Math.floor(compDate.getTime() / sInDay) - Math.floor($.now() / sInDay)) {
case 0 :
day = Constant.LanguageData[lang].today;
break;
case 1 :
day = Constant.LanguageData[lang].tomorrow;
break;
case -1 :
day = Constant.LanguageData[lang].yesterday;
break;
default :
day = (!isChrome ? compDate.toLocaleFormat('%a %d %b') : compDate.toString().split(' ').splice(0, 3).join(' ')) //Dienstag
}
}
if(day != '') {
day += ', '
}
return day + compDate.toLocaleTimeString();
},
FormatTimeToDateString: function (timeString) {
timeString = timeString || 0;
var compDate = new Date(timeString);
return compDate.toLocaleTimeString();
},
FormatRemainingTime : function(time, brackets) {
brackets = brackets || false;
var arrInTime = Utils.FormatTimeLengthToStr(time, 3, ' ');
return (arrInTime == '') ? '' : (brackets ? '(' : '') + arrInTime + (brackets ? ')' : '');
},
FormatNumToStr : function(inputNum, outputSign, precision) {
var lang = database.settings.languageChange.value;
precision = precision ? "10e" + (precision - 1) : 1;
var ret, val, sign, i, j;
var tho = Constant.LanguageData[lang].thousandSeperator;
var dec = Constant.LanguageData[lang].decimalPoint;
if(!isFinite(inputNum)) {
return '\u221E'
}
sign = inputNum > 0 ? 1 : inputNum === 0 ? 0 : -1;
if(sign) {
val = (( Math.floor(Math.abs(inputNum * precision)) / precision ) + '').split('.');
ret = val[1] != undefined ? [dec, val[1]] : [];
val = val[0].split('');
i = val.length;
j = 1;
while(i--) {
ret.unshift(val.pop());
if(i && j % 3 == 0) {
ret.unshift(tho)
}
j++
}
if(outputSign) {
ret.unshift(sign == 1 ? '+' : '-');
}
return ret.join('');
}
else return inputNum;
}
};
/***********************************************************************************************************************
* CLASSES
**********************************************************************************************************************/
function Movement(id, originCityId, targetCityId, arrivalTime, mission, loadingTime, resources, military, ships) {
if(typeof id === "object") {
this._id = id._id || null;
this._originCityId = id._originCityId || null;
this._targetCityId = id._targetCityId || null;
this._arrivalTime = id._arrivalTime || null;
this._mission = id._mission || null;
this._loadingTime = id._loadingTime || null;
this._resources = id._resources || {wood: 0, wine: 0, marble: 0, glass: 0, sulfur: 0, gold: 0};
this._military = id._military || new MilitaryUnits();
this._ships = id._ships || null;
this._updatedCity = id._updatedCity || false;
this._complete = id._complete || false;
this._updateTimer = id._updateTimer || null;
} else {
this._id = id || null;
this._originCityId = originCityId || null;
this._targetCityId = targetCityId || null;
this._arrivalTime = arrivalTime || null;
this._mission = mission || null;
this._loadingTime = loadingTime || null;
this._resources = resources || {wood: 0, wine: 0, marble: 0, glass: 0, sulfur: 0, gold: 0};
this._military = military || new MilitaryUnits();
this._ships = ships || null;
this._updatedCity = false;
this._complete = false;
this._updateTimer = null;
}
}
Movement.prototype = {
startUpdateTimer : function() {
this.clearUpdateTimer();
if(this.isCompleted) {
this.updateTransportComplete()
} else {
this._updateTimer = events.scheduleActionAtTime(this.updateTransportComplete.bind(this), this._arrivalTime + 1000)
}
},
clearUpdateTimer : function() {
var ret = !this._updateTimer || this._updateTimer();
this._updateTimer = null;
return ret
},
get getId() {
return this._id
},
get getOriginCityId() {
return this._originCityId
},
get getTargetCityId() {
return this._targetCityId
},
get getArrivalTime() {
return this._arrivalTime
},
get getMission() {
return this._mission
},
get getLoadingTime() {
return this._loadingTime - $.now()
},
get getResources() {
return this._resources
},
getResource : function(resourceName) {
return this._resources[resourceName]
},
get getMilitary() {
return this._military
},
get getShips() {
return this._ships
},
get isCompleted() {
return this._arrivalTime < $.now()
},
get isLoading() {
return this._loadingTime > $.now()
},
get getRemainingTime() {
return this._arrivalTime - $.now()
},
updateTransportComplete: function() {
if(this.isCompleted && !this._updatedCity) {
var city = database.getCityFromId(this._targetCityId);
var changes = [];
if(city) {
for(var resource in Constant.Resources) {
if(this.getResource(Constant.Resources[resource])) {
changes.push(Constant.Resources[resource])
}
city.getResource(Constant.Resources[resource]).increment(this.getResource(Constant.Resources[resource]));
}
this._updatedCity = true;
city = database.getCityFromId(this.originCityId);
if(city) {
city.updateActionPoints(city.getAvailableActions + 1)
}
if(changes.length) {
events(Constant.Events.MOVEMENTS_UPDATED).pub([this.getTargetCityId]);
events(Constant.Events.RESOURCES_UPDATED).pub(this.getTargetCityId, changes);
}
events.scheduleAction(function() {
database.getGlobalData.removeFleetMovement(this._id)
}.bind(this));
return true
}
} else if(this._updatedCity) {
events.scheduleAction(function() {
database.getGlobalData.removeFleetMovement(this._id)
}.bind(this))
}
return false;
}
};
function Resource(city, name) {
this._current = 0;
this._production = 0;
this._consumption = 0;
this._currentChangedDate = $.now();
this.city = Utils.wrapInClosure(city);
this._name = name;
return this
}
Resource.prototype = {
get name() {
return this._name
},
update : function(current, production, consumption) {
var changed = (current % this._current > 10) || (production != this._production) || (consumption != this._consumption);
this._current = current;
this._production = production;
this._consumption = consumption;
this._currentChangedDate = $.now();
return changed;
},
project : function() {
var limit = Math.floor($.now() / 1000);
var start = Math.floor(this._currentChangedDate / 1000);
while(limit > start) {
this._current += this._production;
if(Math.floor(start / 3600) != Math.floor((start + 1) / 3600))
if(this._current > this._consumption) {
this._current -= this._consumption
} else {
this.city().projectPopData(start * 1000);
this._consumption = 0;
}
start++
}
this._currentChangedDate = limit * 1000;
this.city().projectPopData(limit * 1000)
},
increment: function(amount) {
if(amount !== 0) {
this._current += amount;
return true;
}
return false;
},
get getEmptyTime() {
var net = this.getProduction * 3600 - this.getConsumption;
return (net < 0) ? this.getCurrent / net * -1 : Infinity;
},
get getFullTime() {
var net = this.getProduction * 3600 - this.getConsumption;
return (net > 0) ? (this.city().maxResourceCapacities.capacity - this.getCurrent) / net : 0;
},
get getCurrent() {
return Math.floor(this._current);
},
get getProduction() {
return this._production || 0
},
get getConsumption() {
return this._consumption || 0
}
};
function Military(city) {
this.city = Utils.wrapInClosure(city);
this._units = new MilitaryUnits();
this._advisorLastUpdate = 0;
this.armyTraining = [];
this._trainingTimer = null;
}
Military.prototype = {
init : function() {
this._trainingTimer = null;
this._startTrainingTimer()
},
_getTrainingTotals: function (){
var ret = {};
$.each(this.armyTraining, function(index, training) {
$.each(Constant.UnitData, function(unitId, info) {
ret[unitId] = ret[unitId]?ret[unitId]+(training.units[unitId]||0):training.units[unitId]||0
})
});
return ret
},
get getTrainingTotals() {
if(!this._trainingTotals) {
this._trainingTotals = Utils.cacheFunction(this._getTrainingTotals.bind(this), 1000)
}
return this._trainingTotals()
},
_getIncomingTotals :function (){
var ret = {};
$.each(this.city().getIncomingMilitary, function(index, element) {
for(var unitName in Constant.UnitData) {
ret[unitName] = ret[unitName] ? ret[unitName] + (element.getMilitary.totals[unitName]||0) : element.getMilitary.totals[unitName]||0
}
});
return ret
},
get getIncomingTotals() {
if(!this._incomingTotals) {
this._incomingTotals = Utils.cacheFunction(this._getIncomingTotals.bind(this), 1000)
}
return this._incomingTotals()
},
getTrainingForUnit : function(unit) {
var ret = [];
$.each(this.armyTraining, function(index, training) {
$.each(training.units, function(unitId, count) {
if(unitId === unit) {
ret.push({count: count, time: training.completionTime})
}
})
});
return ret
},
setTraining : function(trainingQueue) {
if(!trainingQueue.length) return false;
this._stopTrainingTimer();
var type = trainingQueue[0].type;
var changes = this._clearTrainingForType(type);
$.each(trainingQueue, function(index, training) {
this.armyTraining.push(training);
$.each(training.units, function(unitId, count) {
changes.push(unitId)
})
}.bind(this));
this.armyTraining.sort(function(a, b) {
return a.completionTime - b.completionTime
});
this._startTrainingTimer();
return $.exclusive(changes)
},
_clearTrainingForType: function(type) {
var oldTraining = this.armyTraining.filter(function(item) {
return item.type === type
});
this.armyTraining = this.armyTraining.filter(function(item) {
return item.type !== type
});
var changes = [];
$.each(oldTraining, function(index, training) {
$.each(training.units, function(unitId, count) {
changes.push(unitId)
})
});
return changes
},
_completeTraining : function() {
if(this.armyTraining.length) {
if(this.armyTraining[0].completionTime < $.now() + 5000) {
var changes = [];
var training = this.armyTraining.shift();
$.each(training.units, function(id, count) {
this.getUnits.addUnit(id, count);
changes.push(id)
}.bind(this));
if(changes.length)events(Constant.Events.MILITARY_UPDATED).pub(this.city().getId, changes)
}
}
this._startTrainingTimer()
},
_startTrainingTimer : function() {
this._stopTrainingTimer();
if(this.armyTraining.length) {
this._trainingTimer = events.scheduleActionAtTime(this._completeTraining.bind(this), this.armyTraining[0].completionTime)
}
},
_stopTrainingTimer : function() {
if(this._trainingTimer) {
this._trainingTimer()
}
this._trainingTimer = null
},
updateUnits : function(counts) {
var changes = [];
$.each(counts, function(unitId, count) {
if(this._units.setUnit(unitId, count)) {
changes.push(unitId)
}
}.bind(this));
return changes;
},
get getUnits() {
return this._units
}
};
function MilitaryUnits(obj) {
this._units = obj !== undefined ? obj._units: {};
}
MilitaryUnits.prototype = {
getUnit : function(unitId) {
return this._units[unitId] || 0
},
setUnit : function(unitId, count) {
var changed = this._units[unitId] != count;
this._units[unitId] = count;
return changed
},
get totals() {
return this._units
},
addUnit : function(unitId, count) {
return this.setUnit(unitId, this.getUnit(unitId) + count)
},
removeUnit: function(unitId, count) {
count = Math.max(0, this.getUnit[unitId] - count);
return this.setUnit(unitId, count)
}
};
function Building(city, pos) {
this._position = pos;
this._level = 0;
this._name = null;
this.city = Utils.wrapInClosure(city);
this._updateTimer = null
}
Building.prototype = {
startUpgradeTimer : function() {
if(this._updateTimer) {
this._updateTimer();
delete this._updateTimer
}
if(this._completionTime) {
if(this._completionTime - $.now() < 5000) {
this.completeUpgrade()
} else {
this._updateTimer = events.scheduleActionAtTime(this.completeUpgrade.bind(this), this._completionTime - 4000)
}
}
var statusPoll = function(a, b){
return events.scheduleActionAtInterval(function(){
if(a != this.isUpgradable || b != this.isUpgrading){
var changes = {position: this._position, name: this.getName, upgraded: this.isUpgrading != b}
events(Constant.Events.BUILDINGS_UPDATED).pub([changes]);
a = this.isUpgradable;
b = this.isUpgrading;
}
}.bind(this),3000)
}(this.isUpgradable,this.isUpgrading)
},
update : function(data) {
var changes;
var name = data.building.split(' ')[0];
var level = parseInt(data.level) || 0;
database.getGlobalData.addLocalisedString(name, data.name);
var completion = ('undefined' !== typeof data['completed']) ? parseInt(data['completed']) : 0;
var changed = (name !== this._name || level !== this._level || !!completion != this.isUpgrading);
if(changed) {
changes = {position: this._position, name: this.getName, upgraded: this.isUpgrading != !completion};
}
if(completion) {
this._completionTime = completion * 1000;
this.startUpgradeTimer()
} else if(this._completionTime) {
delete this._completionTime
}
this._name = name;
this._level = level;
if(changed) {
return changes;
}
return false;
},
get getUrlParams() {
return {
view : this.getName,
cityId : this.city().getId,
position: this.getPosition
};
},
get getUpgradeCost() {
var carpenter, architect, vineyard, fireworker, optician;
var level = this._level + this.isUpgrading;
if(this.isEmpty) {
return {
wood : Infinity,
glass : 0,
marble: 0,
sulfur: 0,
wine : 0,
time : 0
}
}
var time = Constant.BuildingData[this._name].time;
var bon = 1;
var bonTime = 1 + Constant.GovernmentData[database.getGlobalData.getGovernmentType].buildingTime;
bon -= database.getGlobalData.getResearchTopicLevel(Constant.Research.Economy.PULLEY) ? .02 : 0;
bon -= database.getGlobalData.getResearchTopicLevel(Constant.Research.Economy.GEOMETRY) ? .04 : 0;
bon -= database.getGlobalData.getResearchTopicLevel(Constant.Research.Economy.SPIRIT_LEVEL) ? .08 : 0;
return{
wood : Math.floor((Constant.BuildingData[this._name].wood[level] || 0) * (bon - (carpenter = this.city().getBuildingFromName(Constant.Buildings.CARPENTER), carpenter ? carpenter.getLevel / 100 : 0))),
wine : Math.floor((Constant.BuildingData[this._name].wine[level] || 0) * (bon - (vineyard = this.city().getBuildingFromName(Constant.Buildings.VINEYARD), vineyard ? vineyard.getLevel / 100 : 0))),
marble: Math.floor((Constant.BuildingData[this._name].marble[level] || 0) * (bon - (architect = this.city().getBuildingFromName(Constant.Buildings.ARCHITECT), architect ? architect.getLevel / 100 : 0))),
glass : Math.floor((Constant.BuildingData[this._name].glass[level] || 0) * (bon - (optician = this.city().getBuildingFromName(Constant.Buildings.OPTICIAN), optician ? optician.getLevel / 100 : 0))),
sulfur: Math.floor((Constant.BuildingData[this._name].sulfur[level] || 0) * (bon - (fireworker = this.city().getBuildingFromName(Constant.Buildings.FIREWORK_TEST_AREA), fireworker ? fireworker.getLevel / 100 : 0))),
time : Math.round(time.a / time.b * Math.pow(time.c, level + 1) - time.d) * 1000 * bonTime
}
},
get getName() {
return this._name
},
get getType() {
return Constant.BuildingData[this.getName].type
},
get getLevel() {
return this._level
},
get isEmpty() {
return this._name == 'buildingGround' || this._name == null
},
get isUpgrading() {
return (this._completionTime > $.now())
},
subtractUpgradeResourcesFromCity: function() {
var cost = this.getUpgradeCost;
$.each(Constant.Resources, function(key, resourceName) {
this.city().getResource(resourceName).increment(cost[resourceName] * -1)
}.bind(this));
this._completionTime = $.now() + cost.time;
},
get isUpgradable() {
if(this.isEmpty || this.isMaxLevel) {
return false
}
var cost = this.getUpgradeCost;
var upgradable = true;
$.each(Constant.Resources, function(key, value) {
upgradable = upgradable && (!cost[value] || cost[value] <= this.city().getResource(value).getCurrent);
}.bind(this));
return upgradable;
},
get getCompletionTime() {
return this._completionTime
},
get getCompletionDate() {
},
get isMaxLevel() {
return Constant.BuildingData[this.getName].maxLevel === (this.getLevel)
},
get getPosition() {
return this._position
},
completeUpgrade : function() {
this._level++;
delete this._completionTime;
delete this._updateTimer;
events(Constant.Events.BUILDINGS_UPDATED).pub(this.city().getId, [
{position: this._position, name: this.getName, upgraded: true}
])
}
};
function CityResearch(city) {
this._researchersLastUpdate = 0;
this._researchers = 0;
this._researchCostLastUpdate = 0;
this._researchCost = 0;
this.city = Utils.wrapInClosure(city);
}
CityResearch.prototype = {
updateResearchers: function(researchers) {
var changed = this._researchers !== researchers;
this._researchers = researchers;
this._researchersLastUpdate = $.now();
this._researchCost = this.getResearchCost;
return changed;
},
updateCost : function(cost) {
var changed = this._researchCost !== cost;
this._researchCost = cost;
this._researchCostLastUpdate = $.now();
this._researchers = this.getResearchers;
return changed;
},
get getResearchers() {
if(this._researchersLastUpdate < this._researchCostLastUpdate) {
return Math.floor(this._researchCost / this._researchCostModifier);
} else {
return this._researchers
}
},
get getResearch() {
return this.researchData.total
},
get researchData(){
if (!this._researchData){
this._researchData = Utils.cacheFunction(this.researchDataCached.bind(this),1000)
}
return this._researchData()
},
researchDataCached :function(){
var resBon = 0 + Constant.GovernmentData[database.getGlobalData.getGovernmentType].researchBonus
+ (database.getGlobalData.getResearchTopicLevel(Constant.Research.Science.PAPER) * 0.02)
+ (database.getGlobalData.getResearchTopicLevel(Constant.Research.Science.INK) * 0.04)
+ (database.getGlobalData.getResearchTopicLevel(Constant.Research.Science.MECHANICAL_PEN) * 0.08)
+ (database.getGlobalData.getResearchTopicLevel(Constant.Research.Science.SCIENTIFIC_FUTURE) * 0.02);
var premBon = database.getGlobalData.hasPremiumFeature(Constant.Premium.RESEARCH_POINTS_BONUS_EXTREME_LENGTH) ? (0 + Constant.PremiumData[Constant.Premium.RESEARCH_POINTS_BONUS_EXTREME_LENGTH].bonus) : database.getGlobalData.hasPremiumFeature(Constant.Premium.RESEARCH_POINTS_BONUS) ? (0 + Constant.PremiumData[Constant.Premium.RESEARCH_POINTS_BONUS].bonus) : 0;
var goods = Constant.GovernmentData[database.getGlobalData.getGovernmentType].researchPerCulturalGood * this.city()._culturalGoods;
var researchers = this.getResearchers;
var corruptionSpend = researchers * this.city().getCorruption;
var nonCorruptedResearchers = researchers * (1 - this.city().getCorruption);
var premiumResBonus = nonCorruptedResearchers * premBon;
var researchBonus = nonCorruptedResearchers * resBon;
var premiumGoodsBonus = goods * premBon;
var serverTyp = $('li.logout a[href="?view=normalServerStatus"]').text() ? 1 : 3;
return {
scientists: researchers,
researchBonus: researchBonus,
premiumScientistBonus: premiumResBonus,
premiumResearchBonus: (researchBonus* premBon),
culturalGoods: goods,
premiumCulturalGoodsBonus: premiumGoodsBonus,
corruption: corruptionSpend,
total: (nonCorruptedResearchers + researchBonus + premiumResBonus + goods + premiumGoodsBonus + (researchBonus* premBon))* serverTyp
}
},
get _researchCostModifier() {
return 6 + Constant.GovernmentData[database.getGlobalData.getGovernmentType].researcherCost - (database.getGlobalData.getResearchTopicLevel(Constant.Research.Science.LETTER_CHUTE) * 3)
},
get getResearchCost() {
return this.getResearchers * this._researchCostModifier;
}
};
function Changes(city, type, changes) {
this.city = city || null;
this.type = type || null;
this.changes = changes || [];
}
function Population(city) {
this._population = 0;
this._citizens = 0;
this._resourceWorkers = 0;
this._tradeWorkers = 0;
this._priests = 0;
this._culturalGoods = 0;
this._popChanged = $.now();
this._citizensChanged = $.now();
this._culturalGoodsChanged = $.now();
this._priestsChanged = $.now();
this.city = Utils.wrapInClosure(city)
}
Population.prototype = {
updatePopulationData: function(population, citizens, priests, culturalGoods) {
var changes = [];
if(population && population != this._population) {
changes.push({population: true});
this.population = population;
}
if(citizens && citizens != this._priests) {
changes.push({citizens: true});
this.citizens = citizens;
}
if(priests && priests != this._priests) {
changes.push({priests: true});
this.priests = priests;
}
},
updateWorkerData : function(resourceName, workers) {
},
updatePriests : function(newCount) {
},
updateCulturalGoods : function(newCount) {
},
get population() {
return this._population
},
set population(newVal) {
this._population = newVal;
this._popChanged = $.now()
},
get citizens() {
return this._citizens
},
set citizens(newVal) {
this._citizens = newVal;
this._citizensChanged = $.now()
},
get priests() {
return this._priests
},
set priests(newVal) {
this._priests = newVal;
this._priestsChanged = $.now()
}
};
function City(id) {
this._id = id || 0;
this._name = '';
this._resources = {
gold : new Resource(this, Constant.Resources.GOLD),
wood : new Resource(this, Constant.Resources.WOOD),
wine : new Resource(this, Constant.Resources.WINE),
marble: new Resource(this, Constant.Resources.MARBLE),
glass : new Resource(this, Constant.Resources.GLASS),
sulfur: new Resource(this, Constant.Resources.SULFUR)
};
this._capacities = {
capacity : 0,
safe : 0,
buildings: {
dump : {storage: 0, safe: 0},
warehouse: {storage: 0, safe: 0},
townHall : {storage: 2500, safe: 100}
},
invalid : true
};
this._tradeGoodID = 0;
this.knownTime = $.now();
this._